diff --git a/docs/developer/contributing/development-ci-metrics.asciidoc b/docs/developer/contributing/development-ci-metrics.asciidoc new file mode 100644 index 00000000000000..d4d54f1da7b8b6 --- /dev/null +++ b/docs/developer/contributing/development-ci-metrics.asciidoc @@ -0,0 +1,65 @@ +[[ci-metrics]] +== CI Metrics + +In addition to running our tests, CI collects metrics about the Kibana build. These metrics are sent to an external service to track changes over time, and to provide PR authors insights into the impact of their changes. + + +[[ci-metric-types]] +=== Metric types + + +[[ci-metric-types-bundle-size-metrics]] +==== Bundle size + +These metrics help contributors know how they are impacting the size of the bundles Kibana creates, and help make sure that Kibana loads as fast as possible. + +[[ci-metric-page-load-bundle-size]] `page load bundle size` :: +The size of the entry file produced for each bundle/plugin. This file is always loaded on every page load, so it should be as small as possible. To reduce this metric you can put any code that isn't necessary on every page load behind an https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports[`async import()`]. ++ +Code that is shared statically with other plugins will contribute to the `page load bundle size` of that plugin. This includes exports from the `public/index.ts` file and any file referenced by the `extraPublicDirs` manifest property. + +[[ci-metric-async-chunks-size]] `async chunks size` :: +An "async chunk" is created for the files imported by each https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports[`async import()`] statement. This metric tracks the sum size of these chunks, in bytes, broken down by plugin/bundle id. You can think of this as the amount of code users will have to download if they access all the components/applications within a bundle. + +[[ci-metric-misc-asset-size]] `miscellaneous assets size` :: +A "miscellaneous asset" is anything that isn't an async chunk or entry chunk, often images. This metric tracks the sum size of these assets, in bytes, broken down by plugin/bundle id. + +[[ci-metric-bundle-module-count]] `@kbn/optimizer bundle module count` :: +The number of separate modules included in each bundle/plugin. This is the best indicator we have for how long a specific bundle will take to be built by the `@kbn/optimizer`, so we report it to help people know when they've imported a module which might include a surprising number of sub-modules. + + +[[ci-metric-types-distributable-size]] +==== Distributable size + +The size of the Kibana distributable is an essential metric as it not only contributes to the time it takes to download, but it also impacts time it takes to extract the archive once downloaded. + +There are several metrics that we don't report on PRs because gzip-compression produces different file sizes even when provided the same input, so this metric would regularly show changes even though PR authors hadn't made any relevant changes. + +All metrics are collected from the `tar.gz` archive produced for the linux platform. + +[[ci-metric-distributable-file-count]] `distributable file count` :: +The number of files included in the default distributable. + +[[ci-metric-oss-distributable-file-count]] `oss distributable file count` :: +The number of files included in the OSS distributable. + +[[ci-metric-distributable-size]] `distributable size` :: +The size, in bytes, of the default distributable. _(not reported on PRs)_ + +[[ci-metric-oss-distributable-size]] `oss distributable size` :: +The size, in bytes, of the OSS distributable. _(not reported on PRs)_ + + +[[ci-metric-types-saved-object-field-counts]] +==== Saved Object field counts + +Elasticsearch limits the number of fields in an index to 1000 by default, and we want to avoid raising that limit. + +[[ci-metric-saved-object-field-count]] `Saved Objects .kibana field count` :: +The number of saved object fields broken down by saved object type. + + +[[ci-metric-adding-new-metrics]] +=== Adding new metrics + +You can report new metrics by using the `CiStatsReporter` class provided by the `@kbn/dev-utils` package. This class is automatically configured on CI and its methods noop when running outside of CI. For more details checkout the {kib-repo}blob/{branch}/packages/kbn-dev-utils/src/ci_stats_reporter[`CiStatsReporter` readme]. \ No newline at end of file diff --git a/docs/developer/contributing/index.asciidoc b/docs/developer/contributing/index.asciidoc index 99ab83bc2f073e..ecb37ffe9c97bf 100644 --- a/docs/developer/contributing/index.asciidoc +++ b/docs/developer/contributing/index.asciidoc @@ -9,6 +9,7 @@ Read <> to get your environment up and running, the * <> * <> * <> +* <> * <> * <> * <> @@ -78,6 +79,8 @@ include::development-tests.asciidoc[leveloffset=+1] include::interpreting-ci-failures.asciidoc[leveloffset=+1] +include::development-ci-metrics.asciidoc[leveloffset=+1] + include::development-documentation.asciidoc[leveloffset=+1] include::development-pull-request.asciidoc[leveloffset=+1] diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md new file mode 100644 index 00000000000000..7d29ced66afa84 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getIdsWithTitle](./kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md) + +## IndexPatternsService.getIdsWithTitle property + +Get list of index pattern ids with titles + +Signature: + +```typescript +getIdsWithTitle: (refresh?: boolean) => Promise>; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md index 0022bff34a8e76..af087344268d73 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md @@ -29,6 +29,7 @@ export declare class IndexPatternsService | [getFieldsForIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md) | | (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise<any> | Get field list by providing an index patttern (or spec) | | [getFieldsForWildcard](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md) | | (options?: GetFieldsOptions) => Promise<any> | Get field list by providing { pattern } | | [getIds](./kibana-plugin-plugins-data-public.indexpatternsservice.getids.md) | | (refresh?: boolean) => Promise<string[]> | Get list of index pattern ids | +| [getIdsWithTitle](./kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md) | | (refresh?: boolean) => Promise<Array<{
id: string;
title: string;
}>> | Get list of index pattern ids with titles | | [getTitles](./kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md) | | (refresh?: boolean) => Promise<string[]> | Get list of index pattern titles | | [refreshFields](./kibana-plugin-plugins-data-public.indexpatternsservice.refreshfields.md) | | (indexPattern: IndexPattern) => Promise<void> | Refresh field list for a given index pattern | | [savedObjectToSpec](./kibana-plugin-plugins-data-public.indexpatternsservice.savedobjecttospec.md) | | (savedObject: SavedObject<IndexPatternAttributes>) => IndexPatternSpec | Converts index pattern saved object to index pattern spec | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index accf46f534e89a..8625120d54848a 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -79,6 +79,7 @@ | [OptionedValueProp](./kibana-plugin-plugins-data-public.optionedvalueprop.md) | | | [QueryState](./kibana-plugin-plugins-data-public.querystate.md) | All query state service state | | [QueryStateChange](./kibana-plugin-plugins-data-public.querystatechange.md) | | +| [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) | | | [QuerySuggestionBasic](./kibana-plugin-plugins-data-public.querysuggestionbasic.md) | \* | | [QuerySuggestionField](./kibana-plugin-plugins-data-public.querysuggestionfield.md) | \* | | [QuerySuggestionGetFnArgs](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.md) | \* | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index e85747b8cc3d7d..aa7c3bb5d49323 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md new file mode 100644 index 00000000000000..5a41852001ac08 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [bubbleSubmitEvent](./kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md) + +## QueryStringInputProps.bubbleSubmitEvent property + +Signature: + +```typescript +bubbleSubmitEvent?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.classname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.classname.md new file mode 100644 index 00000000000000..7fa3b769771837 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.classname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [className](./kibana-plugin-plugins-data-public.querystringinputprops.classname.md) + +## QueryStringInputProps.className property + +Signature: + +```typescript +className?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md new file mode 100644 index 00000000000000..edaedf49f4b101 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [dataTestSubj](./kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md) + +## QueryStringInputProps.dataTestSubj property + +Signature: + +```typescript +dataTestSubj?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md new file mode 100644 index 00000000000000..cc4c6f606409e1 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [disableAutoFocus](./kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md) + +## QueryStringInputProps.disableAutoFocus property + +Signature: + +```typescript +disableAutoFocus?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md new file mode 100644 index 00000000000000..37831386960201 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [indexPatterns](./kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md) + +## QueryStringInputProps.indexPatterns property + +Signature: + +```typescript +indexPatterns: Array; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md new file mode 100644 index 00000000000000..a282ac3bc5049a --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [isInvalid](./kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md) + +## QueryStringInputProps.isInvalid property + +Signature: + +```typescript +isInvalid?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md new file mode 100644 index 00000000000000..d133a0930b53d7 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [languageSwitcherPopoverAnchorPosition](./kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md) + +## QueryStringInputProps.languageSwitcherPopoverAnchorPosition property + +Signature: + +```typescript +languageSwitcherPopoverAnchorPosition?: PopoverAnchorPosition; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.md new file mode 100644 index 00000000000000..d503980da7947f --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) + +## QueryStringInputProps interface + +Signature: + +```typescript +export interface QueryStringInputProps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [bubbleSubmitEvent](./kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md) | boolean | | +| [className](./kibana-plugin-plugins-data-public.querystringinputprops.classname.md) | string | | +| [dataTestSubj](./kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md) | string | | +| [disableAutoFocus](./kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md) | boolean | | +| [indexPatterns](./kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md) | Array<IIndexPattern | string> | | +| [isInvalid](./kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md) | boolean | | +| [languageSwitcherPopoverAnchorPosition](./kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md) | PopoverAnchorPosition | | +| [onBlur](./kibana-plugin-plugins-data-public.querystringinputprops.onblur.md) | () => void | | +| [onChange](./kibana-plugin-plugins-data-public.querystringinputprops.onchange.md) | (query: Query) => void | | +| [onChangeQueryInputFocus](./kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md) | (isFocused: boolean) => void | | +| [onSubmit](./kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md) | (query: Query) => void | | +| [persistedLog](./kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md) | PersistedLog | | +| [placeholder](./kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md) | string | | +| [prepend](./kibana-plugin-plugins-data-public.querystringinputprops.prepend.md) | any | | +| [query](./kibana-plugin-plugins-data-public.querystringinputprops.query.md) | Query | | +| [screenTitle](./kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md) | string | | +| [size](./kibana-plugin-plugins-data-public.querystringinputprops.size.md) | SuggestionsListSize | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onblur.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onblur.md new file mode 100644 index 00000000000000..10f2ae2ea4f146 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onblur.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onBlur](./kibana-plugin-plugins-data-public.querystringinputprops.onblur.md) + +## QueryStringInputProps.onBlur property + +Signature: + +```typescript +onBlur?: () => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchange.md new file mode 100644 index 00000000000000..fee44d7afd506f --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchange.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onChange](./kibana-plugin-plugins-data-public.querystringinputprops.onchange.md) + +## QueryStringInputProps.onChange property + +Signature: + +```typescript +onChange?: (query: Query) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md new file mode 100644 index 00000000000000..0421ae9c8bac5d --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onChangeQueryInputFocus](./kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md) + +## QueryStringInputProps.onChangeQueryInputFocus property + +Signature: + +```typescript +onChangeQueryInputFocus?: (isFocused: boolean) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md new file mode 100644 index 00000000000000..951ec7419485ff --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onSubmit](./kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md) + +## QueryStringInputProps.onSubmit property + +Signature: + +```typescript +onSubmit?: (query: Query) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md new file mode 100644 index 00000000000000..d1a8efb3640167 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [persistedLog](./kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md) + +## QueryStringInputProps.persistedLog property + +Signature: + +```typescript +persistedLog?: PersistedLog; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md new file mode 100644 index 00000000000000..31e41f4d552053 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [placeholder](./kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md) + +## QueryStringInputProps.placeholder property + +Signature: + +```typescript +placeholder?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.prepend.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.prepend.md new file mode 100644 index 00000000000000..7be882058d3fdc --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.prepend.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [prepend](./kibana-plugin-plugins-data-public.querystringinputprops.prepend.md) + +## QueryStringInputProps.prepend property + +Signature: + +```typescript +prepend?: any; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.query.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.query.md new file mode 100644 index 00000000000000..f15f6d082332b5 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.query.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [query](./kibana-plugin-plugins-data-public.querystringinputprops.query.md) + +## QueryStringInputProps.query property + +Signature: + +```typescript +query: Query; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md new file mode 100644 index 00000000000000..0c80252d74571b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [screenTitle](./kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md) + +## QueryStringInputProps.screenTitle property + +Signature: + +```typescript +screenTitle?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.size.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.size.md new file mode 100644 index 00000000000000..6b0e53a23e07be --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.size.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [size](./kibana-plugin-plugins-data-public.querystringinputprops.size.md) + +## QueryStringInputProps.size property + +Signature: + +```typescript +size?: SuggestionsListSize; +``` diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index ed20166c87f299..1bae04cc2e58b4 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -1,9 +1,10 @@ [[advanced-options]] == Advanced Settings -The *Advanced Settings* UI enables you to edit settings that control the behavior of Kibana. -For example, you can change the format used to display dates, specify the default index pattern, and set the precision -for displayed decimal values. +The *Advanced Settings* UI enables you to edit settings that control the +behavior of Kibana. For example, you can change the format used to display dates, +specify the default index pattern, and set the precision for displayed decimal +values. . Open the menu, then go to *Stack Management > {kib} > Advanced Settings*. . Scroll or search for the setting you want to modify. @@ -15,8 +16,9 @@ for displayed decimal values. [[settings-read-only-access]] === [xpack]#Read only access# When you have insufficient privileges to edit advanced settings, the following -indicator in Kibana will be displayed. The buttons to edit settings won't be visible. -For more information on granting access to Kibana see <>. +indicator in Kibana will be displayed. The buttons to edit settings won't be +visible. For more information on granting access to Kibana, see +<>. [role="screenshot"] image::images/settings-read-only-badge.png[Example of Advanced Settings Management's read only access indicator in Kibana's header] @@ -25,12 +27,11 @@ image::images/settings-read-only-badge.png[Example of Advanced Settings Manageme [[kibana-settings-reference]] === Kibana settings reference -WARNING: Modifying a setting can affect {kib} -performance and cause problems that are -difficult to diagnose. Setting a property value to a blank field reverts -to the default behavior, which might not be -compatible with other configuration settings. Deleting a custom setting -removes it from {kib} permanently. +WARNING: Modifying a setting can affect {kib} performance and cause problems +that are difficult to diagnose. Setting a property value to a blank field +reverts to the default behavior, which might not be compatible with other +configuration settings. Deleting a custom setting removes it from {kib} +permanently. [float] @@ -38,72 +39,159 @@ removes it from {kib} permanently. ==== General [horizontal] -`csv:quoteValues`:: Set this property to `true` to quote exported values. -`csv:separator`:: A string that serves as the separator for exported values. -`dateFormat`:: The format to use for displaying https://momentjs.com/docs/#/displaying/format/[pretty formatted dates]. -`dateFormat:dow`:: The day that a week should start on. -`dateFormat:scaled`:: The values that define the format to use to render ordered time-based data. Formatted timestamps must -adapt to the interval between measurements. Keys are http://en.wikipedia.org/wiki/ISO_8601#Time_intervals[ISO8601 intervals]. -`dateFormat:tz`:: The timezone that Kibana uses. The default value of `Browser` uses the timezone detected by the browser. -`dateNanosFormat`:: The format to use for displaying https://momentjs.com/docs/#/displaying/format/[pretty formatted dates] of {ref}/date_nanos.html[Elasticsearch date_nanos type]. -`defaultIndex`:: The index to access if no index is set. The default is `null`. -`defaultRoute`:: The default route when opening Kibana. Use this setting to route users to a specific dashboard, application, or saved object as they enter each space. -`fields:popularLimit`:: The top N most popular fields to show. -`filterEditor:suggestValues`:: Set this property to `false` to prevent the filter editor from suggesting values for fields. -`filters:pinnedByDefault`:: Set this property to `true` to make filters have a global state (be pinned) by default. -`format:bytes:defaultPattern`:: The default <> format for the "bytes" format. -`format:currency:defaultPattern`:: The default <> format for the "currency" format. -`format:defaultTypeMap`:: A map of the default format name for each field type. Field types that are not explicitly -mentioned use "\_default_". -`format:number:defaultLocale`:: The <> locale. -`format:number:defaultPattern`:: The <> for the "number" format. -`format:percent:defaultPattern`:: The <> for the "percent" format. -`histogram:barTarget`:: When date histograms use the `auto` interval, Kibana attempts to generate this number of bars. -`histogram:maxBars`:: Date histograms are not generated with more bars than the value of this property, scaling values -when necessary. -`history:limit`:: In fields that have history, such as query inputs, show this many recent values. -`indexPattern:placeholder`:: The default placeholder value to use in Management > Index Patterns > Create Index Pattern. -`metaFields`:: Fields that exist outside of `_source`. Kibana merges these fields -into the document when displaying it. -`metrics:max_buckets`:: The maximum numbers of buckets that a single -data source can return. This might arise when the user selects a -short interval (for example, 1s) for a long time period (1 year). -`pageNavigation`:: The style of navigation menu for Kibana. -Choices are Legacy, the legacy style where every plugin is represented in the nav, -and Modern, a new format that bundles related plugins together in flyaway nested navigation. -`query:allowLeadingWildcards`:: Allows a wildcard (*) as the first character -in a query clause. Only applies when experimental query features are -enabled in the query bar. To disallow leading wildcards in Lucene queries, -use `query:queryString:options`. -`query:queryString:options`:: Options for the Lucene query string parser. Only -used when "Query language" is set to Lucene. -`savedObjects:listingLimit`:: The number of objects to fetch for lists of saved objects. -The default value is 1000. Do not set above 10000. -`savedObjects:perPage`:: The number of objects to show on each page of the -list of saved objects. The default is 5. -`search:queryLanguage`:: The query language to use in the query bar. -Choices are <>, a language built specifically for {kib}, and the <>. -`shortDots:enable`:: Set this property to `true` to shorten long -field names in visualizations. For example, show `f.b.baz` instead of `foo.bar.baz`. -`sort:options`:: Options for the Elasticsearch {ref}/search-request-body.html#request-body-search-sort[sort] parameter. -`state:storeInSessionStorage`:: [experimental] Kibana tracks UI state in the -URL, which can lead to problems when there is a lot of state information, -and the URL gets very long. -Enabling this setting stores part of the URL in your browser session to keep the -URL short. -`theme:darkMode`:: Set to `true` to enable a dark mode for the {kib} UI. You must -refresh the page to apply the setting. -`timepicker:quickRanges`:: The list of ranges to show in the Quick section of -the time filter. This should be an array of objects, with each object containing -`from`, `to` (see {ref}/common-options.html#date-math[accepted formats]), -and `display` (the title to be displayed). -`timepicker:refreshIntervalDefaults`:: The default refresh interval for the time filter. Example: `{ "display": "15 seconds", "pause": true, "value": 15000 }`. -`timepicker:timeDefaults`:: The default selection in the time filter. -`truncate:maxHeight`:: The maximum height that a cell occupies in a table. Set to 0 to disable +[[csv-quotevalues]]`csv:quoteValues`:: +Set this property to `true` to quote exported values. + +[[csv-separator]]`csv:separator`:: +A string that serves as the separator for exported values. + +[[dateformat]]`dateFormat`:: +The format to use for displaying +https://momentjs.com/docs/#/displaying/format/[pretty formatted dates]. + +[[dateformat-dow]]`dateFormat:dow`:: +The day that a week should start on. + +[[dateformat-scaled]]`dateFormat:scaled`:: +The values that define the format to use to render ordered time-based data. +Formatted timestamps must adapt to the interval between measurements. Keys are +http://en.wikipedia.org/wiki/ISO_8601#Time_intervals[ISO8601 intervals]. + +[[dateformat-tz]]`dateFormat:tz`:: +The timezone that Kibana uses. The default value of `Browser` uses the timezone +detected by the browser. + +[[datenanosformat]]`dateNanosFormat`:: +The format to use for displaying +https://momentjs.com/docs/#/displaying/format/[pretty formatted dates] of +{ref}/date_nanos.html[Elasticsearch date_nanos type]. + +[[defaultindex]]`defaultIndex`:: +The index to access if no index is set. The default is `null`. + +[[defaultroute]]`defaultRoute`:: +The default route when opening Kibana. Use this setting to route users to a +specific dashboard, application, or saved object as they enter each space. + +[[fields-popularlimit]]`fields:popularLimit`:: +The top N most popular fields to show. + +[[filtereditor-suggestvalues]]`filterEditor:suggestValues`:: +Set this property to `false` to prevent the filter editor from suggesting values +for fields. + +[[filters-pinnedbydefault]]`filters:pinnedByDefault`:: +Set this property to `true` to make filters have a global state (be pinned) by +default. + +[[format-bytes-defaultpattern]]`format:bytes:defaultPattern`:: +The default <> format for the "bytes" format. + +[[format-currency-defaultpattern]]`format:currency:defaultPattern`:: +The default <> format for the "currency" format. + +[[format-defaulttypemap]]`format:defaultTypeMap`:: +A map of the default format name for each field type. Field types that are not +explicitly mentioned use "\_default_". + +[[format-number-defaultlocale]]`format:number:defaultLocale`:: +The <> locale. + +[[format-number-defaultpattern]]`format:number:defaultPattern`:: +The <> for the "number" format. + +[[format-percent-defaultpattern]]`format:percent:defaultPattern`:: +The <> for the "percent" format. + +[[histogram-bartarget]]`histogram:barTarget`:: +When date histograms use the `auto` interval, Kibana attempts to generate this +number of bars. + +[[histogram-maxbars]]`histogram:maxBars`:: +Date histograms are not generated with more bars than the value of this property, +scaling values when necessary. + +[[history-limit]]`history:limit`:: +In fields that have history, such as query inputs, show this many recent values. + +[[indexpattern-placeholder]]`indexPattern:placeholder`:: +The default placeholder value to use in +*Management > Index Patterns > Create Index Pattern*. + +[[metafields]]`metaFields`:: +Fields that exist outside of `_source`. Kibana merges these fields into the +document when displaying it. + +[[metrics-maxbuckets]]`metrics:max_buckets`:: +The maximum numbers of buckets that a single data source can return. This might +arise when the user selects a short interval (for example, 1s) for a long time +period (1 year). + +[[pagenavigation]]`pageNavigation`:: +The style of navigation menu for Kibana. Choices are Legacy, the legacy style +where every plugin is represented in the nav, and Modern, a new format that +bundles related plugins together in flyaway nested navigation. + +[[query-allowleadingwildcards]]`query:allowLeadingWildcards`:: +Allows a wildcard (*) as the first character in a query clause. Only applies +when experimental query features are enabled in the query bar. To disallow +leading wildcards in Lucene queries, use `query:queryString:options`. + +[[query-querystring-options]]`query:queryString:options`:: +Options for the Lucene query string parser. Only used when "Query language" is +set to Lucene. + +[[savedobjects-listinglimit]]`savedObjects:listingLimit`:: +The number of objects to fetch for lists of saved objects. The default value +is 1000. Do not set above 10000. + +[[savedobjects-perpage]]`savedObjects:perPage`:: +The number of objects to show on each page of the list of saved objects. The +default is 5. + +[[search-querylanguage]]`search:queryLanguage`:: +The query language to use in the query bar. Choices are <>, a +language built specifically for {kib}, and the +<>. + +[[shortdots-enable]]`shortDots:enable`:: +Set this property to `true` to shorten long field names in visualizations. For +example, show `f.b.baz` instead of `foo.bar.baz`. + +[[sort-options]]`sort:options`:: Options for the Elasticsearch +{ref}/search-request-body.html#request-body-search-sort[sort] parameter. + +[[state-storeinsessionstorage]]`state:storeInSessionStorage`:: +experimental:[] +Kibana tracks UI state in the URL, which can lead to problems +when there is a lot of state information, and the URL gets very long. Enabling +this setting stores part of the URL in your browser session to keep the URL +short. + +[[theme-darkmode]]`theme:darkMode`:: +Set to `true` to enable a dark mode for the {kib} UI. You must refresh the page +to apply the setting. + +[[timepicker-quickranges]]`timepicker:quickRanges`:: +The list of ranges to show in the Quick section of the time filter. This should +be an array of objects, with each object containing `from`, `to` (see +{ref}/common-options.html#date-math[accepted formats]), and `display` (the title +to be displayed). + +[[timepicker-refreshintervaldefaults]]`timepicker:refreshIntervalDefaults`:: +The default refresh interval for the time filter. Example: +`{ "display": "15 seconds", "pause": true, "value": 15000 }`. + +[[timepicker-timedefaults]]`timepicker:timeDefaults`:: +The default selection in the time filter. + +[[truncate-maxheight]]`truncate:maxHeight`:: +The maximum height that a cell occupies in a table. Set to 0 to disable truncation. -`xPack:defaultAdminEmail`:: Email address for X-Pack admin operations, such as -cluster alert notifications from Monitoring. + +[[xpack-defaultadminemail]]`xPack:defaultAdminEmail`:: +Email address for {xpack} admin operations, such as cluster alert notifications +from *{stack-monitor-app}*. [float] @@ -111,15 +199,17 @@ cluster alert notifications from Monitoring. ==== Accessibility [horizontal] -`accessibility:disableAnimations`:: Turns off all unnecessary animations in the -{kib} UI. Refresh the page to apply the changes. +[[accessibility-disableanimations]]`accessibility:disableAnimations`:: +Turns off all unnecessary animations in the {kib} UI. Refresh the page to apply +the changes. [float] [[kibana-dashboard-settings]] ==== Dashboard [horizontal] -`xpackDashboardMode:roles`:: **Deprecated. Use <> instead.** +[[xpackdashboardmode-roles]]`xpackDashboardMode:roles`:: +**Deprecated. Use <> instead.** The roles that belong to <>. [float] @@ -127,38 +217,63 @@ The roles that belong to <>. ==== Discover [horizontal] -`context:defaultSize`:: The number of surrounding entries to display in the context view. The default value is 5. -`context:step`:: The number by which to increment or decrement the context size. The default value is 5. -`context:tieBreakerFields`:: A comma-separated list of fields to use -for breaking a tie between documents that have the same timestamp value. The first -field that is present and sortable in the current index pattern is used. -`defaultColumns`:: The columns that appear by default on the Discover page. -The default is `_source`. -`discover:aggs:terms:size`:: The number terms that are visualized when clicking -the Visualize button in the field drop down. The default is `20`. -`discover:sampleSize`:: The number of rows to show in the Discover table. -`discover:sort:defaultOrder`:: The default sort direction for time-based index patterns. -`discover:searchOnPageLoad`:: Controls whether a search is executed when Discover first loads. -This setting does not have an effect when loading a saved search. -`doc_table:hideTimeColumn`:: Hides the "Time" column in Discover and in all saved searches on dashboards. -`doc_table:highlight`:: Highlights results in Discover and saved searches on dashboards. -Highlighting slows requests when -working on big documents. +[[context-defaultsize]]`context:defaultSize`:: +The number of surrounding entries to display in the context view. The default +value is 5. + +[[context-step]]`context:step`:: +The number by which to increment or decrement the context size. The default +value is 5. + +[[context-tiebreakerfields]]`context:tieBreakerFields`:: +A comma-separated list of fields to use for breaking a tie between documents +that have the same timestamp value. The first field that is present and sortable +in the current index pattern is used. + +[[defaultcolumns]]`defaultColumns`:: +The columns that appear by default on the *Discover* page. The default is +`_source`. + +[[discover-aggs-terms-size]]`discover:aggs:terms:size`:: +The number terms that are visualized when clicking the *Visualize* button in the +field drop down. The default is `20`. + +[[discover-samplesize]]`discover:sampleSize`:: +The number of rows to show in the *Discover* table. + +[[discover-sort-defaultorder]]`discover:sort:defaultOrder`:: +The default sort direction for time-based index patterns. + +[[discover-searchonpageload]]`discover:searchOnPageLoad`:: +Controls whether a search is executed when *Discover* first loads. This setting +does not have an effect when loading a saved search. + +[[doctable-hidetimecolumn]]`doc_table:hideTimeColumn`:: +Hides the "Time" column in *Discover* and in all saved searches on dashboards. + +[[doctable-highlight]]`doc_table:highlight`:: +Highlights results in *Discover* and saved searches on dashboards. Highlighting +slows requests when working on big documents. [float] [[kibana-ml-settings]] ==== Machine learning [horizontal] -`ml:anomalyDetection:results:enableTimeDefaults`:: Use the default time filter -in the *Single Metric Viewer* and *Anomaly Explorer*. If this setting is -disabled, the results for the full time range are shown. -`ml:anomalyDetection:results:timeDefaults`:: Sets the default time filter for -viewing {anomaly-job} results. This setting must contain `from` and `to` values (see {ref}/common-options.html#date-math[accepted formats]). It is ignored -unless `ml:anomalyDetection:results:enableTimeDefaults` is enabled. -`ml:fileDataVisualizerMaxFileSize`:: Sets the file size limit when importing -data in the {data-viz}. The default value is `100MB`. The highest supported -value for this setting is `1GB`. +[[ml-anomalydetection-results-enabletimedefaults]]`ml:anomalyDetection:results:enableTimeDefaults`:: +Use the default time filter in the *Single Metric Viewer* and +*Anomaly Explorer*. If this setting is disabled, the results for the full time +range are shown. + +[[ml-anomalydetection-results-timedefaults]]`ml:anomalyDetection:results:timeDefaults`:: +Sets the default time filter for viewing {anomaly-job} results. This setting +must contain `from` and `to` values (see +{ref}/common-options.html#date-math[accepted formats]). It is ignored unless +`ml:anomalyDetection:results:enableTimeDefaults` is enabled. + +[[ml-filedatavisualizermaxfilesize]]`ml:fileDataVisualizerMaxFileSize`:: +Sets the file size limit when importing data in the {data-viz}. The default +value is `100MB`. The highest supported value for this setting is `1GB`. [float] @@ -166,18 +281,26 @@ value for this setting is `1GB`. ==== Notifications [horizontal] -`notifications:banner`:: A custom banner intended for temporary notices to all users. -Supports https://help.github.com/en/articles/basic-writing-and-formatting-syntax[Markdown]. -`notifications:lifetime:banner`:: The duration, in milliseconds, for banner -notification displays. The default value is 3000000. Set this field to `Infinity` -to disable banner notifications. -`notifications:lifetime:error`:: The duration, in milliseconds, for error -notification displays. The default value is 300000. Set this field to `Infinity` to disable error notifications. -`notifications:lifetime:info`:: The duration, in milliseconds, for information notification displays. -The default value is 5000. Set this field to `Infinity` to disable information notifications. -`notifications:lifetime:warning`:: The duration, in milliseconds, for warning notification -displays. The default value is 10000. Set this field to `Infinity` to disable warning notifications. +[[notifications-banner]]`notifications:banner`:: +A custom banner intended for temporary notices to all users. Supports +https://help.github.com/en/articles/basic-writing-and-formatting-syntax[Markdown]. +[[notifications-lifetime-banner]]`notifications:lifetime:banner`:: +The duration, in milliseconds, for banner notification displays. The default +value is 3000000. Set this field to `Infinity` to disable banner notifications. + +[[notificatios-lifetime-error]]`notifications:lifetime:error`:: +The duration, in milliseconds, for error notification displays. The default +value is 300000. Set this field to `Infinity` to disable error notifications. + +[[notifications-lifetime-info]]`notifications:lifetime:info`:: +The duration, in milliseconds, for information notification displays. The +default value is 5000. Set this field to `Infinity` to disable information +notifications. + +[[notifications-lifetime-warning]]`notifications:lifetime:warning`:: +The duration, in milliseconds, for warning notification displays. The default +value is 10000. Set this field to `Infinity` to disable warning notifications. [float] @@ -185,7 +308,8 @@ displays. The default value is 10000. Set this field to `Infinity` to disable wa ==== Reporting [horizontal] -`xpackReporting:customPdfLogo`:: A custom image to use in the footer of the PDF. +[[xpackreporting-custompdflogo]]`xpackReporting:customPdfLogo`:: +A custom image to use in the footer of the PDF. [float] @@ -193,9 +317,10 @@ displays. The default value is 10000. Set this field to `Infinity` to disable wa ==== Rollup [horizontal] -`rollups:enableIndexPatterns`:: Enables the creation of index patterns that -capture rollup indices, which in turn enables visualizations based on rollup data. -Refresh the page to apply the changes. +[[rollups-enableindexpatterns]]`rollups:enableIndexPatterns`:: +Enables the creation of index patterns that capture rollup indices, which in +turn enables visualizations based on rollup data. Refresh the page to apply the +changes. [float] @@ -203,67 +328,117 @@ Refresh the page to apply the changes. ==== Search [horizontal] -`courier:batchSearches`:: **Deprecated in 7.6. Starting in 8.0, this setting will be optimized internally.** -When disabled, dashboard panels will load individually, and search requests will terminate when -users navigate away or update the query. When enabled, dashboard panels will load together when all of the data is loaded, -and searches will not terminate. -`courier:customRequestPreference`:: {ref}/search-request-body.html#request-body-search-preference[Request preference] +[[courier-batchsearches]]`courier:batchSearches`:: +**Deprecated in 7.6. Starting in 8.0, this setting will be optimized internally.** +When disabled, dashboard panels will load individually, and search requests will +terminate when users navigate away or update the query. When enabled, dashboard +panels will load together when all of the data is loaded, and searches will not +terminate. + +[[courier-customrequestpreference]]`courier:customRequestPreference`:: +{ref}/search-request-body.html#request-body-search-preference[Request preference] to use when `courier:setRequestPreference` is set to "custom". -`courier:ignoreFilterIfFieldNotInIndex`:: Skips filters that apply to fields that don't exist in the index for a visualization. -Useful when dashboards consist of visualizations from multiple index patterns. -`courier:maxConcurrentShardRequests`:: Controls the {ref}/search-multi-search.html[max_concurrent_shard_requests] + +[[courier-ignorefilteriffieldnotinindex]]`courier:ignoreFilterIfFieldNotInIndex`:: +Skips filters that apply to fields that don't exist in the index for a +visualization. Useful when dashboards consist of visualizations from multiple +index patterns. + +[[courier-maxconcurrentshardrequests]]`courier:maxConcurrentShardRequests`:: +Controls the {ref}/search-multi-search.html[max_concurrent_shard_requests] setting used for `_msearch` requests sent by {kib}. Set to 0 to disable this config and use the {es} default. -`courier:setRequestPreference`:: Enables you to set which shards handle your search requests. -* *Session ID:* Restricts operations to execute all search requests on the same shards. -This has the benefit of reusing shard caches across requests. -* *Custom:* Allows you to define your own preference. Use `courier:customRequestPreference` -to customize your preference value. + +[[courier-setrequestpreference]]`courier:setRequestPreference`:: +Enables you to set which shards handle your search requests. +* *Session ID:* Restricts operations to execute all search requests on the same +shards. This has the benefit of reusing shard caches across requests. +* *Custom:* Allows you to define your own preference. Use +`courier:customRequestPreference` to customize your preference value. * *None:* Do not set a preference. This might provide better performance because requests can be spread across all shard copies. However, results might be inconsistent because different shards might be in different refresh states. -`search:includeFrozen`:: Includes {ref}/frozen-indices.html[frozen indices] in results. -Searching through frozen indices -might increase the search time. This setting is off by default. Users must opt-in to include frozen indices. -`search:timeout`:: Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion. + +[[search-includefrozen]]`search:includeFrozen`:: +Includes {ref}/frozen-indices.html[frozen indices] in results. Searching through +frozen indices might increase the search time. This setting is off by default. +Users must opt-in to include frozen indices. + +[[search-timeout]]`search:timeout`:: Change the maximum timeout for a search +session or set to 0 to disable the timeout and allow queries to run to +completion. [float] [[kibana-siem-settings]] -==== Security Solution +==== Security solution [horizontal] -`securitySolution:defaultAnomalyScore`:: The threshold above which Machine Learning job anomalies are displayed in the Security app. -`securitySolution:defaultIndex`:: A comma-delimited list of Elasticsearch indices from which the Security app collects events. -`securitySolution:ipReputationLinks`:: A JSON array containing links for verifying the reputation of an IP address. The links are displayed on -{security-guide}/network-page-overview.html[IP detail] pages. -`securitySolution:enableNewsFeed`:: Enables the security news feed on the Security *Overview* -page. -`securitySolution:newsFeedUrl`:: The URL from which the security news feed content is -retrieved. -`securitySolution:refreshIntervalDefaults`:: The default refresh interval for the Security time filter, in milliseconds. -`securitySolution:timeDefaults`:: The default period of time in the Security time filter. +[[securitysolution-defaultanomalyscore]]`securitySolution:defaultAnomalyScore`:: +The threshold above which {ml} job anomalies are displayed in the {security-app}. + +[[securitysolution-defaultindex]]`securitySolution:defaultIndex`:: +A comma-delimited list of {es} indices from which the {security-app} collects +events. + +[[securitysolution-ipreputationlinks]]`securitySolution:ipReputationLinks`:: +A JSON array containing links for verifying the reputation of an IP address. The +links are displayed on {security-guide}/network-page-overview.html[IP detail] +pages. + +[[securitysolution-enablenewsfeed]]`securitySolution:enableNewsFeed`:: Enables +the security news feed on the Security *Overview* page. + +[[securitysolution-newsfeedurl]]`securitySolution:newsFeedUrl`:: +The URL from which the security news feed content is retrieved. + +[[securitysolution-refreshintervaldefaults]]`securitySolution:refreshIntervalDefaults`:: +The default refresh interval for the Security time filter, in milliseconds. + +[[securitysolution-timedefaults]]`securitySolution:timeDefaults`:: +The default period of time in the Security time filter. [float] [[kibana-timelion-settings]] ==== Timelion [horizontal] -`timelion:default_columns`:: The default number of columns to use on a Timelion sheet. -`timelion:default_rows`:: The default number of rows to use on a Timelion sheet. -`timelion:es.default_index`:: The default index when using the `.es()` query. -`timelion:es.timefield`:: The default field containing a timestamp when using the `.es()` query. -`timelion:graphite.url`:: [experimental] Used with graphite queries, this is the URL of your graphite host -in the form https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite. This URL can be -selected from an allow-list configured in the `kibana.yml` under `timelion.graphiteUrls`. -`timelion:max_buckets`:: The maximum number of buckets a single data source can return. -This value is used for calculating automatic intervals in visualizations. -`timelion:min_interval`:: The smallest interval to calculate when using "auto". -`timelion:quandl.key`:: [experimental] Used with quandl queries, this is your API key from https://www.quandl.com/[www.quandl.com]. -`timelion:showTutorial`:: Shows the Timelion tutorial -to users when they first open the Timelion app. -`timelion:target_buckets`:: Used for calculating automatic intervals in visualizations, -this is the number of buckets to try to represent. +[[timelion-defaultcolumns]]`timelion:default_columns`:: +The default number of columns to use on a Timelion sheet. + +[[timelion-defaultrows]]`timelion:default_rows`:: +The default number of rows to use on a Timelion sheet. + +[[timelion-esdefaultindex]]`timelion:es.default_index`:: +The default index when using the `.es()` query. + +[[timelion-estimefield]]`timelion:es.timefield`:: +The default field containing a timestamp when using the `.es()` query. + +[[timelion-graphite-url]]`timelion:graphite.url`:: +experimental:[] +Used with graphite queries, this is the URL of your graphite host +in the form https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite. This URL can +be selected from an allow-list configured in the `kibana.yml` under +`timelion.graphiteUrls`. + +[[timelion-maxbuckets]]`timelion:max_buckets`:: +The maximum number of buckets a single data source can return. This value is +used for calculating automatic intervals in visualizations. +[[timelion-mininterval]]`timelion:min_interval`:: +The smallest interval to calculate when using "auto". + +[[timelion-quandlkey]]`timelion:quandl.key`:: +experimental:[] +Used with quandl queries, this is your API key from +https://www.quandl.com/[www.quandl.com]. + +[[timelion-showtutorial]]`timelion:showTutorial`:: +Shows the Timelion tutorial to users when they first open the Timelion app. + +[[timelion-targetbuckets]]`timelion:target_buckets`:: +Used for calculating automatic intervals in visualizations, this is the number +of buckets to try to represent. [float] @@ -271,20 +446,32 @@ this is the number of buckets to try to represent. ==== Visualization [horizontal] -`visualization:colorMapping`:: Maps values to specified colors in visualizations. -`visualization:dimmingOpacity`:: The opacity of the chart items that are dimmed -when highlighting another element of the chart. The lower this number, the more -the highlighted element stands out. This must be a number between 0 and 1. -`visualization:loadingDelay`:: The time to wait before dimming visualizations -during a query. -`visualization:regionmap:showWarnings`:: Shows -a warning in a region map when terms cannot be joined to a shape. -`visualization:tileMap:WMSdefaults`:: The default properties for the WMS map server support in the coordinate map. -`visualization:tileMap:maxPrecision`:: The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, +[[visualization-colormapping]]`visualization:colorMapping`:: +Maps values to specified colors in visualizations. + +[[visualization-dimmingopacity]]`visualization:dimmingOpacity`:: +The opacity of the chart items that are dimmed when highlighting another element +of the chart. The lower this number, the more the highlighted element stands out. +This must be a number between 0 and 1. + +[[visualization-loadingdelay]]`visualization:loadingDelay`:: +The time to wait before dimming visualizations during a query. + +[[visualization-regionmap-showwarnings]]`visualization:regionmap:showWarnings`:: +Shows a warning in a region map when terms cannot be joined to a shape. + +[[visualization-tilemap-wmsdefaults]]`visualization:tileMap:WMSdefaults`:: +The default properties for the WMS map server support in the coordinate map. + +[[visualization-tilemap-maxprecision]]`visualization:tileMap:maxPrecision`:: +The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, and 12 is the maximum. See this {ref}/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator[explanation of cell dimensions]. -`visualize:enableLabs`:: Enables users to create, view, and edit experimental visualizations. -If disabled, only visualizations that are considered production-ready are available to the user. + +[[visualize-enablelabs]]`visualize:enableLabs`:: +Enables users to create, view, and edit experimental visualizations. If disabled, +only visualizations that are considered production-ready are available to the +user. [float] diff --git a/docs/management/images/add_remote_cluster.png b/docs/management/images/add_remote_cluster.png deleted file mode 100755 index 160d29b741c629..00000000000000 Binary files a/docs/management/images/add_remote_cluster.png and /dev/null differ diff --git a/docs/management/images/auto_follow_pattern.png b/docs/management/images/auto_follow_pattern.png deleted file mode 100755 index f80de9352280fb..00000000000000 Binary files a/docs/management/images/auto_follow_pattern.png and /dev/null differ diff --git a/docs/management/images/cross-cluster-replication-list-view.png b/docs/management/images/cross-cluster-replication-list-view.png deleted file mode 100755 index 4c45174cff7f12..00000000000000 Binary files a/docs/management/images/cross-cluster-replication-list-view.png and /dev/null differ diff --git a/docs/management/images/remote-clusters-list-view.png b/docs/management/images/remote-clusters-list-view.png deleted file mode 100755 index c28379863b74bf..00000000000000 Binary files a/docs/management/images/remote-clusters-list-view.png and /dev/null differ diff --git a/docs/management/managing-ccr.asciidoc b/docs/management/managing-ccr.asciidoc deleted file mode 100644 index 9c06e479e28b21..00000000000000 --- a/docs/management/managing-ccr.asciidoc +++ /dev/null @@ -1,80 +0,0 @@ -[role="xpack"] -[[managing-cross-cluster-replication]] -== Cross-Cluster Replication - -Use *Cross-Cluster Replication* to reproduce indices in -remote clusters on a local cluster. {ref}/xpack-ccr.html[Cross-cluster replication] -is commonly used to provide remote backups for disaster recovery and for -geo-proximite copies of data. - -To get started, open the menu, then go to *Stack Management > Data > Cross-Cluster Replication*. - -[role="screenshot"] -image::images/cross-cluster-replication-list-view.png[][Cross-cluster replication list view] - -[float] -=== Prerequisites - -* You must have a {ref}/modules-remote-clusters.html[remote cluster]. -* Leader indices must meet {ref}/ccr-requirements.html[these requirements]. -* The Elasticsearch version of the local cluster must be the same as or newer than the remote cluster. -Refer to {ref}/ccr-overview.html[this document] for more information. - -[float] -=== Required permissions - -The `manage` and `manage_ccr` cluster privileges are required to access *Cross-Cluster Replication*. - -You can add these privileges in *Stack Management > Security > Roles*. - -[float] -[[configure-replication]] -=== Configure replication - -Replication requires a leader index, the index being replicated, and a -follower index, which will contain the leader index's replicated data. -The follower index is passive in that it can read requests and searches, -but cannot accept direct writes. Only the leader index is active for direct writes. - -You can configure follower indices in two ways: - -* Create specific follower indices -* Create follower indices from an auto-follow pattern - -[float] -==== Create specific follower indices - -To replicate data from existing indices, or set up local followers on a case-by-case basis, -go to *Follower indices*. When you create the follower index, you must reference the -remote cluster and the leader index that you created in the remote cluster. - -[role="screenshot"] -image::images/follower_indices.png[][UI for adding follower indices] - -[float] -==== Create follower indices from an auto-follow pattern - -To automatically detect and follow new indices when they are created on a remote cluster, -go to *Auto-follow patterns*. Creating an auto-follow pattern is useful when you have -time series data, like event logs, on the remote cluster that is created or rolled over on a daily basis. - -When creating the pattern, you must reference the remote cluster that you -connected to your local cluster. You must also specify a collection of index patterns -that match the indices you want to automatically follow. - -Once you configure an -auto-follow pattern, any time a new index with a name that matches the pattern is -created in the remote cluster, a follower index is automatically configured in the local cluster. - -[role="screenshot"] -image::images/auto_follow_pattern.png[UI for adding an auto-follow pattern] - -[float] -[[manage-replication]] -=== Manage replication - -Use the list views in *Cross-Cluster Replication* to monitor whether the replication is active and -pause and resume replication. You can also edit and remove the follower indices and auto-follow patterns. - -For an example of cross-cluster replication, -refer to https://www.elastic.co/blog/bi-directional-replication-with-elasticsearch-cross-cluster-replication-ccr[Bi-directional replication with Elasticsearch cross-cluster replication]. diff --git a/docs/management/managing-remote-clusters.asciidoc b/docs/management/managing-remote-clusters.asciidoc deleted file mode 100644 index 92e0fa822b0567..00000000000000 --- a/docs/management/managing-remote-clusters.asciidoc +++ /dev/null @@ -1,50 +0,0 @@ -[[working-remote-clusters]] -== Remote Clusters - -Use *Remote Clusters* to establish a unidirectional -connection from your cluster to other clusters. This functionality is -required for {ref}/xpack-ccr.html[cross-cluster replication] and -{ref}/modules-cross-cluster-search.html[cross-cluster search]. - -To get started, open the menu, then go to *Stack Management > Data > Remote Clusters*. - -[role="screenshot"] -image::images/remote-clusters-list-view.png[Remote Clusters list view, including Add a remote cluster button] - -[float] -=== Required permissions - -The `manage` cluster privilege is required to access *Remote Clusters*. - -You can add this privilege in *Stack Management > Security > Roles*. - -[float] -[[managing-remote-clusters]] -=== Add a remote cluster - -A {ref}/modules-remote-clusters.html[remote cluster] connection works by configuring a remote cluster and -connecting to a limited number of nodes, called {ref}/modules-remote-clusters.html#sniff-mode[seed nodes], -in that cluster. -Alternatively, you can define a single proxy address for the remote cluster. - -By default, a cross-cluster request, such as a cross-cluster search or -replication request, fails if any cluster in the request is unavailable. -To skip a cluster when its unavailable, -set *Skip if unavailable* to true. - -Once you add a remote cluster, you can configure <> -to reproduce indices in the remote cluster on a local cluster. - -[role="screenshot"] -image::images/add_remote_cluster.png[][UI for adding a remote cluster] - -To create an index pattern to search across clusters, -use the same syntax that you’d use in a raw cross-cluster search request in {es}: :. -See <> for examples. - -[float] -[[manage-remote-clusters]] -=== Manage remote clusters - -From the *Remote Clusters* list view, you can drill down into each cluster and -view its status. You can also edit and delete a cluster. diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 42d1d89145d79c..5067bc08bec99e 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -100,3 +100,15 @@ This content has moved to the <> page. == TSVB This page was deleted. See <>. + +[role="exclude",id="managing-cross-cluster-replication"] +== Cross-Cluster Replication + +This content has moved. See +{ref}/ccr-getting-started.html[Set up cross-cluster replication]. + +[role="exclude",id="working-remote-clusters"] +== Remote clusters + +This content has moved. See +{ref}/ccr-getting-started.html#ccr-getting-started-remote-cluster[Connect to a remote cluster]. diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 7f48f21db71976..af68f3e5416286 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -54,7 +54,7 @@ overwritten by client-side headers, regardless of the |[[elasticsearch-hosts]] `elasticsearch.hosts:` | The URLs of the {es} instances to use for all your queries. All nodes listed here must be on the same cluster. *Default: `[ "http://localhost:9200" ]`* -+ + To enable SSL/TLS for outbound connections to {es}, use the `https` protocol in this setting. @@ -129,7 +129,7 @@ be set to `"required"` or `"optional"` to request a client certificate from [NOTE] ============ -These settings cannot be used in conjunction with +These settings cannot be used in conjunction with <>. ============ @@ -141,9 +141,9 @@ These settings cannot be used in conjunction with certificates, which make up a trusted certificate chain for {es}. This chain is used by {kib} to establish trust when making outbound SSL/TLS connections to {es}. -+ + In addition to this setting, trusted certificates may be specified via -<> and/or +<> and/or <>. | `elasticsearch.ssl.keyPassphrase:` @@ -157,7 +157,7 @@ corresponding private key. These are used by {kib} to authenticate itself when making outbound SSL/TLS connections to {es}. For this setting, you must also set the `xpack.security.http.ssl.client_authentication` setting in {es} to `"required"` or `"optional"` to request a client certificate from {kib}. -+ + If the keystore contains any additional certificates, they are used as a trusted certificate chain for {es}. This chain is used by {kib} to establish trust when making outbound SSL/TLS connections to {es}. In addition to this @@ -178,7 +178,7 @@ This setting cannot be used in conjunction with | `elasticsearch.ssl.keystore.password:` | The password that decrypts the keystore specified via -<>. If the keystore has no password, leave this +<>. If the keystore has no password, leave this as blank. If the keystore has an empty password, set this to `""`. @@ -187,14 +187,14 @@ as blank. If the keystore has an empty password, set this to authority (CA) certificates, which make up a trusted certificate chain for {es}. This chain is used by {kib} to establish trust when making outbound SSL/TLS connections to {es}. -+ + In addition to this setting, trusted certificates may be specified via <> and/or <>. |`elasticsearch.ssl.truststore.password:` | The password that decrypts the trust store specified via -<>. If the trust store +<>. If the trust store has no password, leave this as blank. If the trust store has an empty password, set this to `""`. | `elasticsearch.ssl.verificationMode:` @@ -300,15 +300,16 @@ the `polling` method could be used enabling that option. *Default: `false`* suppress all logging output. *Default: `false`* | `logging.timezone` - | Set to the canonical timezone ID -(for example, `America/Los_Angeles`) to log events using that timezone. For a -list of timezones, refer to https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. *Default: `UTC`* + | Set to the canonical time zone ID +(for example, `America/Los_Angeles`) to log events using that time zone. +For possible values, refer to +https://en.wikipedia.org/wiki/List_of_tz_database_time_zones[database time zones]. *Default: `UTC`* -| [[logging-verbose]] `logging.verbose:` {ece-icon} +| [[logging-verbose]] `logging.verbose:` {ess-icon} | Set to `true` to log all events, including system usage information and all requests. *Default: `false`* -| `map.includeElasticMapsService:` {ess-icon} +| [[regionmap-ES-map]] `map.includeElasticMapsService:` {ess-icon} | Set to `false` to disable connections to Elastic Maps Service. When `includeElasticMapsService` is turned off, only the vector layers configured by <> and the tile layer configured by <> are available in <>. *Default: `true`* @@ -317,7 +318,7 @@ and the tile layer configured by <> are availabl | Set to `true` to proxy all <> Elastic Maps Service requests through the {kib} server. *Default: `false`* -| [[regionmap-settings]] `map.regionmap:` {ess-icon} {ece-icon} +| [[regionmap-settings]] `map.regionmap:` {ess-icon} | Specifies additional vector layers for use in <> visualizations. Each layer object points to an external vector file that contains a geojson @@ -347,16 +348,10 @@ map.regionmap: [cols="2*<"] |=== -| [[regionmap-ES-map]] `map.includeElasticMapsService:` {ece-icon} - | Turns on or off whether layers from the Elastic Maps Service should be included in the vector -layer option list. By turning this off, -only the layers that are configured here will be included. The default is `true`. -This also affects whether tile-service from the Elastic Maps Service will be available. - -| [[regionmap-attribution]] `map.regionmap.layers[].attribution:` {ess-icon} {ece-icon} +| [[regionmap-attribution]] `map.regionmap.layers[].attribution:` {ess-icon} | Optional. References the originating source of the geojson file. -| [[regionmap-fields]] `map.regionmap.layers[].fields[]:` {ess-icon} {ece-icon} +| [[regionmap-fields]] `map.regionmap.layers[].fields[]:` {ess-icon} | Mandatory. Each layer can contain multiple fields to indicate what properties from the geojson features you wish to expose. The following shows how to define multiple @@ -382,11 +377,11 @@ map.regionmap: [cols="2*<"] |=== -| [[regionmap-field-description]] `map.regionmap.layers[].fields[].description:` {ess-icon} {ece-icon} +| [[regionmap-field-description]] `map.regionmap.layers[].fields[].description:` {ess-icon} | Mandatory. The human readable text that is shown under the Options tab when building the Region Map visualization. -| [[regionmap-field-name]] `map.regionmap.layers[].fields[].name:` {ess-icon} {ece-icon} +| [[regionmap-field-name]] `map.regionmap.layers[].fields[].name:` {ess-icon} | Mandatory. This value is used to do an inner-join between the document stored in {es} and the geojson file. For example, if the field in the geojson is @@ -394,30 +389,30 @@ called `Location` and has city names, there must be a field in {es} that holds the same values that {kib} can then use to lookup for the geoshape data. -| [[regionmap-name]] `map.regionmap.layers[].name:` {ess-icon} {ece-icon} +| [[regionmap-name]] `map.regionmap.layers[].name:` {ess-icon} | Mandatory. A description of the map being provided. -| [[regionmap-url]] `map.regionmap.layers[].url:` {ess-icon} {ece-icon} +| [[regionmap-url]] `map.regionmap.layers[].url:` {ess-icon} | Mandatory. The location of the geojson file as provided by a webserver. -| [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon} {ece-icon} +| [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon} | The map attribution string. *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* -| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` {ess-icon} {ece-icon} +| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` {ess-icon} | The maximum zoom level. *Default: `10`* -| [[tilemap-min-zoom]] `map.tilemap.options.minZoom:` {ess-icon} {ece-icon} +| [[tilemap-min-zoom]] `map.tilemap.options.minZoom:` {ess-icon} | The minimum zoom level. *Default: `1`* -| [[tilemap-subdomains]] `map.tilemap.options.subdomains:` {ess-icon} {ece-icon} +| [[tilemap-subdomains]] `map.tilemap.options.subdomains:` {ess-icon} | An array of subdomains used by the tile service. Specify the position of the subdomain the URL with the token `{s}`. -| [[tilemap-url]] `map.tilemap.url:` {ess-icon} {ece-icon} +| [[tilemap-url]] `map.tilemap.url:` {ess-icon} | The URL to the tileservice that {kib} uses to display map tiles in tilemap visualizations. By default, {kib} reads this URL from an external metadata service, but users can @@ -521,7 +516,7 @@ These settings cannot be used in conjunction with <> and/or <>. | `server.ssl.cipherSuites:` @@ -549,7 +544,7 @@ is optional, as the key may not be encrypted. keystore contains any additional certificates, those will be used as a trusted certificate chain for {kib}. All of these are used by {kib} to establish trust when receiving inbound SSL/TLS connections from end users. The certificate chain is also used by {kib} to verify client certificates from end users when PKI authentication is enabled. -+ + In addition to this setting, trusted certificates may be specified via <> and/or <>. @@ -571,7 +566,7 @@ keystore has no password, leave this unset. If the keystore has an empty passwor | Path to a PKCS#12 trust store that contains one or more X.509 certificate authority (CA) certificates which make up a trusted certificate chain for {kib}. This chain is used by {kib} to establish trust when receiving inbound SSL/TLS connections from end users. If PKI authentication is enabled, this chain is also used by {kib} to verify client certificates from end users. -+ + In addition to this setting, trusted certificates may be specified via <> and/or <>. diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index bc96463f6efbad..e0d550a15a907b 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -58,12 +58,12 @@ years of historical data in combination with your raw data. | {ref}/transforms.html[Transforms] |Use transforms to pivot existing {es} indices into summarized or entity-centric indices. -| <> +| {ref}/ccr-getting-started.html[Cross-Cluster Replication] |Replicate indices on a remote cluster and copy them to a follower index on a local cluster. This is important for disaster recovery. It also keeps data local for faster queries. -| <> +| {ref}/ccr-getting-started.html#ccr-getting-started-remote-cluster[Remote Clusters] |Manage your remote clusters for use with cross-cluster search and cross-cluster replication. You can add and remove remote clusters, and check their connectivity. |=== @@ -180,8 +180,6 @@ include::{kib-repo-dir}/management/alerting/connector-management.asciidoc[] include::{kib-repo-dir}/management/managing-beats.asciidoc[] -include::{kib-repo-dir}/management/managing-ccr.asciidoc[] - include::{kib-repo-dir}/management/index-lifecycle-policies/intro-to-lifecycle-policies.asciidoc[] include::{kib-repo-dir}/management/index-lifecycle-policies/create-policy.asciidoc[] @@ -200,8 +198,6 @@ include::{kib-repo-dir}/management/managing-licenses.asciidoc[] include::{kib-repo-dir}/management/numeral.asciidoc[] -include::{kib-repo-dir}/management/managing-remote-clusters.asciidoc[] - include::{kib-repo-dir}/management/rollups/create_and_manage_rollups.asciidoc[] include::{kib-repo-dir}/management/managing-saved-objects.asciidoc[] diff --git a/src/core/server/status/plugins_status.test.ts b/src/core/server/status/plugins_status.test.ts index a75dc8c283698d..176e2414a8d04b 100644 --- a/src/core/server/status/plugins_status.test.ts +++ b/src/core/server/status/plugins_status.test.ts @@ -161,13 +161,13 @@ describe('PluginStatusService', () => { }, b: { level: ServiceStatusLevels.degraded, - summary: '[2] services are degraded', + summary: '[savedObjects]: savedObjects degraded', detail: 'See the status page for more information', meta: expect.any(Object), }, c: { level: ServiceStatusLevels.degraded, - summary: '[3] services are degraded', + summary: '[savedObjects]: savedObjects degraded', detail: 'See the status page for more information', meta: expect.any(Object), }, @@ -186,13 +186,13 @@ describe('PluginStatusService', () => { }, b: { level: ServiceStatusLevels.critical, - summary: '[2] services are critical', + summary: '[elasticsearch]: elasticsearch critical', detail: 'See the status page for more information', meta: expect.any(Object), }, c: { level: ServiceStatusLevels.critical, - summary: '[3] services are critical', + summary: '[elasticsearch]: elasticsearch critical', detail: 'See the status page for more information', meta: expect.any(Object), }, diff --git a/src/core/server/status/plugins_status.ts b/src/core/server/status/plugins_status.ts index 113d59b327c11f..988f2d9969ccbf 100644 --- a/src/core/server/status/plugins_status.ts +++ b/src/core/server/status/plugins_status.ts @@ -33,7 +33,17 @@ interface Deps { export class PluginsStatusService { private readonly pluginStatuses = new Map>(); private readonly update$ = new BehaviorSubject(true); - constructor(private readonly deps: Deps) {} + private readonly defaultInheritedStatus$: Observable; + + constructor(private readonly deps: Deps) { + this.defaultInheritedStatus$ = this.deps.core$.pipe( + map((coreStatus) => { + return getSummaryStatus(Object.entries(coreStatus), { + allAvailableSummary: `All dependencies are available`, + }); + }) + ); + } public set(plugin: PluginName, status$: Observable) { this.pluginStatuses.set(plugin, status$); @@ -57,14 +67,24 @@ export class PluginsStatusService { } public getDerivedStatus$(plugin: PluginName): Observable { - return combineLatest([this.deps.core$, this.getDependenciesStatus$(plugin)]).pipe( - map(([coreStatus, pluginStatuses]) => { - return getSummaryStatus( - [...Object.entries(coreStatus), ...Object.entries(pluginStatuses)], - { - allAvailableSummary: `All dependencies are available`, - } - ); + return this.update$.pipe( + switchMap(() => { + // Only go up the dependency tree if any of this plugin's dependencies have a custom status + // Helps eliminate memory overhead of creating thousands of Observables unnecessarily. + if (this.anyCustomStatuses(plugin)) { + return combineLatest([this.deps.core$, this.getDependenciesStatus$(plugin)]).pipe( + map(([coreStatus, pluginStatuses]) => { + return getSummaryStatus( + [...Object.entries(coreStatus), ...Object.entries(pluginStatuses)], + { + allAvailableSummary: `All dependencies are available`, + } + ); + }) + ); + } else { + return this.defaultInheritedStatus$; + } }) ); } @@ -95,4 +115,17 @@ export class PluginsStatusService { }) ); } + + /** + * Determines whether or not this plugin or any plugin in it's dependency tree have a custom status registered. + */ + private anyCustomStatuses(plugin: PluginName): boolean { + if (this.pluginStatuses.get(plugin)) { + return true; + } + + return this.deps.pluginDependencies + .get(plugin)! + .reduce((acc, depName) => acc || this.anyCustomStatuses(depName), false as boolean); + } } diff --git a/src/core/server/status/status_service.ts b/src/core/server/status/status_service.ts index 9acf93f2f81977..62f226405e81a1 100644 --- a/src/core/server/status/status_service.ts +++ b/src/core/server/status/status_service.ts @@ -70,10 +70,10 @@ export class StatusService implements CoreService { const core$ = this.setupCoreStatus({ elasticsearch, savedObjects }); this.pluginsStatus = new PluginsStatusService({ core$, pluginDependencies }); - const overall$: Observable = combineLatest( + const overall$: Observable = combineLatest([ core$, - this.pluginsStatus.getAll$() - ).pipe( + this.pluginsStatus.getAll$(), + ]).pipe( // Prevent many emissions at once from dependency status resolution from making this too noisy debounceTime(500), map(([coreStatus, pluginsStatus]) => { diff --git a/src/plugins/dashboard/public/application/actions/library_notification_action.tsx b/src/plugins/dashboard/public/application/actions/library_notification_action.tsx index 974b55275ccc1d..bff0236c802f1f 100644 --- a/src/plugins/dashboard/public/application/actions/library_notification_action.tsx +++ b/src/plugins/dashboard/public/application/actions/library_notification_action.tsx @@ -79,6 +79,7 @@ export class LibraryNotificationAction implements ActionByType { return ( + embeddable.getRoot().isContainer && embeddable.getInput()?.viewMode !== ViewMode.VIEW && isReferenceOrValueEmbeddable(embeddable) && embeddable.inputIsRefType(embeddable.getInput()) diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index dd5eb1ee5ccaa4..e5b467a4181770 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -66,7 +66,6 @@ import { ViewMode, ContainerOutput, EmbeddableInput, - SavedObjectEmbeddableInput, } from '../../../embeddable/public'; import { NavAction, SavedDashboardPanel } from '../types'; @@ -178,7 +177,7 @@ export class DashboardAppController { chrome.docTitle.change(dash.title); } - const incomingEmbeddable = embeddable + let incomingEmbeddable = embeddable .getStateTransfer(scopedHistory()) .getIncomingEmbeddablePackage(); @@ -344,6 +343,22 @@ export class DashboardAppController { dashboardStateManager.getPanels().forEach((panel: SavedDashboardPanel) => { embeddablesMap[panel.panelIndex] = convertSavedDashboardPanelToPanelState(panel); }); + + // If the incoming embeddable state's id already exists in the embeddables map, replace the input, retaining the existing gridData for that panel. + if (incomingEmbeddable?.embeddableId && embeddablesMap[incomingEmbeddable.embeddableId]) { + const originalPanelState = embeddablesMap[incomingEmbeddable.embeddableId]; + embeddablesMap[incomingEmbeddable.embeddableId] = { + gridData: originalPanelState.gridData, + type: incomingEmbeddable.type, + explicitInput: { + ...originalPanelState.explicitInput, + ...incomingEmbeddable.input, + id: incomingEmbeddable.embeddableId, + }, + }; + incomingEmbeddable = undefined; + } + let expandedPanelId; if (dashboardContainer && !isErrorEmbeddable(dashboardContainer)) { expandedPanelId = dashboardContainer.getInput().expandedPanelId; @@ -482,32 +497,16 @@ export class DashboardAppController { refreshDashboardContainer(); }); - if (incomingEmbeddable) { - if ('id' in incomingEmbeddable) { - container.addOrUpdateEmbeddable( - incomingEmbeddable.type, - { - savedObjectId: incomingEmbeddable.id, - } - ); - } else if ('input' in incomingEmbeddable) { - const input = incomingEmbeddable.input; - // @ts-expect-error - delete input.id; - const explicitInput = { - savedVis: input, - }; - const embeddableId = - 'embeddableId' in incomingEmbeddable - ? incomingEmbeddable.embeddableId - : undefined; - container.addOrUpdateEmbeddable( - incomingEmbeddable.type, - // This ugly solution is temporary - https://github.com/elastic/kibana/pull/70272 fixes this whole section - (explicitInput as unknown) as EmbeddableInput, - embeddableId - ); - } + // If the incomingEmbeddable does not yet exist in the panels listing, create a new panel using the container's addEmbeddable method. + if ( + incomingEmbeddable && + (!incomingEmbeddable.embeddableId || + !container.getInput().panels[incomingEmbeddable.embeddableId]) + ) { + container.addNewEmbeddable( + incomingEmbeddable.type, + incomingEmbeddable.input + ); } } diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service_mock.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.mock.tsx similarity index 100% rename from src/plugins/dashboard/public/attribute_service/attribute_service_mock.tsx rename to src/plugins/dashboard/public/attribute_service/attribute_service.mock.tsx diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts index 06f380ca3862b6..ae8f034aec687c 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts @@ -18,7 +18,7 @@ */ import { ATTRIBUTE_SERVICE_KEY } from './attribute_service'; -import { mockAttributeService } from './attribute_service_mock'; +import { mockAttributeService } from './attribute_service.mock'; import { coreMock } from '../../../../core/public/mocks'; interface TestAttributes { diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 84df05154fb630..7499a6fced72ac 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -156,12 +156,8 @@ export class AttributeService< }; public getExplicitInputFromEmbeddable(embeddable: IEmbeddable): ValType | RefType { - return embeddable.getRoot() && - (embeddable.getRoot() as Container).getInput().panels[embeddable.id].explicitInput - ? ((embeddable.getRoot() as Container).getInput().panels[embeddable.id].explicitInput as - | ValType - | RefType) - : (embeddable.getInput() as ValType | RefType); + return ((embeddable.getRoot() as Container).getInput()?.panels?.[embeddable.id] + ?.explicitInput ?? embeddable.getInput()) as ValType | RefType; } getInputAsValueType = async (input: ValType | RefType): Promise => { @@ -204,7 +200,14 @@ export class AttributeService< const newAttributes = { ...input[ATTRIBUTE_SERVICE_KEY] }; newAttributes.title = props.newTitle; const wrappedInput = (await this.wrapAttributes(newAttributes, true)) as RefType; - resolve(wrappedInput); + + // Remove unneeded attributes from the original input. + delete (input as { [ATTRIBUTE_SERVICE_KEY]?: SavedObjectAttributes })[ + ATTRIBUTE_SERVICE_KEY + ]; + + // Combine input and wrapped input to preserve any passed in explicit Input. + resolve({ ...input, ...wrappedInput }); return { id: wrappedInput.savedObjectId }; } catch (error) { reject(error); diff --git a/src/plugins/dashboard/public/attribute_service/index.ts b/src/plugins/dashboard/public/attribute_service/index.ts new file mode 100644 index 00000000000000..84d4c8a13c31ed --- /dev/null +++ b/src/plugins/dashboard/public/attribute_service/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './attribute_service'; diff --git a/src/plugins/dashboard/public/index.ts b/src/plugins/dashboard/public/index.ts index e22d1f038a4560..315afd61c7c44e 100644 --- a/src/plugins/dashboard/public/index.ts +++ b/src/plugins/dashboard/public/index.ts @@ -31,7 +31,7 @@ export { } from './application'; export { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; -export { DashboardStart, DashboardUrlGenerator } from './plugin'; +export { DashboardStart, DashboardUrlGenerator, DashboardFeatureFlagConfig } from './plugin'; export { DASHBOARD_APP_URL_GENERATOR, createDashboardUrlGenerator, @@ -40,7 +40,7 @@ export { export { addEmbeddableToDashboardUrl } from './url_utils/url_helper'; export { SavedObjectDashboard } from './saved_dashboards'; export { SavedDashboardPanel } from './types'; -export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './attribute_service/attribute_service'; +export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './attribute_service'; export function plugin(initializerContext: PluginInitializerContext) { return new DashboardPlugin(initializerContext); diff --git a/src/plugins/dashboard/public/mocks.tsx b/src/plugins/dashboard/public/mocks.tsx index ba30d72594f2a1..07f29eca530425 100644 --- a/src/plugins/dashboard/public/mocks.tsx +++ b/src/plugins/dashboard/public/mocks.tsx @@ -20,6 +20,7 @@ import { DashboardStart } from './plugin'; export type Start = jest.Mocked; +export { mockAttributeService } from './attribute_service/attribute_service.mock'; const createStartContract = (): DashboardStart => { // @ts-ignore diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 5a45229a58a7d4..eadb3cd207e4dc 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -117,7 +117,7 @@ declare module '../../share/public' { export type DashboardUrlGenerator = UrlGeneratorContract; -interface DashboardFeatureFlagConfig { +export interface DashboardFeatureFlagConfig { allowByValueEmbeddables: boolean; } diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts index c56954ba6a29b3..eef8ef10ea7546 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts @@ -133,6 +133,25 @@ export class IndexPatternsService { return this.savedObjectsCache.map((obj) => obj?.attributes?.title); }; + /** + * Get list of index pattern ids with titles + * @param refresh Force refresh of index pattern list + */ + getIdsWithTitle = async ( + refresh: boolean = false + ): Promise> => { + if (!this.savedObjectsCache || refresh) { + await this.refreshSavedObjectsCache(); + } + if (!this.savedObjectsCache) { + return []; + } + return this.savedObjectsCache.map((obj) => ({ + id: obj?.id, + title: obj?.attributes?.title, + })); + }; + /** * Clear index pattern list cache * @param id optionally clear a single id diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 57865f05871a1a..f7dceffa9fdbc3 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -420,6 +420,7 @@ export { StatefulSearchBarProps, FilterBar, QueryStringInput, + QueryStringInputProps, IndexPatternSelect, } from './ui'; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 5919c1e294b2f2..28dfbf824470c2 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1381,6 +1381,10 @@ export class IndexPatternsService { // Warning: (ae-forgotten-export) The symbol "GetFieldsOptions" needs to be exported by the entry point index.d.ts getFieldsForWildcard: (options?: GetFieldsOptions) => Promise; getIds: (refresh?: boolean) => Promise; + getIdsWithTitle: (refresh?: boolean) => Promise>; getTitles: (refresh?: boolean) => Promise; refreshFields: (indexPattern: IndexPattern) => Promise; savedObjectToSpec: (savedObject: SavedObject) => IndexPatternSpec; @@ -1723,11 +1727,54 @@ export interface QueryStateChange extends QueryStateChangePartial { globalFilters?: boolean; } -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC; + +// Warning: (ae-missing-release-tag) "QueryStringInputProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface QueryStringInputProps { + // (undocumented) + bubbleSubmitEvent?: boolean; + // (undocumented) + className?: string; + // (undocumented) + dataTestSubj?: string; + // (undocumented) + disableAutoFocus?: boolean; + // (undocumented) + indexPatterns: Array; + // (undocumented) + isInvalid?: boolean; + // (undocumented) + languageSwitcherPopoverAnchorPosition?: PopoverAnchorPosition; + // (undocumented) + onBlur?: () => void; + // (undocumented) + onChange?: (query: Query) => void; + // (undocumented) + onChangeQueryInputFocus?: (isFocused: boolean) => void; + // (undocumented) + onSubmit?: (query: Query) => void; + // Warning: (ae-forgotten-export) The symbol "PersistedLog" needs to be exported by the entry point index.d.ts + // + // (undocumented) + persistedLog?: PersistedLog; + // (undocumented) + placeholder?: string; + // (undocumented) + prepend?: any; + // (undocumented) + query: Query; + // (undocumented) + screenTitle?: string; + // Warning: (ae-forgotten-export) The symbol "SuggestionsListSize" needs to be exported by the entry point index.d.ts + // + // (undocumented) + size?: SuggestionsListSize; +} // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; diff --git a/src/plugins/data/public/ui/index.ts b/src/plugins/data/public/ui/index.ts index 35b1bc50ddb1ef..299b9d2681578c 100644 --- a/src/plugins/data/public/ui/index.ts +++ b/src/plugins/data/public/ui/index.ts @@ -20,7 +20,7 @@ export { SuggestionsComponent } from './typeahead'; export { IndexPatternSelect } from './index_pattern_select'; export { FilterBar } from './filter_bar'; -export { QueryStringInput } from './query_string_input/query_string_input'; +export { QueryStringInput, QueryStringInputProps } from './query_string_input/query_string_input'; export { SearchBar, SearchBarProps, StatefulSearchBarProps } from './search_bar'; // @internal diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx index 8e1151b387fee7..0986ad0668c240 100644 --- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx @@ -46,8 +46,7 @@ import { PersistedLog, getQueryLog, matchPairs, toUser, fromUser } from '../../q import { SuggestionsListSize } from '../typeahead/suggestions_component'; import { SuggestionsComponent } from '..'; -interface Props { - kibana: KibanaReactContextValue; +export interface QueryStringInputProps { indexPatterns: Array; query: Query; disableAutoFocus?: boolean; @@ -67,6 +66,10 @@ interface Props { isInvalid?: boolean; } +interface Props extends QueryStringInputProps { + kibana: KibanaReactContextValue; +} + interface State { isSuggestionsVisible: boolean; index: number | null; @@ -687,4 +690,4 @@ export class QueryStringInputUI extends Component { } } -export const QueryStringInput = withKibana(QueryStringInputUI); +export const QueryStringInput: React.FC = withKibana(QueryStringInputUI); diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx b/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx index 8c3d7ab9c30d09..ba24913c6d1c02 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx @@ -18,7 +18,7 @@ */ import { EditPanelAction } from './edit_panel_action'; -import { Embeddable, EmbeddableInput } from '../embeddables'; +import { Embeddable, EmbeddableInput, SavedObjectEmbeddableInput } from '../embeddables'; import { ViewMode } from '../types'; import { ContactCardEmbeddable } from '../test_samples'; import { embeddablePluginMock } from '../../mocks'; @@ -53,20 +53,50 @@ test('is compatible when edit url is available, in edit mode and editable', asyn ).toBe(true); }); -test('redirects to app using state transfer', async () => { +test('redirects to app using state transfer with by value mode', async () => { applicationMock.currentAppId$ = of('superCoolCurrentApp'); const action = new EditPanelAction(getFactory, applicationMock, stateTransferMock); - const input = { id: '123', viewMode: ViewMode.EDIT }; - const embeddable = new EditableEmbeddable(input, true); + const embeddable = new EditableEmbeddable( + ({ + id: '123', + viewMode: ViewMode.EDIT, + coolInput1: 1, + coolInput2: 2, + } as unknown) as EmbeddableInput, + true + ); + embeddable.getOutput = jest.fn(() => ({ editApp: 'ultraVisualize', editPath: '/123' })); + await action.execute({ embeddable }); + expect(stateTransferMock.navigateToEditor).toHaveBeenCalledWith('ultraVisualize', { + path: '/123', + state: { + originatingApp: 'superCoolCurrentApp', + embeddableId: '123', + valueInput: { + id: '123', + viewMode: ViewMode.EDIT, + coolInput1: 1, + coolInput2: 2, + }, + }, + }); +}); + +test('redirects to app using state transfer without by value mode', async () => { + applicationMock.currentAppId$ = of('superCoolCurrentApp'); + const action = new EditPanelAction(getFactory, applicationMock, stateTransferMock); + const embeddable = new EditableEmbeddable( + { id: '123', viewMode: ViewMode.EDIT, savedObjectId: '1234' } as SavedObjectEmbeddableInput, + true + ); embeddable.getOutput = jest.fn(() => ({ editApp: 'ultraVisualize', editPath: '/123' })); await action.execute({ embeddable }); expect(stateTransferMock.navigateToEditor).toHaveBeenCalledWith('ultraVisualize', { path: '/123', state: { originatingApp: 'superCoolCurrentApp', - byValueMode: true, embeddableId: '123', - valueInput: input, + valueInput: undefined, }, }); }); diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts index 8d12ddd0299e7a..cbc28713197ba1 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts @@ -29,6 +29,8 @@ import { EmbeddableEditorState, EmbeddableStateTransfer, SavedObjectEmbeddableInput, + EmbeddableInput, + Container, } from '../..'; export const ACTION_EDIT_PANEL = 'editPanel'; @@ -118,8 +120,7 @@ export class EditPanelAction implements Action { const byValueMode = !(embeddable.getInput() as SavedObjectEmbeddableInput).savedObjectId; const state: EmbeddableEditorState = { originatingApp: this.currentAppId, - byValueMode, - valueInput: byValueMode ? embeddable.getInput() : undefined, + valueInput: byValueMode ? this.getExplicitInput({ embeddable }) : undefined, embeddableId: embeddable.id, }; return { app, path, state }; @@ -132,4 +133,11 @@ export class EditPanelAction implements Action { const editUrl = embeddable ? embeddable.getOutput().editUrl : undefined; return editUrl ? editUrl : ''; } + + private getExplicitInput({ embeddable }: ActionContext): EmbeddableInput { + return ( + (embeddable.getRoot() as Container)?.getInput()?.panels?.[embeddable.id]?.explicitInput ?? + embeddable.getInput() + ); + } } diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts index 38975cc220bc26..9f701f021162a1 100644 --- a/src/plugins/embeddable/public/lib/containers/container.ts +++ b/src/plugins/embeddable/public/lib/containers/container.ts @@ -199,8 +199,8 @@ export abstract class Container< return { type: factory.type, explicitInput: { - id: embeddableId, ...explicitInput, + id: embeddableId, } as TEmbeddableInput, }; } diff --git a/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx b/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx index 715827a72c61b9..17a2ac3b2a32b7 100644 --- a/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx @@ -17,43 +17,36 @@ * under the License. */ import React from 'react'; +import { wait } from '@testing-library/dom'; +import { cleanup, render } from '@testing-library/react/pure'; import { ErrorEmbeddable } from './error_embeddable'; import { EmbeddableRoot } from './embeddable_root'; -import { mount } from 'enzyme'; + +afterEach(cleanup); test('ErrorEmbeddable renders an embeddable', async () => { const embeddable = new ErrorEmbeddable('some error occurred', { id: '123', title: 'Error' }); - const component = mount(); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="embeddableStackError"]').length - ).toBe(1); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="errorMessageMarkdown"]').length - ).toBe(1); - expect( - component - .getDOMNode() - .querySelectorAll('[data-test-subj="errorMessageMarkdown"]')[0] - .innerHTML.includes('some error occurred') - ).toBe(true); + const { getByTestId, getByText } = render(); + + expect(getByTestId('embeddableStackError')).toBeVisible(); + await wait(() => getByTestId('errorMessageMarkdown')); // wait for lazy markdown component + expect(getByText(/some error occurred/i)).toBeVisible(); }); test('ErrorEmbeddable renders an embeddable with markdown message', async () => { const error = '[some link](http://localhost:5601/takeMeThere)'; const embeddable = new ErrorEmbeddable(error, { id: '123', title: 'Error' }); - const component = mount(); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="embeddableStackError"]').length - ).toBe(1); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="errorMessageMarkdown"]').length - ).toBe(1); - expect( - component - .getDOMNode() - .querySelectorAll('[data-test-subj="errorMessageMarkdown"]')[0] - .innerHTML.includes( - 'some link' - ) - ).toBe(true); + const { getByTestId, getByText } = render(); + + expect(getByTestId('embeddableStackError')).toBeVisible(); + await wait(() => getByTestId('errorMessageMarkdown')); // wait for lazy markdown component + expect(getByText(/some link/i)).toMatchInlineSnapshot(` + + some link + + `); }); diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts index ef79b18acd4f5b..4155cb4d3b60c7 100644 --- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts +++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts @@ -85,10 +85,10 @@ describe('embeddable state transfer', () => { it('can send an outgoing embeddable package state', async () => { await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, { - state: { type: 'coolestType', id: '150' }, + state: { type: 'coolestType', input: { savedObjectId: '150' } }, }); expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', { - state: { type: 'coolestType', id: '150' }, + state: { type: 'coolestType', input: { savedObjectId: '150' } }, }); }); @@ -96,12 +96,16 @@ describe('embeddable state transfer', () => { const historyMock = mockHistoryState({ kibanaIsNowForSports: 'extremeSportsKibana' }); stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock); await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, { - state: { type: 'coolestType', id: '150' }, + state: { type: 'coolestType', input: { savedObjectId: '150' } }, appendToExistingState: true, }); expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', { path: undefined, - state: { kibanaIsNowForSports: 'extremeSportsKibana', type: 'coolestType', id: '150' }, + state: { + kibanaIsNowForSports: 'extremeSportsKibana', + type: 'coolestType', + input: { savedObjectId: '150' }, + }, }); }); @@ -120,10 +124,13 @@ describe('embeddable state transfer', () => { }); it('can fetch an incoming embeddable package state', async () => { - const historyMock = mockHistoryState({ type: 'skisEmbeddable', id: '123' }); + const historyMock = mockHistoryState({ + type: 'skisEmbeddable', + input: { savedObjectId: '123' }, + }); stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock); const fetchedState = stateTransfer.getIncomingEmbeddablePackage(); - expect(fetchedState).toEqual({ type: 'skisEmbeddable', id: '123' }); + expect(fetchedState).toEqual({ type: 'skisEmbeddable', input: { savedObjectId: '123' } }); }); it('returns undefined when embeddable package is not in the right shape', async () => { @@ -136,12 +143,12 @@ describe('embeddable state transfer', () => { it('removes all keys in the keysToRemoveAfterFetch array', async () => { const historyMock = mockHistoryState({ type: 'skisEmbeddable', - id: '123', + input: { savedObjectId: '123' }, test1: 'test1', test2: 'test2', }); stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock); - stateTransfer.getIncomingEmbeddablePackage({ keysToRemoveAfterFetch: ['type', 'id'] }); + stateTransfer.getIncomingEmbeddablePackage({ keysToRemoveAfterFetch: ['type', 'input'] }); expect(historyMock.replace).toHaveBeenCalledWith( expect.objectContaining({ state: { test1: 'test1', test2: 'test2' } }) ); @@ -150,7 +157,7 @@ describe('embeddable state transfer', () => { it('leaves state as is when no keysToRemove are supplied', async () => { const historyMock = mockHistoryState({ type: 'skisEmbeddable', - id: '123', + input: { savedObjectId: '123' }, test1: 'test1', test2: 'test2', }); @@ -158,7 +165,7 @@ describe('embeddable state transfer', () => { stateTransfer.getIncomingEmbeddablePackage(); expect(historyMock.location.state).toEqual({ type: 'skisEmbeddable', - id: '123', + input: { savedObjectId: '123' }, test1: 'test1', test2: 'test2', }); diff --git a/src/plugins/embeddable/public/lib/state_transfer/types.ts b/src/plugins/embeddable/public/lib/state_transfer/types.ts index 3f3456d914728b..d8b4f4801bba3c 100644 --- a/src/plugins/embeddable/public/lib/state_transfer/types.ts +++ b/src/plugins/embeddable/public/lib/state_transfer/types.ts @@ -17,17 +17,17 @@ * under the License. */ -import { EmbeddableInput } from '..'; +import { Optional } from '@kbn/utility-types'; +import { EmbeddableInput, SavedObjectEmbeddableInput } from '..'; /** - * Represents a state package that contains the last active app id. + * A state package that contains information an editor will need to create or edit an embeddable then redirect back. * @public */ export interface EmbeddableEditorState { originatingApp: string; - byValueMode?: boolean; - valueInput?: EmbeddableInput; embeddableId?: string; + valueInput?: EmbeddableInput; } export function isEmbeddableEditorState(state: unknown): state is EmbeddableEditorState { @@ -35,32 +35,18 @@ export function isEmbeddableEditorState(state: unknown): state is EmbeddableEdit } /** - * Represents a state package that contains all fields necessary to create an embeddable by reference in a container. + * A state package that contains all fields necessary to create or update an embeddable by reference or by value in a container. * @public */ -export interface EmbeddablePackageByReferenceState { +export interface EmbeddablePackageState { type: string; - id: string; -} - -/** - * Represents a state package that contains all fields necessary to create an embeddable by value in a container. - * @public - */ -export interface EmbeddablePackageByValueState { - type: string; - input: EmbeddableInput; + input: Optional | Optional; embeddableId?: string; } -export type EmbeddablePackageState = - | EmbeddablePackageByReferenceState - | EmbeddablePackageByValueState; - export function isEmbeddablePackageState(state: unknown): state is EmbeddablePackageState { return ( - (ensureFieldOfTypeExists('type', state, 'string') && - ensureFieldOfTypeExists('id', state, 'string')) || + ensureFieldOfTypeExists('type', state, 'string') && ensureFieldOfTypeExists('input', state, 'object') ); } diff --git a/src/plugins/kibana_react/public/code_editor/code_editor.tsx b/src/plugins/kibana_react/public/code_editor/code_editor.tsx index f049085ccff61d..85b2c327e8b213 100644 --- a/src/plugins/kibana_react/public/code_editor/code_editor.tsx +++ b/src/plugins/kibana_react/public/code_editor/code_editor.tsx @@ -186,3 +186,7 @@ export class CodeEditor extends React.Component { } }; } + +// React.lazy requires default export +// eslint-disable-next-line import/no-default-export +export default CodeEditor; diff --git a/src/plugins/kibana_react/public/code_editor/index.tsx b/src/plugins/kibana_react/public/code_editor/index.tsx index 0ef83811d96d3d..63e3d330a1c526 100644 --- a/src/plugins/kibana_react/public/code_editor/index.tsx +++ b/src/plugins/kibana_react/public/code_editor/index.tsx @@ -17,11 +17,23 @@ * under the License. */ import React from 'react'; +import { EuiDelayRender, EuiLoadingContent } from '@elastic/eui'; import { useUiSetting } from '../ui_settings'; -import { CodeEditor as BaseEditor, Props } from './code_editor'; +import type { Props } from './code_editor'; + +const LazyBaseEditor = React.lazy(() => import('./code_editor')); + +const Fallback = () => ( + + + +); export const CodeEditor: React.FunctionComponent = (props) => { const darkMode = useUiSetting('theme:darkMode'); - - return ; + return ( + }> + + + ); }; diff --git a/src/plugins/kibana_react/public/markdown/index.tsx b/src/plugins/kibana_react/public/markdown/index.tsx index cacf223cf33ed3..4d6fd0b742ee40 100644 --- a/src/plugins/kibana_react/public/markdown/index.tsx +++ b/src/plugins/kibana_react/public/markdown/index.tsx @@ -17,5 +17,27 @@ * under the License. */ -export { MarkdownSimple } from './markdown_simple'; -export { Markdown } from './markdown'; +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import type { MarkdownSimpleProps } from './markdown_simple'; +import type { MarkdownProps } from './markdown'; + +const Fallback = () => ( + + + +); + +const LazyMarkdownSimple = React.lazy(() => import('./markdown_simple')); +export const MarkdownSimple = (props: MarkdownSimpleProps) => ( + }> + + +); + +const LazyMarkdown = React.lazy(() => import('./markdown')); +export const Markdown = (props: MarkdownProps) => ( + }> + + +); diff --git a/src/plugins/kibana_react/public/markdown/markdown.tsx b/src/plugins/kibana_react/public/markdown/markdown.tsx index 15d1c4931e60b4..8bb61bc71862e9 100644 --- a/src/plugins/kibana_react/public/markdown/markdown.tsx +++ b/src/plugins/kibana_react/public/markdown/markdown.tsx @@ -84,7 +84,7 @@ export const markdownFactory = memoize( } ); -interface MarkdownProps extends React.HTMLAttributes { +export interface MarkdownProps extends React.HTMLAttributes { className?: string; markdown?: string; openLinksInNewTab?: boolean; @@ -112,3 +112,7 @@ export class Markdown extends PureComponent { ); } } + +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default Markdown; diff --git a/src/plugins/kibana_react/public/markdown/markdown_simple.tsx b/src/plugins/kibana_react/public/markdown/markdown_simple.tsx index a5465fd1c6fc99..71ae4e031abca6 100644 --- a/src/plugins/kibana_react/public/markdown/markdown_simple.tsx +++ b/src/plugins/kibana_react/public/markdown/markdown_simple.tsx @@ -24,7 +24,7 @@ const markdownRenderers = { root: Fragment, }; -interface MarkdownSimpleProps { +export interface MarkdownSimpleProps { children: string; } @@ -32,3 +32,7 @@ interface MarkdownSimpleProps { export const MarkdownSimple = ({ children }: MarkdownSimpleProps) => ( {children} ); + +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default MarkdownSimple; diff --git a/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx b/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx index 2fa1debf51b5c3..e0e295723a69d2 100644 --- a/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx +++ b/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx @@ -556,3 +556,6 @@ class TableListView extends React.Component import('react-markdown')); +const ErrorRenderer = (props: { children: string }) => ( + }> + + +); + interface Mapping { [key: string]: string | { app: string; path: string }; } @@ -96,16 +103,7 @@ export function redirectWhenMissing({ defaultMessage: 'Saved object is missing', }), text: (element: HTMLElement) => { - ReactDOM.render( - - {error.message} - , - element - ); + ReactDOM.render({error.message}, element); return () => ReactDOM.unmountComponentAtNode(element); }, }); diff --git a/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx b/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx index ce08151d37c2c3..dfc0c4049774d9 100644 --- a/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx +++ b/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx @@ -33,6 +33,8 @@ interface SaveModalDocumentInfo { interface OriginSaveModalProps { originatingApp?: string; getAppNameFromId?: (appId: string) => string | undefined; + originatingAppName?: string; + returnToOriginSwitchLabel?: string; documentInfo: SaveModalDocumentInfo; objectType: string; onClose: () => void; @@ -73,11 +75,13 @@ export function SavedObjectSaveModalOrigin(props: OriginSaveModalProps) { setReturnToOriginMode(event.target.checked); }} label={ - + props.returnToOriginSwitchLabel ?? ( + + ) } /> diff --git a/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx b/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx index ff0cc89a5d9c90..6df205b21d910a 100644 --- a/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx @@ -18,11 +18,14 @@ */ import React from 'react'; -import { render, mount } from 'enzyme'; +import { wait } from '@testing-library/dom'; +import { render, cleanup } from '@testing-library/react/pure'; import { MarkdownVisWrapper } from './markdown_vis_controller'; +afterEach(cleanup); + describe('markdown vis controller', () => { - it('should set html from markdown params', () => { + it('should set html from markdown params', async () => { const vis = { params: { openLinksInNewTab: false, @@ -32,13 +35,22 @@ describe('markdown vis controller', () => { }, }; - const wrapper = render( + const { getByTestId, getByText } = render( ); - expect(wrapper.find('a').text()).toBe('markdown'); + + await wait(() => getByTestId('markdownBody')); + + expect(getByText('markdown')).toMatchInlineSnapshot(` + + markdown + + `); }); - it('should not render the html', () => { + it('should not render the html', async () => { const vis = { params: { openLinksInNewTab: false, @@ -47,13 +59,20 @@ describe('markdown vis controller', () => { }, }; - const wrapper = render( + const { getByTestId, getByText } = render( ); - expect(wrapper.text()).toBe('Testing html\n'); + + await wait(() => getByTestId('markdownBody')); + + expect(getByText(/testing/i)).toMatchInlineSnapshot(` +

+ Testing <a>html</a> +

+ `); }); - it('should update the HTML when render again with changed params', () => { + it('should update the HTML when render again with changed params', async () => { const vis = { params: { openLinksInNewTab: false, @@ -62,13 +81,20 @@ describe('markdown vis controller', () => { }, }; - const wrapper = mount( + const { getByTestId, getByText, rerender } = render( ); - expect(wrapper.text().trim()).toBe('Initial'); + + await wait(() => getByTestId('markdownBody')); + + expect(getByText(/initial/i)).toBeInTheDocument(); + vis.params.markdown = 'Updated'; - wrapper.setProps({ vis }); - expect(wrapper.text().trim()).toBe('Updated'); + rerender( + + ); + + expect(getByText(/Updated/i)).toBeInTheDocument(); }); describe('renderComplete', () => { @@ -86,56 +112,71 @@ describe('markdown vis controller', () => { renderComplete.mockClear(); }); - it('should be called on initial rendering', () => { - mount( + it('should be called on initial rendering', async () => { + const { getByTestId } = render( ); - expect(renderComplete.mock.calls.length).toBe(1); + + await wait(() => getByTestId('markdownBody')); + + expect(renderComplete).toHaveBeenCalledTimes(1); }); - it('should be called on successive render when params change', () => { - mount( + it('should be called on successive render when params change', async () => { + const { getByTestId, rerender } = render( ); - expect(renderComplete.mock.calls.length).toBe(1); + + await wait(() => getByTestId('markdownBody')); + + expect(renderComplete).toHaveBeenCalledTimes(1); + renderComplete.mockClear(); vis.params.markdown = 'changed'; - mount( + + rerender( ); - expect(renderComplete.mock.calls.length).toBe(1); + + expect(renderComplete).toHaveBeenCalledTimes(1); }); - it('should be called on successive render even without data change', () => { - mount( + it('should be called on successive render even without data change', async () => { + const { getByTestId, rerender } = render( ); - expect(renderComplete.mock.calls.length).toBe(1); + + await wait(() => getByTestId('markdownBody')); + + expect(renderComplete).toHaveBeenCalledTimes(1); + renderComplete.mockClear(); - mount( + + rerender( ); - expect(renderComplete.mock.calls.length).toBe(1); + + expect(renderComplete).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 18ae68ec40fe5c..c091d396b49244 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -243,12 +243,6 @@ export class VisualizeEmbeddable dirty = true; } - // propagate the title to the output embeddable - // but only when the visualization is in edit/Visualize mode - if (!this.parent && this.vis.title !== this.output.title) { - this.updateOutput({ title: this.vis.title }); - } - if (this.vis.description && this.domNode) { this.domNode.setAttribute('data-description', this.vis.description); } diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx index 1d01900ceffc28..a9bf6bd171f155 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -174,7 +174,9 @@ class NewVisModal extends React.Component void; originatingApp?: string; outsideVisualizeApp?: boolean; + createByValue?: boolean; } /** diff --git a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx index 0423e48bfb41ec..12720f3f22e7cf 100644 --- a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx +++ b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx @@ -21,8 +21,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { TopNavMenuData } from 'src/plugins/navigation/public'; -import uuid from 'uuid'; -import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../visualizations/public'; +import { VISUALIZE_EMBEDDABLE_TYPE, VisualizeInput } from '../../../../visualizations/public'; import { showSaveModal, SavedObjectSaveModalOrigin, @@ -122,7 +121,7 @@ export const getTopNavConfig = ( if (newlyCreated && stateTransfer) { stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { - state: { id, type: VISUALIZE_EMBEDDABLE_TYPE }, + state: { type: VISUALIZE_EMBEDDABLE_TYPE, input: { savedObjectId: id } }, }); } else { application.navigateToApp(originatingApp); @@ -167,15 +166,11 @@ export const getTopNavConfig = ( } const state = { input: { - ...vis.serialize(), - id: embeddableId ? embeddableId : uuid.v4(), - }, + savedVis: vis.serialize(), + } as VisualizeInput, + embeddableId, type: VISUALIZE_EMBEDDABLE_TYPE, - embeddableId: '', }; - if (embeddableId) { - state.embeddableId = embeddableId; - } stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { state }); }; @@ -267,6 +262,7 @@ export const getTopNavConfig = ( } const currentTitle = savedVis.title; savedVis.title = newTitle; + embeddableHandler.updateInput({ title: newTitle }); savedVis.copyOnSave = newCopyOnSave; savedVis.description = newDescription; const saveOptions = { @@ -282,6 +278,7 @@ export const getTopNavConfig = ( } return response; }; + const saveModal = ( { + // FLAKY: https://github.com/elastic/kibana/issues/39842 + describe.skip('inspect', () => { before(async () => { await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.load('discover'); diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/VisitorBreakdownChart.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/VisitorBreakdownChart.tsx index 34fcf62178711b..dea6525d4be5fe 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/VisitorBreakdownChart.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/VisitorBreakdownChart.tsx @@ -10,6 +10,7 @@ import { DARK_THEME, Datum, LIGHT_THEME, + PartialTheme, Partition, PartitionLayout, Settings, @@ -34,6 +35,12 @@ interface Props { loading: boolean; } +const theme: PartialTheme = { + legend: { + verticalWidth: 100, + }, +}; + export function VisitorBreakdownChart({ loading, options }: Props) { const [darkMode] = useUiSetting$('theme:darkMode'); @@ -42,13 +49,13 @@ export function VisitorBreakdownChart({ loading, options }: Props) { : EUI_CHARTS_THEME_LIGHT; return ( - + - - - + + + - - + + + + - - - + + + ); diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts b/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts index ef4f8b16e0e7b5..352a3ecdc3f12b 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts @@ -46,7 +46,7 @@ export async function getPageViewTrends({ terms: { field: breakdownItem.fieldName, size: 9, - missing: 'Other', + missing: 'Others', }, }, } @@ -103,7 +103,7 @@ export async function getPageViewTrends({ }); // Top 9 plus others, get a diff from parent bucket total if (bCount > top9Count) { - res.Other = bCount - top9Count; + res.Others = bCount - top9Count; } } diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts b/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts index 1b4388afd7c5d1..7345d6acc0f82b 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts @@ -12,7 +12,6 @@ import { SetupUIFilters, } from '../helpers/setup_request'; import { - USER_AGENT_DEVICE, USER_AGENT_NAME, USER_AGENT_OS, } from '../../../common/elasticsearch_fieldnames'; @@ -32,6 +31,7 @@ export async function getVisitorBreakdown({ const params = mergeProjection(projection, { body: { size: 0, + track_total_hits: true, query: { bool: projection.body.query.bool, }, @@ -39,19 +39,13 @@ export async function getVisitorBreakdown({ browsers: { terms: { field: USER_AGENT_NAME, - size: 10, + size: 9, }, }, os: { terms: { field: USER_AGENT_OS, - size: 10, - }, - }, - devices: { - terms: { - field: USER_AGENT_DEVICE, - size: 10, + size: 9, }, }, }, @@ -61,20 +55,42 @@ export async function getVisitorBreakdown({ const { apmEventClient } = setup; const response = await apmEventClient.search(params); - const { browsers, os, devices } = response.aggregations!; + const { browsers, os } = response.aggregations!; + + const totalItems = response.hits.total.value; + + const browserTotal = browsers.buckets.reduce( + (prevVal, item) => prevVal + item.doc_count, + 0 + ); + + const osTotal = os.buckets.reduce( + (prevVal, item) => prevVal + item.doc_count, + 0 + ); + + const browserItems = browsers.buckets.map((bucket) => ({ + count: bucket.doc_count, + name: bucket.key as string, + })); + + browserItems.push({ + count: totalItems - browserTotal, + name: 'Others', + }); + + const osItems = os.buckets.map((bucket) => ({ + count: bucket.doc_count, + name: bucket.key as string, + })); + + osItems.push({ + count: totalItems - osTotal, + name: 'Others', + }); return { - browsers: browsers.buckets.map((bucket) => ({ - count: bucket.doc_count, - name: bucket.key as string, - })), - os: os.buckets.map((bucket) => ({ - count: bucket.doc_count, - name: bucket.key as string, - })), - devices: devices.buckets.map((bucket) => ({ - count: bucket.doc_count, - name: bucket.key as string, - })), + os: osItems, + browsers: browserItems, }; } diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.test.ts index 33260b5c9303fb..df205dc742b073 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.test.ts @@ -49,4 +49,9 @@ describe('savedLens', () => { expect(expression.input.filters).toEqual(embeddableFilters); }); + + it('accepts an empty title when title is disabled', () => { + const expression = fn(null, { ...args, title: '' }, {} as any); + expect(expression.input.title).toEqual(''); + }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts index 49b8c5562af650..a823d0606d46f4 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts @@ -72,7 +72,7 @@ export function savedLens(): ExpressionFunctionDefinition< id: args.id, filters: getQueryFilters(filters), timeRange: args.timerange || defaultTimeRange, - title: args.title ? args.title : undefined, + title: args.title === null ? undefined : args.title, disableTriggers: true, }, embeddableType: EmbeddableTypes.lens, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts index ec640cfb5b299d..a64ff7da2aa196 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts @@ -93,7 +93,7 @@ export function savedMap(): ExpressionFunctionDefinition< mapCenter: center, hideFilterActions: true, - title: args.title ? args.title : undefined, + title: args.title === null ? undefined : args.title, isLayerTOCOpen: false, hiddenLayers: args.hideLayer || [], }, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.test.ts index a64fb167dd19f0..7902d09a0bdf1e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.test.ts @@ -36,6 +36,7 @@ describe('savedVisualization', () => { timerange: null, colors: null, hideLegend: null, + title: null, }; it('accepts null context', () => { @@ -50,4 +51,9 @@ describe('savedVisualization', () => { expect(expression.input.filters).toEqual(embeddableFilters); }); + + it('accepts an empty title when title is disabled', () => { + const expression = fn(null, { ...args, title: '' }, {} as any); + expect(expression.input.title).toEqual(''); + }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts index 2782ca039d7ed1..449be2db43d44f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts @@ -20,6 +20,7 @@ interface Arguments { timerange: TimeRangeArg | null; colors: SeriesStyle[] | null; hideLegend: boolean | null; + title: string | null; } type Output = EmbeddableExpression; @@ -61,9 +62,14 @@ export function savedVisualization(): ExpressionFunctionDefinition< help: argHelp.hideLegend, required: false, }, + title: { + types: ['string'], + help: argHelp.title, + required: false, + }, }, type: EmbeddableExpressionType, - fn: (input, { id, timerange, colors, hideLegend }) => { + fn: (input, { id, timerange, colors, hideLegend, title }) => { const filters = input ? input.and : []; const visOptions: VisualizeInput['vis'] = {}; @@ -90,6 +96,7 @@ export function savedVisualization(): ExpressionFunctionDefinition< timeRange: timerange || defaultTimeRange, filters: getQueryFilters(filters), vis: visOptions, + title: title === null ? undefined : title, }, embeddableType: EmbeddableTypes.visualization, generatedAt: Date.now(), diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts index 7bcfd6bef46208..0df39f281da9c3 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts @@ -52,4 +52,16 @@ describe('toExpression', () => { expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); }); + + it('includes empty panel title', () => { + const input: SavedLensInput = { + ...baseEmbeddableInput, + title: '', + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.chain[0].arguments).toHaveProperty('title', [input.title]); + }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts index 5bb45c5ca129e2..a8e200dd3e4ba0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts @@ -13,7 +13,7 @@ export function toExpression(input: SavedLensInput): string { expressionParts.push(`id="${input.id}"`); - if (input.title) { + if (input.title !== undefined) { expressionParts.push(`title="${input.title}"`); } diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts index d910c734a69740..d2c803a1ff2086 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts @@ -69,4 +69,16 @@ describe('toExpression', () => { expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); }); + + it('includes empty panel title', () => { + const input: MapEmbeddableInput = { + ...baseSavedMapInput, + title: '', + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.chain[0].arguments).toHaveProperty('title', [input.title]); + }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts index 111fdc71fa242b..769c2c9e10e9c4 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts @@ -12,7 +12,7 @@ export function toExpression(input: MapEmbeddableInput): string { expressionParts.push('savedMap'); expressionParts.push(`id="${input.id}"`); - if (input.title) { + if (input.title !== undefined) { expressionParts.push(`title="${input.title}"`); } diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts index 07f828755e46f2..4550a90ce98a28 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts @@ -69,4 +69,16 @@ describe('toExpression', () => { expect(aColor?.chain[0].arguments.color[0]).toBe(colorMap.a); expect(bColor?.chain[0].arguments.color[0]).toBe(colorMap.b); }); + + it('includes empty panel title', () => { + const input = { + ...baseInput, + title: '', + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.chain[0].arguments).toHaveProperty('title', [input.title]); + }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts index f03c10e2d424eb..a8adbf9d2d860a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts @@ -12,6 +12,10 @@ export function toExpression(input: VisualizeInput): string { expressionParts.push('savedVisualization'); expressionParts.push(`id="${input.id}"`); + if (input.title !== undefined) { + expressionParts.push(`title="${input.title}"`); + } + if (input.timeRange) { expressionParts.push( `timerange={timerange from="${input.timeRange.from}" to="${input.timeRange.to}"}` diff --git a/x-pack/plugins/canvas/i18n/functions/dict/saved_visualization.ts b/x-pack/plugins/canvas/i18n/functions/dict/saved_visualization.ts index e8cbddc5c11026..257e251fe2bc2e 100644 --- a/x-pack/plugins/canvas/i18n/functions/dict/saved_visualization.ts +++ b/x-pack/plugins/canvas/i18n/functions/dict/saved_visualization.ts @@ -29,5 +29,8 @@ export const help: FunctionHelp> = { defaultMessage: `Specifies the option to hide the legend`, } ), + title: i18n.translate('xpack.canvas.functions.savedVisualization.args.titleHelpText', { + defaultMessage: `The title for the visualization object`, + }), }, }; diff --git a/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot b/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot index 99d5dc3c115be1..5c17eb2b681373 100644 --- a/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot @@ -16,18 +16,7 @@ exports[`Storyshots components/ExpressionInput default 1`] = ` id="generated-id" onBlur={[Function]} onFocus={[Function]} - > -
-
-
+ />
diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts index f66235ff44c6aa..88a900f69c5ecf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts @@ -6,7 +6,7 @@ export { mockHistory, mockLocation } from './react_router_history.mock'; export { mockKibanaContext } from './kibana_context.mock'; -export { mockLicenseContext } from './license_context.mock'; +export { mockLicensingValues } from './licensing_logic.mock'; export { mockHttpValues } from './http_logic.mock'; export { mockFlashMessagesValues, mockFlashMessagesActions } from './flash_messages_logic.mock'; export { mockAllValues, mockAllActions, setMockValues } from './kea.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts index 8e6b0baa5fc00f..bad6beaa1652ee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts @@ -5,13 +5,17 @@ */ /** + * Combine all shared mock values/actions into a single obj + * * NOTE: These variable names MUST start with 'mock*' in order for * Jest to accept its use within a jest.mock() */ +import { mockLicensingValues } from './licensing_logic.mock'; import { mockHttpValues } from './http_logic.mock'; import { mockFlashMessagesValues, mockFlashMessagesActions } from './flash_messages_logic.mock'; export const mockAllValues = { + ...mockLicensingValues, ...mockHttpValues, ...mockFlashMessagesValues, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/license_context.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts similarity index 79% rename from x-pack/plugins/enterprise_search/public/applications/__mocks__/license_context.mock.ts rename to x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts index 7c37ecc7cde1b8..51b32e7a877b26 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/license_context.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts @@ -6,6 +6,8 @@ import { licensingMock } from '../../../../licensing/public/mocks'; -export const mockLicenseContext = { +export const mockLicensingValues = { license: licensingMock.createLicense(), + hasPlatinumLicense: false, + hasGoldLicense: false, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_context.mock.tsx b/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_context.mock.tsx index 5e56f17c8e7f31..646c3104c286fa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_context.mock.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/mount_with_context.mock.tsx @@ -15,8 +15,6 @@ import { getContext, resetContext } from 'kea'; import { I18nProvider } from '@kbn/i18n/react'; import { KibanaContext } from '../'; import { mockKibanaContext } from './kibana_context.mock'; -import { LicenseContext } from '../shared/licensing'; -import { mockLicenseContext } from './license_context.mock'; /** * This helper mounts a component with all the contexts/providers used @@ -34,9 +32,7 @@ export const mountWithContext = (children: React.ReactNode, context?: object) => return mount( - - {children} - + {children} ); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_usecontext.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_usecontext.mock.ts index 3a2193db646de4..df9e58994e36b4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_usecontext.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_usecontext.mock.ts @@ -9,11 +9,10 @@ * Jest to accept its use within a jest.mock() */ import { mockKibanaContext } from './kibana_context.mock'; -import { mockLicenseContext } from './license_context.mock'; jest.mock('react', () => ({ ...(jest.requireActual('react') as object), - useContext: jest.fn(() => ({ ...mockKibanaContext, ...mockLicenseContext })), + useContext: jest.fn(() => ({ ...mockKibanaContext })), useEffect: jest.fn((fn) => fn()), // Calls on mount/every update - use mount for more complex behavior })); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx index 928d92d7910940..44afce96c1a6c0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx @@ -82,9 +82,11 @@ describe('EngineOverview', () => { describe('when on a platinum license', () => { it('renders a 2nd meta engines table & makes a 2nd meta engines API call', async () => { - const wrapper = await mountWithAsyncContext(, { - license: { type: 'platinum', isActive: true }, + setMockValues({ + hasPlatinumLicense: true, + http: { ...mockHttpValues.http, get: mockApi }, }); + const wrapper = await mountWithAsyncContext(); expect(wrapper.find(EngineTable)).toHaveLength(2); expect(mockApi).toHaveBeenNthCalledWith(2, '/api/app_search/engines', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx index c0aedbe7dc6b42..0cb9ba106dbb82 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useValues } from 'kea'; import { EuiPageContent, @@ -19,7 +19,7 @@ import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chro import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { FlashMessages } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; -import { LicenseContext, ILicenseContext, hasPlatinumLicense } from '../../../shared/licensing'; +import { LicensingLogic } from '../../../shared/licensing'; import { EngineIcon } from './assets/engine_icon'; import { MetaEngineIcon } from './assets/meta_engine_icon'; @@ -40,7 +40,7 @@ interface ISetEnginesCallbacks { export const EngineOverview: React.FC = () => { const { http } = useValues(HttpLogic); - const { license } = useContext(LicenseContext) as ILicenseContext; + const { hasPlatinumLicense } = useValues(LicensingLogic); const [isLoading, setIsLoading] = useState(true); const [engines, setEngines] = useState([]); @@ -72,13 +72,13 @@ export const EngineOverview: React.FC = () => { }, [enginesPage]); useEffect(() => { - if (hasPlatinumLicense(license)) { + if (hasPlatinumLicense) { const params = { type: 'meta', pageIndex: metaEnginesPage }; const callbacks = { setResults: setMetaEngines, setResultsTotal: setMetaEnginesTotal }; setEnginesData(params, callbacks); } - }, [license, metaEnginesPage]); + }, [hasPlatinumLicense, metaEnginesPage]); if (isLoading) return ; if (!engines.length) return ; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx index f651511e61b440..35301af44b413d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx @@ -5,8 +5,9 @@ */ import '../../../__mocks__/kea.mock'; +import '../../../__mocks__/shallow_usecontext.mock'; -import React from 'react'; +import React, { useContext } from 'react'; import { shallow } from 'enzyme'; import { EuiCard } from '@elastic/eui'; @@ -26,6 +27,7 @@ describe('ProductCard', () => { }); it('renders an App Search card', () => { + (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } })); const wrapper = shallow(); const card = wrapper.find(EuiCard).dive().shallow(); @@ -34,13 +36,14 @@ describe('ProductCard', () => { const button = card.find(EuiButton); expect(button.prop('to')).toEqual('/app/enterprise_search/app_search'); - expect(button.prop('data-test-subj')).toEqual('LaunchAppSearchButton'); + expect(button.prop('children')).toEqual('Launch App Search'); button.simulate('click'); expect(sendTelemetry).toHaveBeenCalledWith(expect.objectContaining({ metric: 'app_search' })); }); it('renders a Workplace Search card', () => { + (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } })); const wrapper = shallow(); const card = wrapper.find(EuiCard).dive().shallow(); @@ -49,11 +52,21 @@ describe('ProductCard', () => { const button = card.find(EuiButton); expect(button.prop('to')).toEqual('/app/enterprise_search/workplace_search'); - expect(button.prop('data-test-subj')).toEqual('LaunchWorkplaceSearchButton'); + expect(button.prop('children')).toEqual('Launch Workplace Search'); button.simulate('click'); expect(sendTelemetry).toHaveBeenCalledWith( expect.objectContaining({ metric: 'workplace_search' }) ); }); + + it('renders correct button text when host not present', () => { + (useContext as jest.Mock).mockImplementation(() => ({ config: { host: '' } })); + + const wrapper = shallow(); + const card = wrapper.find(EuiCard).dive().shallow(); + const button = card.find(EuiButton); + + expect(button.prop('children')).toEqual('Setup Workplace Search'); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx index 833a782a32f008..482d68736af013 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.tsx @@ -4,13 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useContext } from 'react'; import { useValues } from 'kea'; -import upperFirst from 'lodash/upperFirst'; -import snakeCase from 'lodash/snakeCase'; +import { snakeCase } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiCard, EuiTextColor } from '@elastic/eui'; +import { KibanaContext, IKibanaContext } from '../../../index'; + import { EuiButton } from '../../../shared/react_router_helpers'; import { sendTelemetry } from '../../../shared/telemetry'; import { HttpLogic } from '../../../shared/http'; @@ -30,6 +31,25 @@ interface IProductCard { export const ProductCard: React.FC = ({ product, image }) => { const { http } = useValues(HttpLogic); + const { + config: { host }, + } = useContext(KibanaContext) as IKibanaContext; + + const LAUNCH_BUTTON_TEXT = i18n.translate( + 'xpack.enterpriseSearch.overview.productCard.launchButton', + { + defaultMessage: 'Launch {productName}', + values: { productName: product.NAME }, + } + ); + + const SETUP_BUTTON_TEXT = i18n.translate( + 'xpack.enterpriseSearch.overview.productCard.setupButton', + { + defaultMessage: 'Setup {productName}', + values: { productName: product.NAME }, + } + ); return ( = ({ product, image }) => { metric: snakeCase(product.ID), }) } - data-test-subj={`Launch${upperFirst(product.ID)}Button`} > - {i18n.translate('xpack.enterpriseSearch.overview.productCard.button', { - defaultMessage: `Launch {productName}`, - values: { productName: product.NAME }, - })} + {host ? LAUNCH_BUTTON_TEXT : SETUP_BUTTON_TEXT} } /> diff --git a/x-pack/plugins/security_solution/server/graphql/overview/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/index.ts similarity index 70% rename from x-pack/plugins/security_solution/server/graphql/overview/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/index.ts index 58cf182ccd9766..b67d130cd68f0d 100644 --- a/x-pack/plugins/security_solution/server/graphql/overview/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { createOverviewResolvers } from './resolvers'; -export { overviewSchema } from './schema.gql'; +export { ProductSelector } from './product_selector'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx new file mode 100644 index 00000000000000..44efa57db897ff --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx @@ -0,0 +1,54 @@ +/* + * 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 '../../../__mocks__/shallow_usecontext.mock'; + +import React, { useContext } from 'react'; +import { shallow } from 'enzyme'; +import { EuiPage } from '@elastic/eui'; + +import { ProductSelector } from './'; +import { ProductCard } from '../product_card'; + +describe('ProductSelector', () => { + it('renders the overview page and product cards with no host set', () => { + (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: '' } })); + const wrapper = shallow(); + + expect(wrapper.find(EuiPage).hasClass('enterpriseSearchOverview')).toBe(true); + expect(wrapper.find(ProductCard)).toHaveLength(2); + }); + + describe('access checks when host is set', () => { + beforeEach(() => { + (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } })); + }); + + it('does not render the App Search card if the user does not have access to AS', () => { + const wrapper = shallow( + + ); + + expect(wrapper.find(ProductCard)).toHaveLength(1); + expect(wrapper.find(ProductCard).prop('product').ID).toEqual('workplaceSearch'); + }); + + it('does not render the Workplace Search card if the user does not have access to WS', () => { + const wrapper = shallow( + + ); + + expect(wrapper.find(ProductCard)).toHaveLength(1); + expect(wrapper.find(ProductCard).prop('product').ID).toEqual('appSearch'); + }); + + it('does not render any cards if the user does not have access', () => { + const wrapper = shallow(); + + expect(wrapper.find(ProductCard)).toHaveLength(0); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx new file mode 100644 index 00000000000000..07b8d4b9926d7f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx @@ -0,0 +1,97 @@ +/* + * 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. + */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useContext } from 'react'; + +import { + EuiPage, + EuiPageBody, + EuiPageHeader, + EuiPageHeaderSection, + EuiPageContentBody, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { KibanaContext, IKibanaContext } from '../../../index'; + +import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; + +import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; + +import { ProductCard } from '../product_card'; + +import AppSearchImage from '../../assets/app_search.png'; +import WorkplaceSearchImage from '../../assets/workplace_search.png'; + +interface IProductSelectorProps { + access: { + hasAppSearchAccess?: boolean; + hasWorkplaceSearchAccess?: boolean; + }; +} + +export const ProductSelector: React.FC = ({ access }) => { + const { hasAppSearchAccess, hasWorkplaceSearchAccess } = access; + const { + config: { host }, + } = useContext(KibanaContext) as IKibanaContext; + + const shouldShowAppSearchCard = !host || hasAppSearchAccess; + const shouldShowWorkplaceSearchCard = !host || hasWorkplaceSearchAccess; + + return ( + + + + + + + + +

+ {i18n.translate('xpack.enterpriseSearch.overview.heading', { + defaultMessage: 'Welcome to Elastic Enterprise Search', + })} +

+
+ +

+ {i18n.translate('xpack.enterpriseSearch.overview.subheading', { + defaultMessage: 'Select a product to get started', + })} +

+
+
+
+ + + {shouldShowAppSearchCard && ( + + + + )} + {shouldShowWorkplaceSearchCard && ( + + + + )} + + + +
+
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/assets/getting_started.png b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/assets/getting_started.png new file mode 100644 index 00000000000000..f0fcb432c29e1b Binary files /dev/null and b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/assets/getting_started.png differ diff --git a/x-pack/plugins/security_solution/server/graphql/ip_details/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts similarity index 69% rename from x-pack/plugins/security_solution/server/graphql/ip_details/index.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts index 186397ea347cb4..c367424d375f9d 100644 --- a/x-pack/plugins/security_solution/server/graphql/ip_details/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { createIpDetailsResolvers } from './resolvers'; -export { ipDetailsSchemas } from './schema.gql'; +export { SetupGuide } from './setup_guide'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx new file mode 100644 index 00000000000000..63b0cc5a56cd13 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.test.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; +import { SetupGuide } from './'; + +describe('SetupGuide', () => { + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(SetupGuideLayout)).toHaveLength(1); + expect(wrapper.find(SetPageChrome)).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx new file mode 100644 index 00000000000000..fcb3b399c75b0e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + +import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../../common/constants'; +import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; +import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; +import GettingStarted from './assets/getting_started.png'; + +export const SetupGuide: React.FC = () => ( + + + + + + {i18n.translate('xpack.enterpriseSearch.enterpriseSearch.setupGuide.videoAlt', + + + +

+ +

+
+ + +

+ +

+
+
+); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx index b2918dac086f6c..2c0902163e3d6a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import '../__mocks__/shallow_usecontext.mock'; + +import React, { useContext } from 'react'; import { shallow } from 'enzyme'; import { EuiPage } from '@elastic/eui'; @@ -12,54 +14,31 @@ import '../__mocks__/kea.mock'; import { useValues } from 'kea'; import { EnterpriseSearch } from './'; +import { SetupGuide } from './components/setup_guide'; import { ErrorConnecting } from './components/error_connecting'; -import { ProductCard } from './components/product_card'; +import { ProductSelector } from './components/product_selector'; describe('EnterpriseSearch', () => { beforeEach(() => { (useValues as jest.Mock).mockReturnValue({ errorConnecting: false }); + (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } })); }); - it('renders the overview page and product cards', () => { - const wrapper = shallow( - - ); + it('renders the Setup Guide and Product Selector', () => { + const wrapper = shallow(); - expect(wrapper.find(EuiPage).hasClass('enterpriseSearchOverview')).toBe(true); - expect(wrapper.find(ProductCard)).toHaveLength(2); + expect(wrapper.find(SetupGuide)).toHaveLength(1); + expect(wrapper.find(ProductSelector)).toHaveLength(1); }); - it('renders the error connecting prompt', () => { + it('renders the error connecting prompt when host is not configured', () => { (useValues as jest.Mock).mockReturnValueOnce({ errorConnecting: true }); + (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: '' } })); + const wrapper = shallow(); expect(wrapper.find(ErrorConnecting)).toHaveLength(1); expect(wrapper.find(EuiPage)).toHaveLength(0); - }); - - describe('access checks', () => { - it('does not render the App Search card if the user does not have access to AS', () => { - const wrapper = shallow( - - ); - - expect(wrapper.find(ProductCard)).toHaveLength(1); - expect(wrapper.find(ProductCard).prop('product').ID).toEqual('workplaceSearch'); - }); - - it('does not render the Workplace Search card if the user does not have access to WS', () => { - const wrapper = shallow( - - ); - - expect(wrapper.find(ProductCard)).toHaveLength(1); - expect(wrapper.find(ProductCard).prop('product').ID).toEqual('appSearch'); - }); - - it('does not render any cards if the user does not have access', () => { - const wrapper = shallow(); - - expect(wrapper.find(ProductCard)).toHaveLength(0); - }); + expect(wrapper.find(ProductSelector)).toHaveLength(0); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx index 3a3ba02e07058a..e2c05434dd0bbc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx @@ -4,81 +4,37 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useContext } from 'react'; +import { Route, Switch } from 'react-router-dom'; import { useValues } from 'kea'; -import { - EuiPage, - EuiPageBody, - EuiPageHeader, - EuiPageHeaderSection, - EuiPageContentBody, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiTitle, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { KibanaContext, IKibanaContext } from '../index'; import { IInitialAppData } from '../../../common/types'; -import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../common/constants'; import { HttpLogic } from '../shared/http'; -import { SetEnterpriseSearchChrome as SetPageChrome } from '../shared/kibana_chrome'; -import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../shared/telemetry'; + +import { ROOT_PATH, SETUP_GUIDE_PATH } from './routes'; import { ErrorConnecting } from './components/error_connecting'; -import { ProductCard } from './components/product_card'; +import { ProductSelector } from './components/product_selector'; +import { SetupGuide } from './components/setup_guide'; -import AppSearchImage from './assets/app_search.png'; -import WorkplaceSearchImage from './assets/workplace_search.png'; import './index.scss'; export const EnterpriseSearch: React.FC = ({ access = {} }) => { const { errorConnecting } = useValues(HttpLogic); - const { hasAppSearchAccess, hasWorkplaceSearchAccess } = access; - - return errorConnecting ? ( - - ) : ( - - - - - - - - -

- {i18n.translate('xpack.enterpriseSearch.overview.heading', { - defaultMessage: 'Welcome to Elastic Enterprise Search', - })} -

-
- -

- {i18n.translate('xpack.enterpriseSearch.overview.subheading', { - defaultMessage: 'Select a product to get started', - })} -

-
-
-
- - - {hasAppSearchAccess && ( - - - - )} - {hasWorkplaceSearchAccess && ( - - - - )} - - - -
-
+ const { config } = useContext(KibanaContext) as IKibanaContext; + + const showErrorConnecting = config.host && errorConnecting; + + return ( + + + + + + {showErrorConnecting ? : } + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/routes.ts new file mode 100644 index 00000000000000..1f9c06e9683ab0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/routes.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const ROOT_PATH = '/'; +export const SETUP_GUIDE_PATH = '/setup_guide'; diff --git a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx index 053c450ab925ef..6ee63ee22cae2b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx @@ -6,7 +6,6 @@ import React from 'react'; -import { AppMountParameters } from 'src/core/public'; import { coreMock } from 'src/core/public/mocks'; import { licensingMock } from '../../../licensing/public/mocks'; @@ -15,37 +14,38 @@ import { AppSearch } from './app_search'; import { WorkplaceSearch } from './workplace_search'; describe('renderApp', () => { - let params: AppMountParameters; - const core = coreMock.createStart(); - const plugins = { - licensing: licensingMock.createSetup(), + const kibanaDeps = { + params: coreMock.createAppMountParamters(), + core: coreMock.createStart(), + plugins: { licensing: licensingMock.createStart() }, + } as any; + const pluginData = { + config: {}, + data: {}, } as any; - const config = {}; - const data = {} as any; beforeEach(() => { jest.clearAllMocks(); - params = coreMock.createAppMountParamters(); }); it('mounts and unmounts UI', () => { const MockApp = () =>
Hello world!
; - const unmount = renderApp(MockApp, params, core, plugins, config, data); - expect(params.element.querySelector('.hello-world')).not.toBeNull(); + const unmount = renderApp(MockApp, kibanaDeps, pluginData); + expect(kibanaDeps.params.element.querySelector('.hello-world')).not.toBeNull(); unmount(); - expect(params.element.innerHTML).toEqual(''); + expect(kibanaDeps.params.element.innerHTML).toEqual(''); }); it('renders AppSearch', () => { - renderApp(AppSearch, params, core, plugins, config, data); - expect(params.element.querySelector('.setupGuide')).not.toBeNull(); + renderApp(AppSearch, kibanaDeps, pluginData); + expect(kibanaDeps.params.element.querySelector('.setupGuide')).not.toBeNull(); }); it('renders WorkplaceSearch', () => { - renderApp(WorkplaceSearch, params, core, plugins, config, data); - expect(params.element.querySelector('.setupGuide')).not.toBeNull(); + renderApp(WorkplaceSearch, kibanaDeps, pluginData); + expect(kibanaDeps.params.element.querySelector('.setupGuide')).not.toBeNull(); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index 0869ef7b22729e..4a25ecf6067cc3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -14,8 +14,8 @@ import { getContext, resetContext } from 'kea'; import { I18nProvider } from '@kbn/i18n/react'; import { AppMountParameters, CoreStart, ApplicationStart, ChromeBreadcrumb } from 'src/core/public'; -import { ClientConfigType, ClientData, PluginsSetup } from '../plugin'; -import { LicenseProvider } from './shared/licensing'; +import { PluginsStart, ClientConfigType, ClientData } from '../plugin'; +import { mountLicensingLogic } from './shared/licensing'; import { mountHttpLogic } from './shared/http'; import { mountFlashMessagesLogic } from './shared/flash_messages'; import { IExternalUrl } from './shared/enterprise_search_url'; @@ -39,15 +39,18 @@ export const KibanaContext = React.createContext({}); export const renderApp = ( App: React.FC, - params: AppMountParameters, - core: CoreStart, - plugins: PluginsSetup, - config: ClientConfigType, - { externalUrl, errorConnecting, ...initialData }: ClientData + { params, core, plugins }: { params: AppMountParameters; core: CoreStart; plugins: PluginsStart }, + { config, data }: { config: ClientConfigType; data: ClientData } ) => { + const { externalUrl, errorConnecting, ...initialData } = data; + resetContext({ createStore: true }); const store = getContext().store as Store; + const unmountLicensingLogic = mountLicensingLogic({ + license$: plugins.licensing.license$, + }); + const unmountHttpLogic = mountHttpLogic({ http: core.http, errorConnecting, @@ -67,19 +70,18 @@ export const renderApp = ( setDocTitle: core.chrome.docTitle.change, }} > - - - - - - - + + + + + , params.element ); return () => { ReactDOM.unmountComponentAtNode(params.element); + unmountLicensingLogic(); unmountHttpLogic(); unmountFlashMessagesLogic(); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/index.ts index 29c11ffa1cef8c..4e371b337c40a0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { LicenseContext, LicenseProvider, ILicenseContext } from './license_context'; -export { hasPlatinumLicense, hasGoldLicense } from './license_checks'; +export { LicensingLogic, mountLicensingLogic } from './licensing_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_checks.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_checks.test.ts deleted file mode 100644 index 40f0f6380c21cd..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_checks.test.ts +++ /dev/null @@ -1,54 +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 { hasPlatinumLicense, hasGoldLicense } from './license_checks'; - -describe('hasPlatinumLicense', () => { - it('is true for platinum licenses', () => { - expect(hasPlatinumLicense({ isActive: true, type: 'platinum' } as any)).toEqual(true); - }); - - it('is true for enterprise licenses', () => { - expect(hasPlatinumLicense({ isActive: true, type: 'enterprise' } as any)).toEqual(true); - }); - - it('is true for trial licenses', () => { - expect(hasPlatinumLicense({ isActive: true, type: 'platinum' } as any)).toEqual(true); - }); - - it('is false if the current license is expired', () => { - expect(hasPlatinumLicense({ isActive: false, type: 'platinum' } as any)).toEqual(false); - expect(hasPlatinumLicense({ isActive: false, type: 'enterprise' } as any)).toEqual(false); - expect(hasPlatinumLicense({ isActive: false, type: 'trial' } as any)).toEqual(false); - }); - - it('is false for licenses below platinum', () => { - expect(hasPlatinumLicense({ isActive: true, type: 'basic' } as any)).toEqual(false); - expect(hasPlatinumLicense({ isActive: false, type: 'standard' } as any)).toEqual(false); - expect(hasPlatinumLicense({ isActive: true, type: 'gold' } as any)).toEqual(false); - }); -}); - -describe('hasGoldLicense', () => { - it('is true for gold+ and trial licenses', () => { - expect(hasGoldLicense({ isActive: true, type: 'gold' } as any)).toEqual(true); - expect(hasGoldLicense({ isActive: true, type: 'platinum' } as any)).toEqual(true); - expect(hasGoldLicense({ isActive: true, type: 'enterprise' } as any)).toEqual(true); - expect(hasGoldLicense({ isActive: true, type: 'trial' } as any)).toEqual(true); - }); - - it('is false if the current license is expired', () => { - expect(hasGoldLicense({ isActive: false, type: 'gold' } as any)).toEqual(false); - expect(hasGoldLicense({ isActive: false, type: 'platinum' } as any)).toEqual(false); - expect(hasGoldLicense({ isActive: false, type: 'enterprise' } as any)).toEqual(false); - expect(hasGoldLicense({ isActive: false, type: 'trial' } as any)).toEqual(false); - }); - - it('is false for licenses below gold', () => { - expect(hasGoldLicense({ isActive: true, type: 'basic' } as any)).toEqual(false); - expect(hasGoldLicense({ isActive: false, type: 'standard' } as any)).toEqual(false); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_checks.ts b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_checks.ts deleted file mode 100644 index d13d0909243be7..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_checks.ts +++ /dev/null @@ -1,17 +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 { ILicense } from '../../../../../licensing/public'; - -export const hasPlatinumLicense = (license?: ILicense) => { - const qualifyingLicenses = ['platinum', 'enterprise', 'trial']; - return license?.isActive && qualifyingLicenses.includes(license?.type as string); -}; - -export const hasGoldLicense = (license?: ILicense) => { - const qualifyingLicenses = ['gold', 'platinum', 'enterprise', 'trial']; - return license?.isActive && qualifyingLicenses.includes(license?.type as string); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_context.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_context.test.tsx deleted file mode 100644 index c65474ec1f5900..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_context.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useContext } from 'react'; - -import { mountWithContext } from '../../__mocks__'; -import { LicenseContext, ILicenseContext } from './'; - -describe('LicenseProvider', () => { - const MockComponent: React.FC = () => { - const { license } = useContext(LicenseContext) as ILicenseContext; - return
{license?.type}
; - }; - - it('renders children', () => { - const wrapper = mountWithContext(, { license: { type: 'basic' } }); - - expect(wrapper.find('.license-test')).toHaveLength(1); - expect(wrapper.text()).toEqual('basic'); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_context.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_context.tsx deleted file mode 100644 index 9b47959ff75447..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/license_context.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import useObservable from 'react-use/lib/useObservable'; -import { Observable } from 'rxjs'; - -import { ILicense } from '../../../../../licensing/public'; - -export interface ILicenseContext { - license: ILicense; -} -interface ILicenseContextProps { - license$: Observable; - children: React.ReactNode; -} - -export const LicenseContext = React.createContext({}); - -export const LicenseProvider: React.FC = ({ license$, children }) => { - // Listen for changes to license subscription - const license = useObservable(license$); - - // Render rest of application and pass down license via context - return ; -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/licensing_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/licensing_logic.test.ts new file mode 100644 index 00000000000000..153a5ae7654682 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/licensing_logic.test.ts @@ -0,0 +1,161 @@ +/* + * 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 { resetContext } from 'kea'; +import { BehaviorSubject } from 'rxjs'; + +import { licensingMock } from '../../../../../licensing/public/mocks'; + +import { LicensingLogic, mountLicensingLogic } from './licensing_logic'; + +describe('LicensingLogic', () => { + const mockLicense = licensingMock.createLicense(); + const mockLicense$ = new BehaviorSubject(mockLicense); + const mount = () => mountLicensingLogic({ license$: mockLicense$ }); + + beforeEach(() => { + jest.clearAllMocks(); + resetContext({}); + }); + + describe('setLicense()', () => { + it('sets license value', () => { + mount(); + LicensingLogic.actions.setLicense('test' as any); + expect(LicensingLogic.values.license).toEqual('test'); + }); + }); + + describe('setLicenseSubscription()', () => { + it('sets licenseSubscription value', () => { + mount(); + LicensingLogic.actions.setLicenseSubscription('test' as any); + expect(LicensingLogic.values.licenseSubscription).toEqual('test'); + }); + }); + + describe('licensing subscription', () => { + describe('on mount', () => { + it('subscribes to the license observable', () => { + mount(); + expect(LicensingLogic.values.license).toEqual(mockLicense); + expect(LicensingLogic.values.licenseSubscription).not.toBeNull(); + }); + }); + + describe('on subscription update', () => { + it('updates the license value', () => { + mount(); + + const nextMockLicense = licensingMock.createLicense({ license: { status: 'invalid' } }); + mockLicense$.next(nextMockLicense); + + expect(LicensingLogic.values.license).toEqual(nextMockLicense); + }); + }); + + describe('on unmount', () => { + it('unsubscribes to the license observable', () => { + const mockUnsubscribe = jest.fn(); + const unmount = mountLicensingLogic({ + license$: { subscribe: () => ({ unsubscribe: mockUnsubscribe }) } as any, + }); + unmount(); + expect(mockUnsubscribe).toHaveBeenCalled(); + }); + + it('does not crash if no subscription exists', () => { + const unmount = mount(); + LicensingLogic.actions.setLicenseSubscription(null as any); + unmount(); + }); + }); + }); + + describe('license check selectors', () => { + beforeEach(() => { + mount(); + }); + + const updateLicense = (license: any) => { + const updatedLicense = licensingMock.createLicense({ license }); + mockLicense$.next(updatedLicense); + }; + + describe('hasPlatinumLicense', () => { + it('is true for platinum+ and trial licenses', () => { + updateLicense({ status: 'active', type: 'platinum' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(true); + + updateLicense({ status: 'active', type: 'enterprise' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(true); + + updateLicense({ status: 'active', type: 'trial' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(true); + }); + + it('is false if the current license is expired', () => { + updateLicense({ status: 'expired', type: 'platinum' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(false); + + updateLicense({ status: 'expired', type: 'enterprise' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(false); + + updateLicense({ status: 'expired', type: 'trial' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(false); + }); + + it('is false for licenses below platinum', () => { + updateLicense({ status: 'active', type: 'basic' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(false); + + updateLicense({ status: 'active', type: 'standard' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(false); + + updateLicense({ status: 'active', type: 'gold' }); + expect(LicensingLogic.values.hasPlatinumLicense).toEqual(false); + }); + }); + + describe('hasGoldLicense', () => { + it('is true for gold+ and trial licenses', () => { + updateLicense({ status: 'active', type: 'gold' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(true); + + updateLicense({ status: 'active', type: 'platinum' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(true); + + updateLicense({ status: 'active', type: 'enterprise' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(true); + + updateLicense({ status: 'active', type: 'trial' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(true); + }); + + it('is false if the current license is expired', () => { + updateLicense({ status: 'expired', type: 'gold' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(false); + + updateLicense({ status: 'expired', type: 'platinum' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(false); + + updateLicense({ status: 'expired', type: 'enterprise' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(false); + + updateLicense({ status: 'expired', type: 'trial' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(false); + }); + + it('is false for licenses below gold', () => { + updateLicense({ status: 'active', type: 'basic' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(false); + + updateLicense({ status: 'active', type: 'standard' }); + expect(LicensingLogic.values.hasGoldLicense).toEqual(false); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/licensing/licensing_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/licensing_logic.ts new file mode 100644 index 00000000000000..ae31b2ec6168a4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/licensing/licensing_logic.ts @@ -0,0 +1,82 @@ +/* + * 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 { kea, MakeLogicType } from 'kea'; +import { Observable, Subscription } from 'rxjs'; + +import { ILicense } from '../../../../../licensing/public'; + +export interface ILicensingValues { + license: ILicense | null; + licenseSubscription: Subscription | null; + hasPlatinumLicense: boolean; + hasGoldLicense: boolean; +} +export interface ILicensingActions { + setLicense(license: ILicense): ILicense; + setLicenseSubscription(licenseSubscription: Subscription): Subscription; +} + +export const LicensingLogic = kea>({ + path: ['enterprise_search', 'licensing_logic'], + actions: { + setLicense: (license) => license, + setLicenseSubscription: (licenseSubscription) => licenseSubscription, + }, + reducers: { + license: [ + null, + { + setLicense: (_, license) => license, + }, + ], + licenseSubscription: [ + null, + { + setLicenseSubscription: (_, licenseSubscription) => licenseSubscription, + }, + ], + }, + selectors: { + hasPlatinumLicense: [ + (selectors) => [selectors.license], + (license) => { + const qualifyingLicenses = ['platinum', 'enterprise', 'trial']; + return license?.isActive && qualifyingLicenses.includes(license?.type); + }, + ], + hasGoldLicense: [ + (selectors) => [selectors.license], + (license) => { + const qualifyingLicenses = ['gold', 'platinum', 'enterprise', 'trial']; + return license?.isActive && qualifyingLicenses.includes(license?.type); + }, + ], + }, + events: ({ props, actions, values }) => ({ + afterMount: () => { + const licenseSubscription = props.license$.subscribe(async (license: ILicense) => { + actions.setLicense(license); + }); + actions.setLicenseSubscription(licenseSubscription); + }, + beforeUnmount: () => { + if (values.licenseSubscription) values.licenseSubscription.unsubscribe(); + }, + }), +}); + +/** + * Mount/props helper + */ +interface ILicensingLogicProps { + license$: Observable; +} +export const mountLicensingLogic = (props: ILicensingLogicProps) => { + LicensingLogic(props); + const unmount = LicensingLogic.mount(); + return unmount; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx index ce9071ad7b9d0c..62c0af31cffd9a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../__mocks__/shallow_usecontext.mock'; +import '../../__mocks__/kea.mock'; -import React, { useContext } from 'react'; +import React from 'react'; +import { useValues } from 'kea'; import { shallow } from 'enzyme'; import { EuiButton as EuiButtonExternal, EuiEmptyPrompt } from '@elastic/eui'; @@ -18,13 +19,6 @@ import { WorkplaceSearchLogo } from './assets/workplace_search_logo'; import { NotFound } from './'; describe('NotFound', () => { - const basicLicense = { isActive: true, type: 'basic' }; - const goldLicense = { isActive: true, type: 'gold' }; - - beforeEach(() => { - (useContext as jest.Mock).mockImplementation(() => ({ license: basicLicense })); - }); - it('renders an App Search 404 view', () => { const wrapper = shallow(); const prompt = wrapper.find(EuiEmptyPrompt).dive().shallow(); @@ -50,7 +44,7 @@ describe('NotFound', () => { }); it('changes the support URL if the user has a gold+ license', () => { - (useContext as jest.Mock).mockImplementation(() => ({ license: goldLicense })); + (useValues as jest.Mock).mockReturnValueOnce({ hasGoldLicense: true }); const wrapper = shallow(); const prompt = wrapper.find(EuiEmptyPrompt).dive().shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx index bd988854225fbd..40bb5efcc6330b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; +import { useValues } from 'kea'; import { i18n } from '@kbn/i18n'; import { EuiPageContent, @@ -24,7 +25,7 @@ import { import { EuiButton } from '../react_router_helpers'; import { SetAppSearchChrome, SetWorkplaceSearchChrome } from '../kibana_chrome'; import { SendAppSearchTelemetry, SendWorkplaceSearchTelemetry } from '../telemetry'; -import { LicenseContext, ILicenseContext, hasGoldLicense } from '../licensing'; +import { LicensingLogic } from '../licensing'; import { AppSearchLogo } from './assets/app_search_logo'; import { WorkplaceSearchLogo } from './assets/workplace_search_logo'; @@ -39,8 +40,8 @@ interface NotFoundProps { } export const NotFound: React.FC = ({ product = {} }) => { - const { license } = useContext(LicenseContext) as ILicenseContext; - const supportUrl = hasGoldLicense(license) ? LICENSED_SUPPORT_URL : product.SUPPORT_URL; + const { hasGoldLicense } = useValues(LicensingLogic); + const supportUrl = hasGoldLicense ? LICENSED_SUPPORT_URL : product.SUPPORT_URL; let Logo; let SetPageChrome; diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index c23bb23be3979e..f59ec830c812fb 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -7,7 +7,6 @@ import { AppMountParameters, CoreSetup, - CoreStart, HttpSetup, Plugin, PluginInitializerContext, @@ -17,7 +16,7 @@ import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; -import { LicensingPluginSetup } from '../../licensing/public'; +import { LicensingPluginStart } from '../../licensing/public'; import { APP_SEARCH_PLUGIN, ENTERPRISE_SEARCH_PLUGIN, @@ -36,7 +35,9 @@ export interface ClientData extends IInitialAppData { export interface PluginsSetup { home?: HomePublicPluginSetup; - licensing: LicensingPluginSetup; +} +export interface PluginsStart { + licensing: LicensingPluginStart; } export class EnterpriseSearchPlugin implements Plugin { @@ -57,16 +58,17 @@ export class EnterpriseSearchPlugin implements Plugin { appRoute: ENTERPRISE_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { - const [coreStart] = await core.getStartServices(); - const { chrome } = coreStart; - chrome.docTitle.change(ENTERPRISE_SEARCH_PLUGIN.NAME); + const kibanaDeps = await this.getKibanaDeps(core, params); + const pluginData = this.getPluginData(); - await this.getInitialData(coreStart.http); + const { chrome, http } = kibanaDeps.core; + chrome.docTitle.change(ENTERPRISE_SEARCH_PLUGIN.NAME); + await this.getInitialData(http); const { renderApp } = await import('./applications'); const { EnterpriseSearch } = await import('./applications/enterprise_search'); - return renderApp(EnterpriseSearch, params, coreStart, plugins, this.config, this.data); + return renderApp(EnterpriseSearch, kibanaDeps, pluginData); }, }); @@ -77,16 +79,17 @@ export class EnterpriseSearchPlugin implements Plugin { appRoute: APP_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { - const [coreStart] = await core.getStartServices(); - const { chrome } = coreStart; - chrome.docTitle.change(APP_SEARCH_PLUGIN.NAME); + const kibanaDeps = await this.getKibanaDeps(core, params); + const pluginData = this.getPluginData(); - await this.getInitialData(coreStart.http); + const { chrome, http } = kibanaDeps.core; + chrome.docTitle.change(APP_SEARCH_PLUGIN.NAME); + await this.getInitialData(http); const { renderApp } = await import('./applications'); const { AppSearch } = await import('./applications/app_search'); - return renderApp(AppSearch, params, coreStart, plugins, this.config, this.data); + return renderApp(AppSearch, kibanaDeps, pluginData); }, }); @@ -97,11 +100,12 @@ export class EnterpriseSearchPlugin implements Plugin { appRoute: WORKPLACE_SEARCH_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { - const [coreStart] = await core.getStartServices(); - const { chrome } = coreStart; - chrome.docTitle.change(WORKPLACE_SEARCH_PLUGIN.NAME); + const kibanaDeps = await this.getKibanaDeps(core, params); + const pluginData = this.getPluginData(); - await this.getInitialData(coreStart.http); + const { chrome, http } = kibanaDeps.core; + chrome.docTitle.change(APP_SEARCH_PLUGIN.NAME); + await this.getInitialData(http); const { renderApp, renderHeaderActions } = await import('./applications'); const { WorkplaceSearch } = await import('./applications/workplace_search'); @@ -113,7 +117,7 @@ export class EnterpriseSearchPlugin implements Plugin { renderHeaderActions(WorkplaceSearchHeaderActions, element, this.data.externalUrl) ); - return renderApp(WorkplaceSearch, params, coreStart, plugins, this.config, this.data); + return renderApp(WorkplaceSearch, kibanaDeps, pluginData); }, }); @@ -149,10 +153,22 @@ export class EnterpriseSearchPlugin implements Plugin { } } - public start(core: CoreStart) {} + public start() {} public stop() {} + private async getKibanaDeps(core: CoreSetup, params: AppMountParameters) { + // Helper for using start dependencies on mount (instead of setup dependencies) + // and for grouping Kibana-related args together (vs. plugin-specific args) + const [coreStart, pluginsStart] = await core.getStartServices(); + return { params, core: coreStart, plugins: pluginsStart as PluginsStart }; + } + + private getPluginData() { + // Small helper for grouping plugin data related args together + return { config: this.config, data: this.data }; + } + private async getInitialData(http: HttpSetup) { if (!this.config.host) return; // No API to call if (this.hasInitialized) return; // We've already made an initial call diff --git a/x-pack/plugins/security_solution/server/graphql/uncommon_processes/index.ts b/x-pack/plugins/infra/common/http_api/infra_ml/index.ts similarity index 66% rename from x-pack/plugins/security_solution/server/graphql/uncommon_processes/index.ts rename to x-pack/plugins/infra/common/http_api/infra_ml/index.ts index d0da0efd8a5604..38684cb22e237f 100644 --- a/x-pack/plugins/security_solution/server/graphql/uncommon_processes/index.ts +++ b/x-pack/plugins/infra/common/http_api/infra_ml/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { createUncommonProcessesResolvers } from './resolvers'; -export { uncommonProcessesSchema } from './schema.gql'; +export * from './results'; diff --git a/x-pack/plugins/infra/common/http_api/infra_ml/results/common.ts b/x-pack/plugins/infra/common/http_api/infra_ml/results/common.ts new file mode 100644 index 00000000000000..0474fbd1cfc2fe --- /dev/null +++ b/x-pack/plugins/infra/common/http_api/infra_ml/results/common.ts @@ -0,0 +1,59 @@ +/* + * 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 * as rt from 'io-ts'; + +// [Sort field value, tiebreaker value] +export const paginationCursorRT = rt.tuple([ + rt.union([rt.string, rt.number]), + rt.union([rt.string, rt.number]), +]); + +export type PaginationCursor = rt.TypeOf; + +export const anomalyTypeRT = rt.keyof({ + metrics_hosts: null, + metrics_k8s: null, +}); + +export type AnomalyType = rt.TypeOf; + +const sortOptionsRT = rt.keyof({ + anomalyScore: null, + dataset: null, + startTime: null, +}); + +const sortDirectionsRT = rt.keyof({ + asc: null, + desc: null, +}); + +const paginationPreviousPageCursorRT = rt.type({ + searchBefore: paginationCursorRT, +}); + +const paginationNextPageCursorRT = rt.type({ + searchAfter: paginationCursorRT, +}); + +export const paginationRT = rt.intersection([ + rt.type({ + pageSize: rt.number, + }), + rt.partial({ + cursor: rt.union([paginationPreviousPageCursorRT, paginationNextPageCursorRT]), + }), +]); + +export type Pagination = rt.TypeOf; + +export const sortRT = rt.type({ + field: sortOptionsRT, + direction: sortDirectionsRT, +}); + +export type Sort = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/http_api/infra_ml/results/index.ts b/x-pack/plugins/infra/common/http_api/infra_ml/results/index.ts new file mode 100644 index 00000000000000..efd597a043e072 --- /dev/null +++ b/x-pack/plugins/infra/common/http_api/infra_ml/results/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './metrics_hosts_anomalies'; +export * from './metrics_k8s_anomalies'; +export * from './common'; diff --git a/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts new file mode 100644 index 00000000000000..9fdac09fec20e2 --- /dev/null +++ b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts @@ -0,0 +1,79 @@ +/* + * 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 * as rt from 'io-ts'; + +import { timeRangeRT, routeTimingMetadataRT } from '../../shared'; +import { anomalyTypeRT, paginationCursorRT, sortRT, paginationRT } from './common'; + +export const INFA_ML_GET_METRICS_HOSTS_ANOMALIES_PATH = + '/api/infra/infra_ml/results/metrics_hosts_anomalies'; + +const metricsHostAnomalyCommonFieldsRT = rt.type({ + id: rt.string, + anomalyScore: rt.number, + typical: rt.number, + actual: rt.number, + type: anomalyTypeRT, + duration: rt.number, + startTime: rt.number, + jobId: rt.string, +}); +const metricsHostsAnomalyRT = metricsHostAnomalyCommonFieldsRT; + +export type MetricsHostsAnomaly = rt.TypeOf; + +export const getMetricsHostsAnomaliesSuccessReponsePayloadRT = rt.intersection([ + rt.type({ + data: rt.intersection([ + rt.type({ + anomalies: rt.array(metricsHostsAnomalyRT), + // Signifies there are more entries backwards or forwards. If this was a request + // for a previous page, there are more previous pages, if this was a request for a next page, + // there are more next pages. + hasMoreEntries: rt.boolean, + }), + rt.partial({ + paginationCursors: rt.type({ + // The cursor to use to fetch the previous page + previousPageCursor: paginationCursorRT, + // The cursor to use to fetch the next page + nextPageCursor: paginationCursorRT, + }), + }), + ]), + }), + rt.partial({ + timing: routeTimingMetadataRT, + }), +]); + +export type GetMetricsHostsAnomaliesSuccessResponsePayload = rt.TypeOf< + typeof getMetricsHostsAnomaliesSuccessReponsePayloadRT +>; + +export const getMetricsHostsAnomaliesRequestPayloadRT = rt.type({ + data: rt.intersection([ + rt.type({ + // the ID of the source configuration + sourceId: rt.string, + // the time range to fetch the log entry anomalies from + timeRange: timeRangeRT, + }), + rt.partial({ + // Pagination properties + pagination: paginationRT, + // Sort properties + sort: sortRT, + // // Dataset filters + // datasets: rt.array(rt.string), + }), + ]), +}); + +export type GetMetricsHostsAnomaliesRequestPayload = rt.TypeOf< + typeof getMetricsHostsAnomaliesRequestPayloadRT +>; diff --git a/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts new file mode 100644 index 00000000000000..ab1f245a74c0cb --- /dev/null +++ b/x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts @@ -0,0 +1,79 @@ +/* + * 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 * as rt from 'io-ts'; + +import { timeRangeRT, routeTimingMetadataRT } from '../../shared'; +import { paginationCursorRT, anomalyTypeRT, sortRT, paginationRT } from './common'; + +export const INFA_ML_GET_METRICS_K8S_ANOMALIES_PATH = + '/api/infra/infra_ml/results/metrics_k8s_anomalies'; + +const metricsK8sAnomalyCommonFieldsRT = rt.type({ + id: rt.string, + anomalyScore: rt.number, + typical: rt.number, + actual: rt.number, + type: anomalyTypeRT, + duration: rt.number, + startTime: rt.number, + jobId: rt.string, +}); +const metricsK8sAnomalyRT = metricsK8sAnomalyCommonFieldsRT; + +export type MetricsK8sAnomaly = rt.TypeOf; + +export const getMetricsK8sAnomaliesSuccessReponsePayloadRT = rt.intersection([ + rt.type({ + data: rt.intersection([ + rt.type({ + anomalies: rt.array(metricsK8sAnomalyRT), + // Signifies there are more entries backwards or forwards. If this was a request + // for a previous page, there are more previous pages, if this was a request for a next page, + // there are more next pages. + hasMoreEntries: rt.boolean, + }), + rt.partial({ + paginationCursors: rt.type({ + // The cursor to use to fetch the previous page + previousPageCursor: paginationCursorRT, + // The cursor to use to fetch the next page + nextPageCursor: paginationCursorRT, + }), + }), + ]), + }), + rt.partial({ + timing: routeTimingMetadataRT, + }), +]); + +export type GetMetricsK8sAnomaliesSuccessResponsePayload = rt.TypeOf< + typeof getMetricsK8sAnomaliesSuccessReponsePayloadRT +>; + +export const getMetricsK8sAnomaliesRequestPayloadRT = rt.type({ + data: rt.intersection([ + rt.type({ + // the ID of the source configuration + sourceId: rt.string, + // the time range to fetch the log entry anomalies from + timeRange: timeRangeRT, + }), + rt.partial({ + // Pagination properties + pagination: paginationRT, + // Sort properties + sort: sortRT, + // Dataset filters + datasets: rt.array(rt.string), + }), + ]), +}); + +export type GetMetricsK8sAnomaliesRequestPayload = rt.TypeOf< + typeof getMetricsK8sAnomaliesRequestPayloadRT +>; diff --git a/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts b/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts new file mode 100644 index 00000000000000..f4497dbba50567 --- /dev/null +++ b/x-pack/plugins/infra/common/infra_ml/anomaly_results.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const ML_SEVERITY_SCORES = { + warning: 3, + minor: 25, + major: 50, + critical: 75, +}; + +export type MLSeverityScoreCategories = keyof typeof ML_SEVERITY_SCORES; + +export const ML_SEVERITY_COLORS = { + critical: 'rgb(228, 72, 72)', + major: 'rgb(229, 113, 0)', + minor: 'rgb(255, 221, 0)', + warning: 'rgb(125, 180, 226)', +}; + +export const getSeverityCategoryForScore = ( + score: number +): MLSeverityScoreCategories | undefined => { + if (score >= ML_SEVERITY_SCORES.critical) { + return 'critical'; + } else if (score >= ML_SEVERITY_SCORES.major) { + return 'major'; + } else if (score >= ML_SEVERITY_SCORES.minor) { + return 'minor'; + } else if (score >= ML_SEVERITY_SCORES.warning) { + return 'warning'; + } else { + // Category is too low to include + return undefined; + } +}; + +export const formatAnomalyScore = (score: number) => { + return Math.round(score); +}; + +export const formatOneDecimalPlace = (number: number) => { + return Math.round(number * 10) / 10; +}; + +export const getFriendlyNameForPartitionId = (partitionId: string) => { + return partitionId !== '' ? partitionId : 'unknown'; +}; + +export const compareDatasetsByMaximumAnomalyScore = < + Dataset extends { maximumAnomalyScore: number } +>( + firstDataset: Dataset, + secondDataset: Dataset +) => firstDataset.maximumAnomalyScore - secondDataset.maximumAnomalyScore; diff --git a/x-pack/plugins/infra/common/infra_ml/index.ts b/x-pack/plugins/infra/common/infra_ml/index.ts new file mode 100644 index 00000000000000..88fbbd4f250451 --- /dev/null +++ b/x-pack/plugins/infra/common/infra_ml/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './infra_ml'; +export * from './anomaly_results'; +export * from './job_parameters'; +export * from './metrics_hosts_ml'; +export * from './metrics_k8s_ml'; diff --git a/x-pack/plugins/infra/common/infra_ml/infra_ml.ts b/x-pack/plugins/infra/common/infra_ml/infra_ml.ts new file mode 100644 index 00000000000000..680a2a0fef1145 --- /dev/null +++ b/x-pack/plugins/infra/common/infra_ml/infra_ml.ts @@ -0,0 +1,52 @@ +/* + * 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. + */ + +// combines and abstracts job and datafeed status +export type JobStatus = + | 'unknown' + | 'missing' + | 'initializing' + | 'stopped' + | 'started' + | 'finished' + | 'failed'; + +export type SetupStatus = + | { type: 'initializing' } // acquiring job statuses to determine setup status + | { type: 'unknown' } // job status could not be acquired (failed request etc) + | { type: 'required' } // setup required + | { type: 'pending' } // In the process of setting up the module for the first time or retrying, waiting for response + | { type: 'succeeded' } // setup succeeded, notifying user + | { + type: 'failed'; + reasons: string[]; + } // setup failed, notifying user + | { + type: 'skipped'; + newlyCreated?: boolean; + }; // setup is not necessary + +/** + * Maps a job status to the possibility that results have already been produced + * before this state was reached. + */ +export const isJobStatusWithResults = (jobStatus: JobStatus) => + ['started', 'finished', 'stopped', 'failed'].includes(jobStatus); + +export const isHealthyJobStatus = (jobStatus: JobStatus) => + ['started', 'finished'].includes(jobStatus); + +/** + * Maps a setup status to the possibility that results have already been + * produced before this state was reached. + */ +export const isSetupStatusWithResults = (setupStatus: SetupStatus) => + setupStatus.type === 'skipped'; + +const KIBANA_SAMPLE_DATA_INDICES = ['kibana_sample_data_logs*']; + +export const isExampleDataIndex = (indexName: string) => + KIBANA_SAMPLE_DATA_INDICES.includes(indexName); diff --git a/x-pack/plugins/infra/common/infra_ml/job_parameters.ts b/x-pack/plugins/infra/common/infra_ml/job_parameters.ts new file mode 100644 index 00000000000000..8cd1c9ea6e2ba9 --- /dev/null +++ b/x-pack/plugins/infra/common/infra_ml/job_parameters.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as rt from 'io-ts'; + +export const bucketSpan = 900000; + +export const categoriesMessageField = 'message'; + +export const partitionField = 'event.dataset'; + +export const getJobIdPrefix = (spaceId: string, sourceId: string) => + `kibana-metrics-ui-${spaceId}-${sourceId}-`; + +export const getJobId = (spaceId: string, sourceId: string, jobType: string) => + `${getJobIdPrefix(spaceId, sourceId)}${jobType}`; + +export const getDatafeedId = (spaceId: string, sourceId: string, jobType: string) => + `datafeed-${getJobId(spaceId, sourceId, jobType)}`; + +export const datasetFilterRT = rt.union([ + rt.strict({ + type: rt.literal('includeAll'), + }), + rt.strict({ + type: rt.literal('includeSome'), + datasets: rt.array(rt.string), + }), +]); + +export type DatasetFilter = rt.TypeOf; + +export const jobSourceConfigurationRT = rt.partial({ + indexPattern: rt.string, + timestampField: rt.string, + bucketSpan: rt.number, + datasetFilter: datasetFilterRT, +}); + +export type JobSourceConfiguration = rt.TypeOf; + +export const jobCustomSettingsRT = rt.partial({ + job_revision: rt.number, + metrics_source_config: jobSourceConfigurationRT, +}); + +export type JobCustomSettings = rt.TypeOf; + +export const combineDatasetFilters = ( + firstFilter: DatasetFilter, + secondFilter: DatasetFilter +): DatasetFilter => { + if (firstFilter.type === 'includeAll' && secondFilter.type === 'includeAll') { + return { + type: 'includeAll', + }; + } + + const includedDatasets = new Set([ + ...(firstFilter.type === 'includeSome' ? firstFilter.datasets : []), + ...(secondFilter.type === 'includeSome' ? secondFilter.datasets : []), + ]); + + return { + type: 'includeSome', + datasets: [...includedDatasets], + }; +}; + +export const filterDatasetFilter = ( + datasetFilter: DatasetFilter, + predicate: (dataset: string) => boolean +): DatasetFilter => { + if (datasetFilter.type === 'includeAll') { + return datasetFilter; + } else { + const newDatasets = datasetFilter.datasets.filter(predicate); + + if (newDatasets.length > 0) { + return { + type: 'includeSome', + datasets: newDatasets, + }; + } else { + return { + type: 'includeAll', + }; + } + } +}; diff --git a/x-pack/plugins/infra/common/infra_ml/metrics_hosts_ml.ts b/x-pack/plugins/infra/common/infra_ml/metrics_hosts_ml.ts new file mode 100644 index 00000000000000..d09b3be78204f9 --- /dev/null +++ b/x-pack/plugins/infra/common/infra_ml/metrics_hosts_ml.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as rt from 'io-ts'; + +export const metricsHostsJobTypeRT = rt.keyof({ + hosts_memory_usage: null, + hosts_network_in: null, + hosts_network_out: null, +}); + +export type MetricsHostsJobType = rt.TypeOf; + +export const metricsHostsJobTypes: MetricsHostsJobType[] = [ + 'hosts_memory_usage', + 'hosts_network_in', + 'hosts_network_out', +]; diff --git a/x-pack/plugins/infra/common/infra_ml/metrics_k8s_ml.ts b/x-pack/plugins/infra/common/infra_ml/metrics_k8s_ml.ts new file mode 100644 index 00000000000000..3c27dbb61a14ac --- /dev/null +++ b/x-pack/plugins/infra/common/infra_ml/metrics_k8s_ml.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as rt from 'io-ts'; + +export const metricK8sJobTypeRT = rt.keyof({ + k8s_memory_usage: null, + k8s_network_in: null, + k8s_network_out: null, +}); + +export type MetricK8sJobType = rt.TypeOf; + +export const metricsK8SJobTypes: MetricK8sJobType[] = [ + 'k8s_memory_usage', + 'k8s_network_in', + 'k8s_network_out', +]; diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts b/x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts index c12137f7810d40..6453332be4f507 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts +++ b/x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts @@ -31,4 +31,5 @@ export const awsEC2: InventoryModel = { }, requiredMetrics: ['awsEC2CpuUtilization', 'awsEC2NetworkTraffic', 'awsEC2DiskIOBytes'], tooltipMetrics: ['cpu', 'rx', 'tx'], + nodeFilter: [{ term: { 'event.dataset': 'aws.ec2' } }], }; diff --git a/x-pack/plugins/infra/common/inventory_models/types.ts b/x-pack/plugins/infra/common/inventory_models/types.ts index 7eb74056dcf28f..5cc788f2383656 100644 --- a/x-pack/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/plugins/infra/common/inventory_models/types.ts @@ -371,4 +371,5 @@ export interface InventoryModel { metrics: InventoryMetrics; requiredMetrics: InventoryMetric[]; tooltipMetrics: SnapshotMetricType[]; + nodeFilter?: object[]; } diff --git a/x-pack/plugins/infra/public/containers/ml/api/ml_api_types.ts b/x-pack/plugins/infra/public/containers/ml/api/ml_api_types.ts new file mode 100644 index 00000000000000..ee70edc31d49ba --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/api/ml_api_types.ts @@ -0,0 +1,28 @@ +/* + * 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 * as rt from 'io-ts'; + +export const getMlCapabilitiesResponsePayloadRT = rt.type({ + capabilities: rt.type({ + canGetJobs: rt.boolean, + canCreateJob: rt.boolean, + canDeleteJob: rt.boolean, + canOpenJob: rt.boolean, + canCloseJob: rt.boolean, + canForecastJob: rt.boolean, + canGetDatafeeds: rt.boolean, + canStartStopDatafeed: rt.boolean, + canUpdateJob: rt.boolean, + canUpdateDatafeed: rt.boolean, + canPreviewDatafeed: rt.boolean, + }), + isPlatinumOrTrialLicense: rt.boolean, + mlFeatureEnabledInSpace: rt.boolean, + upgradeInProgress: rt.boolean, +}); + +export type GetMlCapabilitiesResponsePayload = rt.TypeOf; diff --git a/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts b/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts new file mode 100644 index 00000000000000..23fa338e74f147 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts @@ -0,0 +1,95 @@ +/* + * 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 * as rt from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { npStart } from '../../../legacy_singletons'; + +import { getDatafeedId, getJobId } from '../../../../common/infra_ml'; +import { throwErrors, createPlainError } from '../../../../common/runtime_types'; + +export const callDeleteJobs = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + // NOTE: Deleting the jobs via this API will delete the datafeeds at the same time + const deleteJobsResponse = await npStart.http.fetch('/api/ml/jobs/delete_jobs', { + method: 'POST', + body: JSON.stringify( + deleteJobsRequestPayloadRT.encode({ + jobIds: jobTypes.map((jobType) => getJobId(spaceId, sourceId, jobType)), + }) + ), + }); + + return pipe( + deleteJobsResponsePayloadRT.decode(deleteJobsResponse), + fold(throwErrors(createPlainError), identity) + ); +}; + +export const callGetJobDeletionTasks = async () => { + const jobDeletionTasksResponse = await npStart.http.fetch('/api/ml/jobs/deleting_jobs_tasks'); + + return pipe( + getJobDeletionTasksResponsePayloadRT.decode(jobDeletionTasksResponse), + fold(throwErrors(createPlainError), identity) + ); +}; + +export const callStopDatafeeds = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + // Stop datafeed due to https://github.com/elastic/kibana/issues/44652 + const stopDatafeedResponse = await npStart.http.fetch('/api/ml/jobs/stop_datafeeds', { + method: 'POST', + body: JSON.stringify( + stopDatafeedsRequestPayloadRT.encode({ + datafeedIds: jobTypes.map((jobType) => getDatafeedId(spaceId, sourceId, jobType)), + }) + ), + }); + + return pipe( + stopDatafeedsResponsePayloadRT.decode(stopDatafeedResponse), + fold(throwErrors(createPlainError), identity) + ); +}; + +export const deleteJobsRequestPayloadRT = rt.type({ + jobIds: rt.array(rt.string), +}); + +export type DeleteJobsRequestPayload = rt.TypeOf; + +export const deleteJobsResponsePayloadRT = rt.record( + rt.string, + rt.type({ + deleted: rt.boolean, + }) +); + +export type DeleteJobsResponsePayload = rt.TypeOf; + +export const getJobDeletionTasksResponsePayloadRT = rt.type({ + jobIds: rt.array(rt.string), +}); + +export const stopDatafeedsRequestPayloadRT = rt.type({ + datafeedIds: rt.array(rt.string), +}); + +export const stopDatafeedsResponsePayloadRT = rt.record( + rt.string, + rt.type({ + stopped: rt.boolean, + }) +); diff --git a/x-pack/plugins/infra/public/containers/ml/api/ml_get_jobs_summary_api.ts b/x-pack/plugins/infra/public/containers/ml/api/ml_get_jobs_summary_api.ts new file mode 100644 index 00000000000000..3fddb63f69791b --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/api/ml_get_jobs_summary_api.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; +import * as rt from 'io-ts'; +import { npStart } from '../../../legacy_singletons'; + +import { getJobId, jobCustomSettingsRT } from '../../../../common/infra_ml'; +import { createPlainError, throwErrors } from '../../../../common/runtime_types'; + +export const callJobsSummaryAPI = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + const response = await npStart.http.fetch('/api/ml/jobs/jobs_summary', { + method: 'POST', + body: JSON.stringify( + fetchJobStatusRequestPayloadRT.encode({ + jobIds: jobTypes.map((jobType) => getJobId(spaceId, sourceId, jobType)), + }) + ), + }); + return pipe( + fetchJobStatusResponsePayloadRT.decode(response), + fold(throwErrors(createPlainError), identity) + ); +}; + +export const fetchJobStatusRequestPayloadRT = rt.type({ + jobIds: rt.array(rt.string), +}); + +export type FetchJobStatusRequestPayload = rt.TypeOf; + +const datafeedStateRT = rt.keyof({ + started: null, + stopped: null, + stopping: null, + '': null, +}); + +const jobStateRT = rt.keyof({ + closed: null, + closing: null, + deleting: null, + failed: null, + opened: null, + opening: null, +}); + +const jobCategorizationStatusRT = rt.keyof({ + ok: null, + warn: null, +}); + +const jobModelSizeStatsRT = rt.type({ + categorization_status: jobCategorizationStatusRT, + categorized_doc_count: rt.number, + dead_category_count: rt.number, + frequent_category_count: rt.number, + rare_category_count: rt.number, + total_category_count: rt.number, +}); + +export type JobModelSizeStats = rt.TypeOf; + +export const jobSummaryRT = rt.intersection([ + rt.type({ + id: rt.string, + jobState: jobStateRT, + }), + rt.partial({ + datafeedIndices: rt.array(rt.string), + datafeedState: datafeedStateRT, + fullJob: rt.partial({ + custom_settings: jobCustomSettingsRT, + finished_time: rt.number, + model_size_stats: jobModelSizeStatsRT, + }), + }), +]); + +export type JobSummary = rt.TypeOf; + +export const fetchJobStatusResponsePayloadRT = rt.array(jobSummaryRT); + +export type FetchJobStatusResponsePayload = rt.TypeOf; diff --git a/x-pack/plugins/infra/public/containers/ml/api/ml_get_module.ts b/x-pack/plugins/infra/public/containers/ml/api/ml_get_module.ts new file mode 100644 index 00000000000000..d492522c120a11 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/api/ml_get_module.ts @@ -0,0 +1,41 @@ +/* + * 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 { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; +import * as rt from 'io-ts'; +import { npStart } from '../../../legacy_singletons'; + +import { jobCustomSettingsRT } from '../../../../common/log_analysis'; +import { createPlainError, throwErrors } from '../../../../common/runtime_types'; + +export const callGetMlModuleAPI = async (moduleId: string) => { + const response = await npStart.http.fetch(`/api/ml/modules/get_module/${moduleId}`, { + method: 'GET', + }); + + return pipe( + getMlModuleResponsePayloadRT.decode(response), + fold(throwErrors(createPlainError), identity) + ); +}; + +const jobDefinitionRT = rt.type({ + id: rt.string, + config: rt.type({ + custom_settings: jobCustomSettingsRT, + }), +}); + +export type JobDefinition = rt.TypeOf; + +const getMlModuleResponsePayloadRT = rt.type({ + id: rt.string, + jobs: rt.array(jobDefinitionRT), +}); + +export type GetMlModuleResponsePayload = rt.TypeOf; diff --git a/x-pack/plugins/infra/public/containers/ml/api/ml_setup_module_api.ts b/x-pack/plugins/infra/public/containers/ml/api/ml_setup_module_api.ts new file mode 100644 index 00000000000000..06b0e075387b01 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/api/ml_setup_module_api.ts @@ -0,0 +1,115 @@ +/* + * 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 { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; +import * as rt from 'io-ts'; +import { npStart } from '../../../legacy_singletons'; + +import { getJobIdPrefix, jobCustomSettingsRT } from '../../../../common/infra_ml'; +import { createPlainError, throwErrors } from '../../../../common/runtime_types'; + +export const callSetupMlModuleAPI = async ( + moduleId: string, + start: number | undefined, + end: number | undefined, + spaceId: string, + sourceId: string, + indexPattern: string, + jobOverrides: SetupMlModuleJobOverrides[] = [], + datafeedOverrides: SetupMlModuleDatafeedOverrides[] = [], + query?: object +) => { + const response = await npStart.http.fetch(`/api/ml/modules/setup/${moduleId}`, { + method: 'POST', + body: JSON.stringify( + setupMlModuleRequestPayloadRT.encode({ + start, + end, + indexPatternName: indexPattern, + prefix: getJobIdPrefix(spaceId, sourceId), + startDatafeed: true, + jobOverrides, + datafeedOverrides, + query, + }) + ), + }); + + return pipe( + setupMlModuleResponsePayloadRT.decode(response), + fold(throwErrors(createPlainError), identity) + ); +}; + +const setupMlModuleTimeParamsRT = rt.partial({ + start: rt.number, + end: rt.number, +}); + +const setupMlModuleJobOverridesRT = rt.type({ + job_id: rt.string, + custom_settings: jobCustomSettingsRT, +}); + +export type SetupMlModuleJobOverrides = rt.TypeOf; + +const setupMlModuleDatafeedOverridesRT = rt.object; + +export type SetupMlModuleDatafeedOverrides = rt.TypeOf; + +const setupMlModuleRequestParamsRT = rt.intersection([ + rt.strict({ + indexPatternName: rt.string, + prefix: rt.string, + startDatafeed: rt.boolean, + jobOverrides: rt.array(setupMlModuleJobOverridesRT), + datafeedOverrides: rt.array(setupMlModuleDatafeedOverridesRT), + }), + rt.exact( + rt.partial({ + query: rt.object, + }) + ), +]); + +const setupMlModuleRequestPayloadRT = rt.intersection([ + setupMlModuleTimeParamsRT, + setupMlModuleRequestParamsRT, +]); + +const setupErrorResponseRT = rt.type({ + msg: rt.string, +}); + +const datafeedSetupResponseRT = rt.intersection([ + rt.type({ + id: rt.string, + started: rt.boolean, + success: rt.boolean, + }), + rt.partial({ + error: setupErrorResponseRT, + }), +]); + +const jobSetupResponseRT = rt.intersection([ + rt.type({ + id: rt.string, + success: rt.boolean, + }), + rt.partial({ + error: setupErrorResponseRT, + }), +]); + +const setupMlModuleResponsePayloadRT = rt.type({ + datafeeds: rt.array(datafeedSetupResponseRT), + jobs: rt.array(jobSetupResponseRT), +}); + +export type SetupMlModuleResponsePayload = rt.TypeOf; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx new file mode 100644 index 00000000000000..f4c90a459af6ac --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_capabilities.tsx @@ -0,0 +1,97 @@ +/* + * 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 createContainer from 'constate'; +import { useMemo, useState, useEffect } from 'react'; +import { fold } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { identity } from 'fp-ts/lib/function'; +import { useTrackedPromise } from '../../utils/use_tracked_promise'; +import { npStart } from '../../legacy_singletons'; +import { + getMlCapabilitiesResponsePayloadRT, + GetMlCapabilitiesResponsePayload, +} from './api/ml_api_types'; +import { throwErrors, createPlainError } from '../../../common/runtime_types'; + +export const useInfraMLCapabilities = () => { + const [mlCapabilities, setMlCapabilities] = useState( + initialMlCapabilities + ); + + const [fetchMlCapabilitiesRequest, fetchMlCapabilities] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + const rawResponse = await npStart.http.fetch('/api/ml/ml_capabilities'); + + return pipe( + getMlCapabilitiesResponsePayloadRT.decode(rawResponse), + fold(throwErrors(createPlainError), identity) + ); + }, + onResolve: (response) => { + setMlCapabilities(response); + }, + }, + [] + ); + + useEffect(() => { + fetchMlCapabilities(); + }, [fetchMlCapabilities]); + + const isLoading = useMemo(() => fetchMlCapabilitiesRequest.state === 'pending', [ + fetchMlCapabilitiesRequest.state, + ]); + + const hasInfraMLSetupCapabilities = mlCapabilities.capabilities.canCreateJob; + const hasInfraMLReadCapabilities = mlCapabilities.capabilities.canGetJobs; + const hasInfraMLCapabilites = + mlCapabilities.isPlatinumOrTrialLicense && mlCapabilities.mlFeatureEnabledInSpace; + + return { + hasInfraMLCapabilites, + hasInfraMLReadCapabilities, + hasInfraMLSetupCapabilities, + isLoading, + }; +}; + +export const [InfraMLCapabilitiesProvider, useInfraMLCapabilitiesContext] = createContainer( + useInfraMLCapabilities +); + +const initialMlCapabilities = { + capabilities: { + canGetJobs: false, + canCreateJob: false, + canDeleteJob: false, + canOpenJob: false, + canCloseJob: false, + canForecastJob: false, + canGetDatafeeds: false, + canStartStopDatafeed: false, + canUpdateJob: false, + canUpdateDatafeed: false, + canPreviewDatafeed: false, + canGetCalendars: false, + canCreateCalendar: false, + canDeleteCalendar: false, + canGetFilters: false, + canCreateFilter: false, + canDeleteFilter: false, + canFindFileStructure: false, + canGetDataFrameJobs: false, + canDeleteDataFrameJob: false, + canPreviewDataFrameJob: false, + canCreateDataFrameJob: false, + canStartStopDataFrameJob: false, + }, + isPlatinumOrTrialLicense: false, + mlFeatureEnabledInSpace: false, + upgradeInProgress: false, +}; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx new file mode 100644 index 00000000000000..736982c8043b14 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx @@ -0,0 +1,55 @@ +/* + * 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 { getJobId } from '../../../common/infra_ml'; +import { callDeleteJobs, callGetJobDeletionTasks, callStopDatafeeds } from './api/ml_cleanup'; + +export const cleanUpJobsAndDatafeeds = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + try { + await callStopDatafeeds(spaceId, sourceId, jobTypes); + } catch (err) { + // Proceed only if datafeed has been deleted or didn't exist in the first place + if (err?.res?.status !== 404) { + throw err; + } + } + + return await deleteJobs(spaceId, sourceId, jobTypes); +}; + +const deleteJobs = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + const deleteJobsResponse = await callDeleteJobs(spaceId, sourceId, jobTypes); + await waitUntilJobsAreDeleted(spaceId, sourceId, jobTypes); + return deleteJobsResponse; +}; + +const waitUntilJobsAreDeleted = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + const moduleJobIds = jobTypes.map((jobType) => getJobId(spaceId, sourceId, jobType)); + while (true) { + const { jobIds: jobIdsBeingDeleted } = await callGetJobDeletionTasks(); + const needToWait = jobIdsBeingDeleted.some((jobId) => moduleJobIds.includes(jobId)); + + if (needToWait) { + await timeout(1000); + } else { + return true; + } + } +}; + +const timeout = (ms: number) => new Promise((res) => setTimeout(res, ms)); diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx new file mode 100644 index 00000000000000..349541d108f5ed --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx @@ -0,0 +1,147 @@ +/* + * 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 { useCallback, useMemo } from 'react'; +import { DatasetFilter } from '../../../common/infra_ml'; +import { useTrackedPromise } from '../../utils/use_tracked_promise'; +import { useModuleStatus } from './infra_ml_module_status'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './infra_ml_module_types'; + +export const useInfraMLModule = ({ + sourceConfiguration, + moduleDescriptor, +}: { + sourceConfiguration: ModuleSourceConfiguration; + moduleDescriptor: ModuleDescriptor; +}) => { + const { spaceId, sourceId, timestampField } = sourceConfiguration; + const [moduleStatus, dispatchModuleStatus] = useModuleStatus(moduleDescriptor.jobTypes); + + const [, fetchJobStatus] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + dispatchModuleStatus({ type: 'fetchingJobStatuses' }); + return await moduleDescriptor.getJobSummary(spaceId, sourceId); + }, + onResolve: (jobResponse) => { + dispatchModuleStatus({ + type: 'fetchedJobStatuses', + payload: jobResponse, + spaceId, + sourceId, + }); + }, + onReject: () => { + dispatchModuleStatus({ type: 'failedFetchingJobStatuses' }); + }, + }, + [spaceId, sourceId] + ); + + const [, setUpModule] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async ( + selectedIndices: string[], + start: number | undefined, + end: number | undefined, + datasetFilter: DatasetFilter, + partitionField?: string + ) => { + dispatchModuleStatus({ type: 'startedSetup' }); + const setupResult = await moduleDescriptor.setUpModule( + start, + end, + datasetFilter, + { + indices: selectedIndices, + sourceId, + spaceId, + timestampField, + }, + partitionField + ); + const jobSummaries = await moduleDescriptor.getJobSummary(spaceId, sourceId); + return { setupResult, jobSummaries }; + }, + onResolve: ({ setupResult: { datafeeds, jobs }, jobSummaries }) => { + dispatchModuleStatus({ + type: 'finishedSetup', + datafeedSetupResults: datafeeds, + jobSetupResults: jobs, + jobSummaries, + spaceId, + sourceId, + }); + }, + onReject: () => { + dispatchModuleStatus({ type: 'failedSetup' }); + }, + }, + [moduleDescriptor.setUpModule, spaceId, sourceId, timestampField] + ); + + const [cleanUpModuleRequest, cleanUpModule] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await moduleDescriptor.cleanUpModule(spaceId, sourceId); + }, + }, + [spaceId, sourceId] + ); + + const isCleaningUp = useMemo(() => cleanUpModuleRequest.state === 'pending', [ + cleanUpModuleRequest.state, + ]); + + const cleanUpAndSetUpModule = useCallback( + ( + selectedIndices: string[], + start: number | undefined, + end: number | undefined, + datasetFilter: DatasetFilter, + partitionField?: string + ) => { + dispatchModuleStatus({ type: 'startedSetup' }); + cleanUpModule() + .then(() => { + setUpModule(selectedIndices, start, end, datasetFilter, partitionField); + }) + .catch(() => { + dispatchModuleStatus({ type: 'failedSetup' }); + }); + }, + [cleanUpModule, dispatchModuleStatus, setUpModule] + ); + + const viewResults = useCallback(() => { + dispatchModuleStatus({ type: 'viewedResults' }); + }, [dispatchModuleStatus]); + + const jobIds = useMemo(() => moduleDescriptor.getJobIds(spaceId, sourceId), [ + moduleDescriptor, + spaceId, + sourceId, + ]); + + return { + cleanUpAndSetUpModule, + cleanUpModule, + fetchJobStatus, + isCleaningUp, + jobIds, + jobStatus: moduleStatus.jobStatus, + jobSummaries: moduleStatus.jobSummaries, + lastSetupErrorMessages: moduleStatus.lastSetupErrorMessages, + moduleDescriptor, + setUpModule, + setupStatus: moduleStatus.setupStatus, + sourceConfiguration, + viewResults, + }; +}; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_configuration.ts b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_configuration.ts new file mode 100644 index 00000000000000..2d90f5d5310109 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_configuration.ts @@ -0,0 +1,52 @@ +/* + * 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 { useMemo } from 'react'; +import { JobSummary } from './api/ml_get_jobs_summary_api'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './infra_ml_module_types'; + +export const useInfraMLModuleConfiguration = ({ + moduleDescriptor, + sourceConfiguration, +}: { + moduleDescriptor: ModuleDescriptor; + sourceConfiguration: ModuleSourceConfiguration; +}) => { + const getIsJobConfigurationOutdated = useMemo( + () => isJobConfigurationOutdated(moduleDescriptor, sourceConfiguration), + [sourceConfiguration, moduleDescriptor] + ); + + return { + getIsJobConfigurationOutdated, + }; +}; + +export const isJobConfigurationOutdated = ( + { bucketSpan }: ModuleDescriptor, + currentSourceConfiguration: ModuleSourceConfiguration +) => (jobSummary: JobSummary): boolean => { + if (!jobSummary.fullJob || !jobSummary.fullJob.custom_settings) { + return false; + } + + const jobConfiguration = jobSummary.fullJob.custom_settings.metrics_source_config; + + return !( + jobConfiguration && + jobConfiguration.bucketSpan === bucketSpan && + jobConfiguration.indexPattern && + isSubset( + new Set(jobConfiguration.indexPattern.split(',')), + new Set(currentSourceConfiguration.indices) + ) && + jobConfiguration.timestampField === currentSourceConfiguration.timestampField + ); +}; + +const isSubset = (subset: Set, superset: Set) => { + return Array.from(subset).every((subsetElement) => superset.has(subsetElement)); +}; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_definition.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_definition.tsx new file mode 100644 index 00000000000000..3c7ffcfd4a4e25 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_definition.tsx @@ -0,0 +1,76 @@ +/* + * 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 { useCallback, useMemo, useState } from 'react'; +import { getJobId } from '../../../common/log_analysis'; +import { useTrackedPromise } from '../../utils/use_tracked_promise'; +import { JobSummary } from './api/ml_get_jobs_summary_api'; +import { GetMlModuleResponsePayload, JobDefinition } from './api/ml_get_module'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './infra_ml_module_types'; + +export const useInfraMLModuleDefinition = ({ + sourceConfiguration: { spaceId, sourceId }, + moduleDescriptor, +}: { + sourceConfiguration: ModuleSourceConfiguration; + moduleDescriptor: ModuleDescriptor; +}) => { + const [moduleDefinition, setModuleDefinition] = useState< + GetMlModuleResponsePayload | undefined + >(); + + const jobDefinitionByJobId = useMemo( + () => + moduleDefinition + ? moduleDefinition.jobs.reduce>( + (accumulatedJobDefinitions, jobDefinition) => ({ + ...accumulatedJobDefinitions, + [getJobId(spaceId, sourceId, jobDefinition.id)]: jobDefinition, + }), + {} + ) + : {}, + [moduleDefinition, sourceId, spaceId] + ); + + const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await moduleDescriptor.getModuleDefinition(); + }, + onResolve: (response) => { + setModuleDefinition(response); + }, + onReject: () => { + setModuleDefinition(undefined); + }, + }, + [moduleDescriptor.getModuleDefinition, spaceId, sourceId] + ); + + const getIsJobDefinitionOutdated = useCallback( + (jobSummary: JobSummary): boolean => { + const jobDefinition: JobDefinition | undefined = jobDefinitionByJobId[jobSummary.id]; + + if (jobDefinition == null) { + return false; + } + + const currentRevision = jobDefinition?.config.custom_settings.job_revision; + return (jobSummary.fullJob?.custom_settings?.job_revision ?? 0) < (currentRevision ?? 0); + }, + [jobDefinitionByJobId] + ); + + return { + fetchModuleDefinition, + fetchModuleDefinitionRequestState: fetchModuleDefinitionRequest.state, + getIsJobDefinitionOutdated, + jobDefinitionByJobId, + moduleDefinition, + }; +}; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx new file mode 100644 index 00000000000000..63d479546b44ff --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx @@ -0,0 +1,268 @@ +/* + * 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 { useReducer } from 'react'; + +import { + JobStatus, + getDatafeedId, + getJobId, + isJobStatusWithResults, + SetupStatus, +} from '../../../common/infra_ml'; +import { FetchJobStatusResponsePayload, JobSummary } from './api/ml_get_jobs_summary_api'; +import { SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; +import { MandatoryProperty } from '../../../common/utility_types'; + +interface StatusReducerState { + jobStatus: Record; + jobSummaries: JobSummary[]; + lastSetupErrorMessages: string[]; + setupStatus: SetupStatus; +} + +type StatusReducerAction = + | { type: 'startedSetup' } + | { + type: 'finishedSetup'; + sourceId: string; + spaceId: string; + jobSetupResults: SetupMlModuleResponsePayload['jobs']; + jobSummaries: FetchJobStatusResponsePayload; + datafeedSetupResults: SetupMlModuleResponsePayload['datafeeds']; + } + | { type: 'failedSetup' } + | { type: 'fetchingJobStatuses' } + | { + type: 'fetchedJobStatuses'; + spaceId: string; + sourceId: string; + payload: FetchJobStatusResponsePayload; + } + | { type: 'failedFetchingJobStatuses' } + | { type: 'viewedResults' }; + +const createInitialState = ({ + jobTypes, +}: { + jobTypes: JobType[]; +}): StatusReducerState => ({ + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'unknown', + }), + {} as Record + ), + jobSummaries: [], + lastSetupErrorMessages: [], + setupStatus: { type: 'initializing' }, +}); + +const createStatusReducer = (jobTypes: JobType[]) => ( + state: StatusReducerState, + action: StatusReducerAction +): StatusReducerState => { + switch (action.type) { + case 'startedSetup': { + return { + ...state, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'initializing', + }), + {} as Record + ), + setupStatus: { type: 'pending' }, + }; + } + case 'finishedSetup': { + const { datafeedSetupResults, jobSetupResults, jobSummaries, spaceId, sourceId } = action; + const nextJobStatus = jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: + hasSuccessfullyCreatedJob(getJobId(spaceId, sourceId, jobType))(jobSetupResults) && + hasSuccessfullyStartedDatafeed(getDatafeedId(spaceId, sourceId, jobType))( + datafeedSetupResults + ) + ? 'started' + : 'failed', + }), + {} as Record + ); + const nextSetupStatus: SetupStatus = Object.values(nextJobStatus).every( + (jobState) => jobState === 'started' + ) + ? { type: 'succeeded' } + : { + type: 'failed', + reasons: [ + ...Object.values(datafeedSetupResults) + .filter(hasError) + .map((datafeed) => datafeed.error.msg), + ...Object.values(jobSetupResults) + .filter(hasError) + .map((job) => job.error.msg), + ], + }; + + return { + ...state, + jobStatus: nextJobStatus, + jobSummaries, + setupStatus: nextSetupStatus, + }; + } + case 'failedSetup': { + return { + ...state, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'failed', + }), + {} as Record + ), + setupStatus: { type: 'failed', reasons: ['unknown'] }, + }; + } + case 'fetchingJobStatuses': { + return { + ...state, + setupStatus: + state.setupStatus.type === 'unknown' ? { type: 'initializing' } : state.setupStatus, + }; + } + case 'fetchedJobStatuses': { + const { payload: jobSummaries, spaceId, sourceId } = action; + const { setupStatus } = state; + const nextJobStatus = jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: getJobStatus(getJobId(spaceId, sourceId, jobType))(jobSummaries), + }), + {} as Record + ); + const nextSetupStatus = getSetupStatus(nextJobStatus)(setupStatus); + + return { + ...state, + jobSummaries, + jobStatus: nextJobStatus, + setupStatus: nextSetupStatus, + }; + } + case 'failedFetchingJobStatuses': { + return { + ...state, + setupStatus: { type: 'unknown' }, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'unknown', + }), + {} as Record + ), + }; + } + case 'viewedResults': { + return { + ...state, + setupStatus: { type: 'skipped', newlyCreated: true }, + }; + } + default: { + return state; + } + } +}; + +const hasSuccessfullyCreatedJob = (jobId: string) => ( + jobSetupResponses: SetupMlModuleResponsePayload['jobs'] +) => + jobSetupResponses.filter( + (jobSetupResponse) => + jobSetupResponse.id === jobId && jobSetupResponse.success && !jobSetupResponse.error + ).length > 0; + +const hasSuccessfullyStartedDatafeed = (datafeedId: string) => ( + datafeedSetupResponses: SetupMlModuleResponsePayload['datafeeds'] +) => + datafeedSetupResponses.filter( + (datafeedSetupResponse) => + datafeedSetupResponse.id === datafeedId && + datafeedSetupResponse.success && + datafeedSetupResponse.started && + !datafeedSetupResponse.error + ).length > 0; + +const getJobStatus = (jobId: string) => ( + jobSummaries: FetchJobStatusResponsePayload +): JobStatus => { + return ( + jobSummaries + .filter((jobSummary) => jobSummary.id === jobId) + .map( + (jobSummary): JobStatus => { + if (jobSummary.jobState === 'failed' || jobSummary.datafeedState === '') { + return 'failed'; + } else if ( + jobSummary.jobState === 'closed' && + jobSummary.datafeedState === 'stopped' && + jobSummary.fullJob && + jobSummary.fullJob.finished_time != null + ) { + return 'finished'; + } else if ( + jobSummary.jobState === 'closed' || + jobSummary.jobState === 'closing' || + jobSummary.datafeedState === 'stopped' + ) { + return 'stopped'; + } else if (jobSummary.jobState === 'opening') { + return 'initializing'; + } else if (jobSummary.jobState === 'opened' && jobSummary.datafeedState === 'started') { + return 'started'; + } + + return 'unknown'; + } + )[0] || 'missing' + ); +}; + +const getSetupStatus = (everyJobStatus: Record) => ( + previousSetupStatus: SetupStatus +): SetupStatus => { + return Object.entries(everyJobStatus).reduce( + (setupStatus, [, jobStatus]) => { + if (jobStatus === 'missing') { + return { type: 'required' }; + } else if (setupStatus.type === 'required' || setupStatus.type === 'succeeded') { + return setupStatus; + } else if (setupStatus.type === 'skipped' || isJobStatusWithResults(jobStatus)) { + return { + type: 'skipped', + // preserve newlyCreated status + newlyCreated: setupStatus.type === 'skipped' && setupStatus.newlyCreated, + }; + } + + return setupStatus; + }, + previousSetupStatus + ); +}; + +const hasError = ( + value: Value +): value is MandatoryProperty => value.error != null; + +export const useModuleStatus = (jobTypes: JobType[]) => { + return useReducer(createStatusReducer(jobTypes), { jobTypes }, createInitialState); +}; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts new file mode 100644 index 00000000000000..a9f2671de82598 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + ValidateLogEntryDatasetsResponsePayload, + ValidationIndicesResponsePayload, +} from '../../../common/http_api/log_analysis'; +import { DatasetFilter } from '../../../common/infra_ml'; +import { DeleteJobsResponsePayload } from './api/ml_cleanup'; +import { FetchJobStatusResponsePayload } from './api/ml_get_jobs_summary_api'; +import { GetMlModuleResponsePayload } from './api/ml_get_module'; +import { SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; + +export { JobModelSizeStats, JobSummary } from './api/ml_get_jobs_summary_api'; + +export interface ModuleDescriptor { + moduleId: string; + moduleName: string; + moduleDescription: string; + jobTypes: JobType[]; + bucketSpan: number; + getJobIds: (spaceId: string, sourceId: string) => Record; + getJobSummary: (spaceId: string, sourceId: string) => Promise; + getModuleDefinition: () => Promise; + setUpModule: ( + start: number | undefined, + end: number | undefined, + datasetFilter: DatasetFilter, + sourceConfiguration: ModuleSourceConfiguration, + partitionField?: string + ) => Promise; + cleanUpModule: (spaceId: string, sourceId: string) => Promise; + validateSetupIndices: ( + indices: string[], + timestampField: string + ) => Promise; + validateSetupDatasets: ( + indices: string[], + timestampField: string, + startTime: number, + endTime: number + ) => Promise; +} + +export interface ModuleSourceConfiguration { + indices: string[]; + sourceId: string; + spaceId: string; + timestampField: string; +} + +interface ManyCategoriesWarningReason { + type: 'manyCategories'; + categoriesDocumentRatio: number; +} + +interface ManyDeadCategoriesWarningReason { + type: 'manyDeadCategories'; + deadCategoriesRatio: number; +} + +interface ManyRareCategoriesWarningReason { + type: 'manyRareCategories'; + rareCategoriesRatio: number; +} + +interface NoFrequentCategoriesWarningReason { + type: 'noFrequentCategories'; +} + +interface SingleCategoryWarningReason { + type: 'singleCategory'; +} + +export type CategoryQualityWarningReason = + | ManyCategoriesWarningReason + | ManyDeadCategoriesWarningReason + | ManyRareCategoriesWarningReason + | NoFrequentCategoriesWarningReason + | SingleCategoryWarningReason; + +export type CategoryQualityWarningReasonType = CategoryQualityWarningReason['type']; + +export interface CategoryQualityWarning { + type: 'categoryQualityWarning'; + jobId: string; + reasons: CategoryQualityWarningReason[]; +} + +export type QualityWarning = CategoryQualityWarning; diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts b/x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts new file mode 100644 index 00000000000000..0dfe3b301f2400 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts @@ -0,0 +1,289 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { isEqual } from 'lodash'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { usePrevious } from 'react-use'; +import { + combineDatasetFilters, + DatasetFilter, + filterDatasetFilter, + isExampleDataIndex, +} from '../../../common/infra_ml'; +import { + AvailableIndex, + ValidationIndicesError, + ValidationUIError, +} from '../../components/logging/log_analysis_setup/initial_configuration_step'; +import { useTrackedPromise } from '../../utils/use_tracked_promise'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './infra_ml_module_types'; + +type SetupHandler = ( + indices: string[], + startTime: number | undefined, + endTime: number | undefined, + datasetFilter: DatasetFilter +) => void; + +interface AnalysisSetupStateArguments { + cleanUpAndSetUpModule: SetupHandler; + moduleDescriptor: ModuleDescriptor; + setUpModule: SetupHandler; + sourceConfiguration: ModuleSourceConfiguration; +} + +const fourWeeksInMs = 86400000 * 7 * 4; + +export const useAnalysisSetupState = ({ + cleanUpAndSetUpModule, + moduleDescriptor: { validateSetupDatasets, validateSetupIndices }, + setUpModule, + sourceConfiguration, +}: AnalysisSetupStateArguments) => { + const [startTime, setStartTime] = useState(Date.now() - fourWeeksInMs); + const [endTime, setEndTime] = useState(undefined); + + const isTimeRangeValid = useMemo( + () => (startTime != null && endTime != null ? startTime < endTime : true), + [endTime, startTime] + ); + + const [validatedIndices, setValidatedIndices] = useState( + sourceConfiguration.indices.map((indexName) => ({ + name: indexName, + validity: 'unknown' as const, + })) + ); + + const updateIndicesWithValidationErrors = useCallback( + (validationErrors: ValidationIndicesError[]) => + setValidatedIndices((availableIndices) => + availableIndices.map((previousAvailableIndex) => { + const indexValiationErrors = validationErrors.filter( + ({ index }) => index === previousAvailableIndex.name + ); + + if (indexValiationErrors.length > 0) { + return { + validity: 'invalid', + name: previousAvailableIndex.name, + errors: indexValiationErrors, + }; + } else if (previousAvailableIndex.validity === 'valid') { + return { + ...previousAvailableIndex, + validity: 'valid', + errors: [], + }; + } else { + return { + validity: 'valid', + name: previousAvailableIndex.name, + isSelected: !isExampleDataIndex(previousAvailableIndex.name), + availableDatasets: [], + datasetFilter: { + type: 'includeAll' as const, + }, + }; + } + }) + ), + [] + ); + + const updateIndicesWithAvailableDatasets = useCallback( + (availableDatasets: Array<{ indexName: string; datasets: string[] }>) => + setValidatedIndices((availableIndices) => + availableIndices.map((previousAvailableIndex) => { + if (previousAvailableIndex.validity !== 'valid') { + return previousAvailableIndex; + } + + const availableDatasetsForIndex = availableDatasets.filter( + ({ indexName }) => indexName === previousAvailableIndex.name + ); + const newAvailableDatasets = availableDatasetsForIndex.flatMap( + ({ datasets }) => datasets + ); + + // filter out datasets that have disappeared if this index' datasets were updated + const newDatasetFilter: DatasetFilter = + availableDatasetsForIndex.length > 0 + ? filterDatasetFilter(previousAvailableIndex.datasetFilter, (dataset) => + newAvailableDatasets.includes(dataset) + ) + : previousAvailableIndex.datasetFilter; + + return { + ...previousAvailableIndex, + availableDatasets: newAvailableDatasets, + datasetFilter: newDatasetFilter, + }; + }) + ), + [] + ); + + const validIndexNames = useMemo( + () => validatedIndices.filter((index) => index.validity === 'valid').map((index) => index.name), + [validatedIndices] + ); + + const selectedIndexNames = useMemo( + () => + validatedIndices + .filter((index) => index.validity === 'valid' && index.isSelected) + .map((i) => i.name), + [validatedIndices] + ); + + const datasetFilter = useMemo( + () => + validatedIndices + .flatMap((validatedIndex) => + validatedIndex.validity === 'valid' + ? validatedIndex.datasetFilter + : { type: 'includeAll' as const } + ) + .reduce(combineDatasetFilters, { type: 'includeAll' as const }), + [validatedIndices] + ); + + const [validateIndicesRequest, validateIndices] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await validateSetupIndices( + sourceConfiguration.indices, + sourceConfiguration.timestampField + ); + }, + onResolve: ({ data: { errors } }) => { + updateIndicesWithValidationErrors(errors); + }, + onReject: () => { + setValidatedIndices([]); + }, + }, + [sourceConfiguration.indices, sourceConfiguration.timestampField] + ); + + const [validateDatasetsRequest, validateDatasets] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + if (validIndexNames.length === 0) { + return { data: { datasets: [] } }; + } + + return await validateSetupDatasets( + validIndexNames, + sourceConfiguration.timestampField, + startTime ?? 0, + endTime ?? Date.now() + ); + }, + onResolve: ({ data: { datasets } }) => { + updateIndicesWithAvailableDatasets(datasets); + }, + }, + [validIndexNames, sourceConfiguration.timestampField, startTime, endTime] + ); + + const setUp = useCallback(() => { + return setUpModule(selectedIndexNames, startTime, endTime, datasetFilter); + }, [setUpModule, selectedIndexNames, startTime, endTime, datasetFilter]); + + const cleanUpAndSetUp = useCallback(() => { + return cleanUpAndSetUpModule(selectedIndexNames, startTime, endTime, datasetFilter); + }, [cleanUpAndSetUpModule, selectedIndexNames, startTime, endTime, datasetFilter]); + + const isValidating = useMemo( + () => validateIndicesRequest.state === 'pending' || validateDatasetsRequest.state === 'pending', + [validateDatasetsRequest.state, validateIndicesRequest.state] + ); + + const validationErrors = useMemo(() => { + if (isValidating) { + return []; + } + + return [ + // validate request status + ...(validateIndicesRequest.state === 'rejected' || + validateDatasetsRequest.state === 'rejected' + ? [{ error: 'NETWORK_ERROR' as const }] + : []), + // validation request results + ...validatedIndices.reduce((errors, index) => { + return index.validity === 'invalid' && selectedIndexNames.includes(index.name) + ? [...errors, ...index.errors] + : errors; + }, []), + // index count + ...(selectedIndexNames.length === 0 ? [{ error: 'TOO_FEW_SELECTED_INDICES' as const }] : []), + // time range + ...(!isTimeRangeValid ? [{ error: 'INVALID_TIME_RANGE' as const }] : []), + ]; + }, [ + isValidating, + validateIndicesRequest.state, + validateDatasetsRequest.state, + validatedIndices, + selectedIndexNames, + isTimeRangeValid, + ]); + + const prevStartTime = usePrevious(startTime); + const prevEndTime = usePrevious(endTime); + const prevValidIndexNames = usePrevious(validIndexNames); + + useEffect(() => { + if (!isTimeRangeValid) { + return; + } + + validateIndices(); + }, [isTimeRangeValid, validateIndices]); + + useEffect(() => { + if (!isTimeRangeValid) { + return; + } + + if ( + startTime !== prevStartTime || + endTime !== prevEndTime || + !isEqual(validIndexNames, prevValidIndexNames) + ) { + validateDatasets(); + } + }, [ + endTime, + isTimeRangeValid, + prevEndTime, + prevStartTime, + prevValidIndexNames, + startTime, + validIndexNames, + validateDatasets, + ]); + + return { + cleanUpAndSetUp, + datasetFilter, + endTime, + isValidating, + selectedIndexNames, + setEndTime, + setStartTime, + setUp, + startTime, + validatedIndices, + setValidatedIndices, + validationErrors, + }; +}; diff --git a/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module.tsx b/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module.tsx new file mode 100644 index 00000000000000..9c065f3e91bc49 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module.tsx @@ -0,0 +1,80 @@ +/* + * 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 createContainer from 'constate'; +import { useMemo } from 'react'; +import { useInfraMLModule } from '../../infra_ml_module'; +import { useInfraMLModuleConfiguration } from '../../infra_ml_module_configuration'; +import { useInfraMLModuleDefinition } from '../../infra_ml_module_definition'; +import { ModuleSourceConfiguration } from '../../infra_ml_module_types'; +import { metricHostsModule } from './module_descriptor'; + +export const useMetricHostsModule = ({ + indexPattern, + sourceId, + spaceId, + timestampField, +}: { + indexPattern: string; + sourceId: string; + spaceId: string; + timestampField: string; +}) => { + const sourceConfiguration: ModuleSourceConfiguration = useMemo( + () => ({ + indices: indexPattern.split(','), + sourceId, + spaceId, + timestampField, + }), + [indexPattern, sourceId, spaceId, timestampField] + ); + + const infraMLModule = useInfraMLModule({ + moduleDescriptor: metricHostsModule, + sourceConfiguration, + }); + + const { getIsJobConfigurationOutdated } = useInfraMLModuleConfiguration({ + sourceConfiguration, + moduleDescriptor: metricHostsModule, + }); + + const { fetchModuleDefinition, getIsJobDefinitionOutdated } = useInfraMLModuleDefinition({ + sourceConfiguration, + moduleDescriptor: metricHostsModule, + }); + + const hasOutdatedJobConfigurations = useMemo( + () => infraMLModule.jobSummaries.some(getIsJobConfigurationOutdated), + [getIsJobConfigurationOutdated, infraMLModule.jobSummaries] + ); + + const hasOutdatedJobDefinitions = useMemo( + () => infraMLModule.jobSummaries.some(getIsJobDefinitionOutdated), + [getIsJobDefinitionOutdated, infraMLModule.jobSummaries] + ); + + const hasStoppedJobs = useMemo( + () => + Object.values(infraMLModule.jobStatus).some( + (currentJobStatus) => currentJobStatus === 'stopped' + ), + [infraMLModule.jobStatus] + ); + + return { + ...infraMLModule, + fetchModuleDefinition, + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, + }; +}; + +export const [MetricHostsModuleProvider, useMetricHostsModuleContext] = createContainer( + useMetricHostsModule +); diff --git a/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts b/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts new file mode 100644 index 00000000000000..cec87fb1144e33 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { ModuleDescriptor, ModuleSourceConfiguration } from '../../infra_ml_module_types'; +import { cleanUpJobsAndDatafeeds } from '../../infra_ml_cleanup'; +import { callJobsSummaryAPI } from '../../api/ml_get_jobs_summary_api'; +import { callGetMlModuleAPI } from '../../api/ml_get_module'; +import { callSetupMlModuleAPI } from '../../api/ml_setup_module_api'; +import { callValidateIndicesAPI } from '../../../logs/log_analysis/api/validate_indices'; +import { callValidateDatasetsAPI } from '../../../logs/log_analysis/api/validate_datasets'; +import { + metricsHostsJobTypes, + getJobId, + MetricsHostsJobType, + DatasetFilter, + bucketSpan, + partitionField, +} from '../../../../../common/infra_ml'; + +const moduleId = 'metrics_ui_hosts'; +const moduleName = i18n.translate('xpack.infra.ml.metricsModuleName', { + defaultMessage: 'Metrics anomanly detection', +}); +const moduleDescription = i18n.translate('xpack.infra.ml.metricsHostModuleDescription', { + defaultMessage: 'Use Machine Learning to automatically detect anomalous log entry rates.', +}); + +const getJobIds = (spaceId: string, sourceId: string) => + metricsHostsJobTypes.reduce( + (accumulatedJobIds, jobType) => ({ + ...accumulatedJobIds, + [jobType]: getJobId(spaceId, sourceId, jobType), + }), + {} as Record + ); + +const getJobSummary = async (spaceId: string, sourceId: string) => { + const response = await callJobsSummaryAPI(spaceId, sourceId, metricsHostsJobTypes); + const jobIds = Object.values(getJobIds(spaceId, sourceId)); + + return response.filter((jobSummary) => jobIds.includes(jobSummary.id)); +}; + +const getModuleDefinition = async () => { + return await callGetMlModuleAPI(moduleId); +}; + +const setUpModule = async ( + start: number | undefined, + end: number | undefined, + datasetFilter: DatasetFilter, + { spaceId, sourceId, indices, timestampField }: ModuleSourceConfiguration, + pField?: string +) => { + const indexNamePattern = indices.join(','); + const jobIds = ['hosts_memory_usage', 'hosts_network_in', 'hosts_network_out']; + const jobOverrides = jobIds.map((id) => ({ + job_id: id, + data_description: { + time_field: timestampField, + }, + custom_settings: { + metrics_source_config: { + indexPattern: indexNamePattern, + timestampField, + bucketSpan, + }, + }, + })); + + return callSetupMlModuleAPI( + moduleId, + start, + end, + spaceId, + sourceId, + indexNamePattern, + jobOverrides, + [] + ); +}; + +const cleanUpModule = async (spaceId: string, sourceId: string) => { + return await cleanUpJobsAndDatafeeds(spaceId, sourceId, metricsHostsJobTypes); +}; + +const validateSetupIndices = async (indices: string[], timestampField: string) => { + return await callValidateIndicesAPI(indices, [ + { + name: timestampField, + validTypes: ['date'], + }, + { + name: partitionField, + validTypes: ['keyword'], + }, + ]); +}; + +const validateSetupDatasets = async ( + indices: string[], + timestampField: string, + startTime: number, + endTime: number +) => { + return await callValidateDatasetsAPI(indices, timestampField, startTime, endTime); +}; + +export const metricHostsModule: ModuleDescriptor = { + moduleId, + moduleName, + moduleDescription, + jobTypes: metricsHostsJobTypes, + bucketSpan, + getJobIds, + getJobSummary, + getModuleDefinition, + setUpModule, + cleanUpModule, + validateSetupDatasets, + validateSetupIndices, +}; diff --git a/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module.tsx b/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module.tsx new file mode 100644 index 00000000000000..07c8ab02f17ee1 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module.tsx @@ -0,0 +1,80 @@ +/* + * 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 createContainer from 'constate'; +import { useMemo } from 'react'; +import { useInfraMLModule } from '../../infra_ml_module'; +import { useInfraMLModuleConfiguration } from '../../infra_ml_module_configuration'; +import { useInfraMLModuleDefinition } from '../../infra_ml_module_definition'; +import { ModuleSourceConfiguration } from '../../infra_ml_module_types'; +import { metricHostsModule } from './module_descriptor'; + +export const useMetricK8sModule = ({ + indexPattern, + sourceId, + spaceId, + timestampField, +}: { + indexPattern: string; + sourceId: string; + spaceId: string; + timestampField: string; +}) => { + const sourceConfiguration: ModuleSourceConfiguration = useMemo( + () => ({ + indices: indexPattern.split(','), + sourceId, + spaceId, + timestampField, + }), + [indexPattern, sourceId, spaceId, timestampField] + ); + + const infraMLModule = useInfraMLModule({ + moduleDescriptor: metricHostsModule, + sourceConfiguration, + }); + + const { getIsJobConfigurationOutdated } = useInfraMLModuleConfiguration({ + sourceConfiguration, + moduleDescriptor: metricHostsModule, + }); + + const { fetchModuleDefinition, getIsJobDefinitionOutdated } = useInfraMLModuleDefinition({ + sourceConfiguration, + moduleDescriptor: metricHostsModule, + }); + + const hasOutdatedJobConfigurations = useMemo( + () => infraMLModule.jobSummaries.some(getIsJobConfigurationOutdated), + [getIsJobConfigurationOutdated, infraMLModule.jobSummaries] + ); + + const hasOutdatedJobDefinitions = useMemo( + () => infraMLModule.jobSummaries.some(getIsJobDefinitionOutdated), + [getIsJobDefinitionOutdated, infraMLModule.jobSummaries] + ); + + const hasStoppedJobs = useMemo( + () => + Object.values(infraMLModule.jobStatus).some( + (currentJobStatus) => currentJobStatus === 'stopped' + ), + [infraMLModule.jobStatus] + ); + + return { + ...infraMLModule, + fetchModuleDefinition, + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, + }; +}; + +export const [MetricK8sModuleProvider, useMetricK8sModuleContext] = createContainer( + useMetricK8sModule +); diff --git a/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts b/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts new file mode 100644 index 00000000000000..cbcff1c307af6e --- /dev/null +++ b/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { ModuleDescriptor, ModuleSourceConfiguration } from '../../infra_ml_module_types'; +import { cleanUpJobsAndDatafeeds } from '../../infra_ml_cleanup'; +import { callJobsSummaryAPI } from '../../api/ml_get_jobs_summary_api'; +import { callGetMlModuleAPI } from '../../api/ml_get_module'; +import { callSetupMlModuleAPI } from '../../api/ml_setup_module_api'; +import { callValidateIndicesAPI } from '../../../logs/log_analysis/api/validate_indices'; +import { callValidateDatasetsAPI } from '../../../logs/log_analysis/api/validate_datasets'; +import { + metricsK8SJobTypes, + getJobId, + MetricK8sJobType, + DatasetFilter, + bucketSpan, + partitionField, +} from '../../../../../common/infra_ml'; + +const moduleId = 'metrics_ui_k8s'; +const moduleName = i18n.translate('xpack.infra.ml.metricsModuleName', { + defaultMessage: 'Metrics anomanly detection', +}); +const moduleDescription = i18n.translate('xpack.infra.ml.metricsHostModuleDescription', { + defaultMessage: 'Use Machine Learning to automatically detect anomalous log entry rates.', +}); + +const getJobIds = (spaceId: string, sourceId: string) => + metricsK8SJobTypes.reduce( + (accumulatedJobIds, jobType) => ({ + ...accumulatedJobIds, + [jobType]: getJobId(spaceId, sourceId, jobType), + }), + {} as Record + ); + +const getJobSummary = async (spaceId: string, sourceId: string) => { + const response = await callJobsSummaryAPI(spaceId, sourceId, metricsK8SJobTypes); + const jobIds = Object.values(getJobIds(spaceId, sourceId)); + + return response.filter((jobSummary) => jobIds.includes(jobSummary.id)); +}; + +const getModuleDefinition = async () => { + return await callGetMlModuleAPI(moduleId); +}; + +const setUpModule = async ( + start: number | undefined, + end: number | undefined, + datasetFilter: DatasetFilter, + { spaceId, sourceId, indices, timestampField }: ModuleSourceConfiguration, + pField?: string +) => { + const indexNamePattern = indices.join(','); + const jobIds = ['k8s_memory_usage', 'k8s_network_in', 'k8s_network_out']; + const jobOverrides = jobIds.map((id) => ({ + job_id: id, + analysis_config: { + bucket_span: `${bucketSpan}ms`, + }, + data_description: { + time_field: timestampField, + }, + custom_settings: { + metrics_source_config: { + indexPattern: indexNamePattern, + timestampField, + bucketSpan, + }, + }, + })); + + return callSetupMlModuleAPI( + moduleId, + start, + end, + spaceId, + sourceId, + indexNamePattern, + jobOverrides, + [] + ); +}; + +const cleanUpModule = async (spaceId: string, sourceId: string) => { + return await cleanUpJobsAndDatafeeds(spaceId, sourceId, metricsK8SJobTypes); +}; + +const validateSetupIndices = async (indices: string[], timestampField: string) => { + return await callValidateIndicesAPI(indices, [ + { + name: timestampField, + validTypes: ['date'], + }, + { + name: partitionField, + validTypes: ['keyword'], + }, + ]); +}; + +const validateSetupDatasets = async ( + indices: string[], + timestampField: string, + startTime: number, + endTime: number +) => { + return await callValidateDatasetsAPI(indices, timestampField, startTime, endTime); +}; + +export const metricHostsModule: ModuleDescriptor = { + moduleId, + moduleName, + moduleDescription, + jobTypes: metricsK8SJobTypes, + bucketSpan, + getJobIds, + getJobSummary, + getModuleDefinition, + setUpModule, + cleanUpModule, + validateSetupDatasets, + validateSetupIndices, +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/index.tsx b/x-pack/plugins/infra/public/pages/metrics/index.tsx index 3b3ed80f9e7311..ac2c87248ae779 100644 --- a/x-pack/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/index.tsx @@ -38,6 +38,8 @@ import { MetricsAlertDropdown } from '../../alerting/metric_threshold/components import { SavedView } from '../../containers/saved_view/saved_view'; import { SourceConfigurationFields } from '../../graphql/types'; import { AlertPrefillProvider } from '../../alerting/use_alert_prefill'; +import { InfraMLCapabilitiesProvider } from '../../containers/ml/infra_ml_capabilities'; +import { AnomalyDetectionFlyout } from './inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout'; const ADD_DATA_LABEL = i18n.translate('xpack.infra.metricsHeaderAddDataButtonLabel', { defaultMessage: 'Add data', @@ -55,110 +57,118 @@ export const InfrastructurePage = ({ match }: RouteComponentProps) => { - - + + + - + -
+ - - - - - - - - - - - - {ADD_DATA_LABEL} - - - - - - - - ( - - {({ configuration, createDerivedIndexPattern }) => ( - - - {configuration ? ( - - ) : ( - - )} - - )} - + } )} - /> - - - + > + + + + + + + + + + + + + + {ADD_DATA_LABEL} + + + + + + + + ( + + {({ configuration, createDerivedIndexPattern }) => ( + + + {configuration ? ( + + ) : ( + + )} + + )} + + )} + /> + + + + diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx new file mode 100644 index 00000000000000..b063713fa2c971 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useCallback } from 'react'; +import { EuiButtonEmpty, EuiFlyout } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { FlyoutHome } from './flyout_home'; +import { JobSetupScreen } from './job_setup_screen'; +import { useInfraMLCapabilities } from '../../../../../../containers/ml/infra_ml_capabilities'; +import { MetricHostsModuleProvider } from '../../../../../../containers/ml/modules/metrics_hosts/module'; +import { MetricK8sModuleProvider } from '../../../../../../containers/ml/modules/metrics_k8s/module'; +import { useSourceViaHttp } from '../../../../../../containers/source/use_source_via_http'; +import { useActiveKibanaSpace } from '../../../../../../hooks/use_kibana_space'; + +export const AnomalyDetectionFlyout = () => { + const { hasInfraMLSetupCapabilities } = useInfraMLCapabilities(); + const [showFlyout, setShowFlyout] = useState(false); + const [screenName, setScreenName] = useState<'home' | 'setup'>('home'); + const [screenParams, setScreenParams] = useState(null); + const { source } = useSourceViaHttp({ + sourceId: 'default', + type: 'metrics', + }); + + const { space } = useActiveKibanaSpace(); + + const openFlyout = useCallback(() => { + setScreenName('home'); + setShowFlyout(true); + }, []); + + const openJobSetup = useCallback( + (jobType: 'hosts' | 'kubernetes') => { + setScreenName('setup'); + setScreenParams({ jobType }); + }, + [setScreenName] + ); + + const closeFlyout = useCallback(() => { + setShowFlyout(false); + }, []); + + if (source?.configuration.metricAlias == null || space == null) { + return null; + } + + return ( + <> + + + + {showFlyout && ( + + + + {screenName === 'home' && ( + + )} + {screenName === 'setup' && ( + + )} + + + + )} + + ); +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx new file mode 100644 index 00000000000000..9cf898b6843363 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx @@ -0,0 +1,333 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useCallback, useEffect } from 'react'; +import { EuiFlyoutHeader, EuiTitle, EuiFlyoutBody, EuiTabs, EuiTab, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiText, EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { EuiCallOut } from '@elastic/eui'; +import { EuiButton } from '@elastic/eui'; +import { EuiButtonEmpty } from '@elastic/eui'; +import moment from 'moment'; +import { useInfraMLCapabilitiesContext } from '../../../../../../containers/ml/infra_ml_capabilities'; +import { SubscriptionSplashContent } from './subscription_splash_content'; +import { + MissingResultsPrivilegesPrompt, + MissingSetupPrivilegesPrompt, +} from '../../../../../../components/logging/log_analysis_setup'; +import { useMetricHostsModuleContext } from '../../../../../../containers/ml/modules/metrics_hosts/module'; +import { useMetricK8sModuleContext } from '../../../../../../containers/ml/modules/metrics_k8s/module'; +import { LoadingPage } from '../../../../../../components/loading_page'; +import { useLinkProps } from '../../../../../../hooks/use_link_props'; + +interface Props { + hasSetupCapabilities: boolean; + goToSetup(type: 'hosts' | 'kubernetes'): void; +} + +export const FlyoutHome = (props: Props) => { + const [tab, setTab] = useState<'jobs' | 'anomalies'>('jobs'); + const { goToSetup } = props; + const { + fetchJobStatus: fetchHostJobStatus, + setupStatus: hostSetupStatus, + jobSummaries: hostJobSummaries, + } = useMetricHostsModuleContext(); + const { + fetchJobStatus: fetchK8sJobStatus, + setupStatus: k8sSetupStatus, + jobSummaries: k8sJobSummaries, + } = useMetricK8sModuleContext(); + const { + hasInfraMLCapabilites, + hasInfraMLReadCapabilities, + hasInfraMLSetupCapabilities, + } = useInfraMLCapabilitiesContext(); + + const createHosts = useCallback(() => { + goToSetup('hosts'); + }, [goToSetup]); + + const createK8s = useCallback(() => { + goToSetup('kubernetes'); + }, [goToSetup]); + + const goToJobs = useCallback(() => { + setTab('jobs'); + }, []); + + const jobIds = [ + ...(k8sJobSummaries || []).map((k) => k.id), + ...(hostJobSummaries || []).map((h) => h.id), + ]; + const anomaliesUrl = useLinkProps({ + app: 'ml', + pathname: `/explorer?_g=${createResultsUrl(jobIds)}`, + }); + + useEffect(() => { + if (hasInfraMLReadCapabilities) { + fetchHostJobStatus(); + fetchK8sJobStatus(); + } + }, [fetchK8sJobStatus, fetchHostJobStatus, hasInfraMLReadCapabilities]); + + if (!hasInfraMLCapabilites) { + return ; + } else if (!hasInfraMLReadCapabilities) { + return ; + } else if (hostSetupStatus.type === 'initializing' || k8sSetupStatus.type === 'initializing') { + return ( + + ); + } else if (!hasInfraMLSetupCapabilities) { + return ; + } else { + return ( + <> + + +

+ +

+
+
+ + + + + + + + + + + + {hostJobSummaries.length > 0 && ( + <> + 0} + hasK8sJobs={k8sJobSummaries.length > 0} + /> + + + )} + {tab === 'jobs' && ( + 0} + hasK8sJobs={k8sJobSummaries.length > 0} + hasSetupCapabilities={props.hasSetupCapabilities} + createHosts={createHosts} + createK8s={createK8s} + /> + )} + + + ); + } +}; + +interface CalloutProps { + hasHostJobs: boolean; + hasK8sJobs: boolean; +} +const JobsEnabledCallout = (props: CalloutProps) => { + let target = ''; + if (props.hasHostJobs && props.hasK8sJobs) { + target = `${i18n.translate('xpack.infra.ml.anomalyFlyout.create.hostTitle', { + defaultMessage: 'Hosts', + })} and ${i18n.translate('xpack.infra.ml.anomalyFlyout.create.k8sSuccessTitle', { + defaultMessage: 'Kubernetes', + })}`; + } else if (props.hasHostJobs) { + target = i18n.translate('xpack.infra.ml.anomalyFlyout.create.hostSuccessTitle', { + defaultMessage: 'Hosts', + }); + } else if (props.hasK8sJobs) { + target = i18n.translate('xpack.infra.ml.anomalyFlyout.create.k8sSuccessTitle', { + defaultMessage: 'Kubernetes', + }); + } + + const manageJobsLinkProps = useLinkProps({ + app: 'ml', + pathname: '/jobs', + }); + + return ( + <> + + } + iconType="check" + /> + + + + + + ); +}; + +interface CreateJobTab { + hasSetupCapabilities: boolean; + hasHostJobs: boolean; + hasK8sJobs: boolean; + createHosts(): void; + createK8s(): void; +} + +const CreateJobTab = (props: CreateJobTab) => { + return ( + <> +
+ +

+ +

+
+ +

+ +

+
+
+ + + + + } + // title="Hosts" + title={ + + } + description={ + + } + footer={ + <> + {props.hasHostJobs && ( + + + + )} + {!props.hasHostJobs && ( + + + + )} + + } + /> + + + } + title={ + + } + description={ + + } + footer={ + <> + {props.hasK8sJobs && ( + + + + )} + {!props.hasK8sJobs && ( + + + + )} + + } + /> + + + + ); +}; + +function createResultsUrl(jobIds: string[], mode = 'absolute') { + const idString = jobIds.map((j) => `'${j}'`).join(','); + let path = ''; + + const from = moment().subtract(4, 'weeks').toISOString(); + const to = moment().toISOString(); + + path += `(ml:(jobIds:!(${idString}))`; + path += `,refreshInterval:(display:Off,pause:!f,value:0),time:(from:'${from}'`; + path += `,to:'${to}'`; + if (mode === 'invalid') { + path += `,mode:invalid`; + } + path += "))&_a=(query:(query_string:(analyze_wildcard:!t,query:'*')))"; + + return path; +} diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx new file mode 100644 index 00000000000000..730cd7b6e9ef5b --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx @@ -0,0 +1,277 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useCallback, useMemo, useEffect } from 'react'; +import { EuiForm, EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; +import { EuiText, EuiSpacer } from '@elastic/eui'; +import { EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFlyoutFooter } from '@elastic/eui'; +import { EuiButton } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; +import moment, { Moment } from 'moment'; +import { EuiComboBox } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { EuiLoadingSpinner } from '@elastic/eui'; +import { useSourceViaHttp } from '../../../../../../containers/source/use_source_via_http'; +import { useMetricK8sModuleContext } from '../../../../../../containers/ml/modules/metrics_k8s/module'; +import { useMetricHostsModuleContext } from '../../../../../../containers/ml/modules/metrics_hosts/module'; +import { FixedDatePicker } from '../../../../../../components/fixed_datepicker'; + +interface Props { + jobType: 'hosts' | 'kubernetes'; + closeFlyout(): void; + goHome(): void; +} + +export const JobSetupScreen = (props: Props) => { + const [now] = useState(() => moment()); + const { goHome } = props; + const [startDate, setStartDate] = useState(now.clone().subtract(4, 'weeks')); + const [partitionField, setPartitionField] = useState(null); + const h = useMetricHostsModuleContext(); + const k = useMetricK8sModuleContext(); + const { createDerivedIndexPattern } = useSourceViaHttp({ + sourceId: 'default', + type: 'metrics', + }); + + const indicies = h.sourceConfiguration.indices; + + const setupStatus = useMemo(() => { + if (props.jobType === 'kubernetes') { + return k.setupStatus; + } else { + return h.setupStatus; + } + }, [props.jobType, k.setupStatus, h.setupStatus]); + + const cleanUpAndSetUpModule = useMemo(() => { + if (props.jobType === 'kubernetes') { + return k.cleanUpAndSetUpModule; + } else { + return h.cleanUpAndSetUpModule; + } + }, [props.jobType, k.cleanUpAndSetUpModule, h.cleanUpAndSetUpModule]); + + const setUpModule = useMemo(() => { + if (props.jobType === 'kubernetes') { + return k.setUpModule; + } else { + return h.setUpModule; + } + }, [props.jobType, k.setUpModule, h.setUpModule]); + + const hasSummaries = useMemo(() => { + if (props.jobType === 'kubernetes') { + return k.jobSummaries.length > 0; + } else { + return h.jobSummaries.length > 0; + } + }, [props.jobType, k.jobSummaries, h.jobSummaries]); + + const derivedIndexPattern = useMemo(() => createDerivedIndexPattern('metrics'), [ + createDerivedIndexPattern, + ]); + + const updateStart = useCallback((date: Moment) => { + setStartDate(date); + }, []); + + const createJobs = useCallback(() => { + if (hasSummaries) { + cleanUpAndSetUpModule( + indicies, + moment(startDate).toDate().getTime(), + undefined, + { type: 'includeAll' }, + partitionField ? partitionField[0] : undefined + ); + } else { + setUpModule( + indicies, + moment(startDate).toDate().getTime(), + undefined, + { type: 'includeAll' }, + partitionField ? partitionField[0] : undefined + ); + } + }, [cleanUpAndSetUpModule, setUpModule, hasSummaries, indicies, partitionField, startDate]); + + const onPartitionFieldChange = useCallback((value: Array<{ label: string }>) => { + setPartitionField(value.map((v) => v.label)); + }, []); + + useEffect(() => { + if (props.jobType === 'kubernetes') { + setPartitionField(['kubernetes.namespace']); + } + }, [props.jobType]); + + useEffect(() => { + if (setupStatus.type === 'succeeded') { + goHome(); + } + }, [setupStatus, goHome]); + + return ( + <> + + +

+ +

+
+
+ + {setupStatus.type === 'pending' ? ( + + + + + + + + + ) : setupStatus.type === 'failed' ? ( + <> + + + + + + + ) : ( + <> + +

+ +

+
+ + + + + + + } + description={ + + } + > + + } + > + + + + + + + + } + description={ + + } + > + + } + compressed + > + ({ label: p })) : undefined + } + options={derivedIndexPattern.fields + .filter((f) => f.aggregatable && f.type === 'string') + .map((f) => ({ label: f.name }))} + onChange={onPartitionFieldChange} + isClearable={true} + /> + + + + + )} +
+ + + + + + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/subscription_splash_content.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/subscription_splash_content.tsx new file mode 100644 index 00000000000000..f07c37f5e7ea2a --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/subscription_splash_content.tsx @@ -0,0 +1,172 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiPage, + EuiPageBody, + EuiPageContent, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiTitle, + EuiText, + EuiButton, + EuiButtonEmpty, + EuiImage, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { LoadingPage } from '../../../../../../components/loading_page'; +import { useTrialStatus } from '../../../../../../hooks/use_trial_status'; +import { useKibana } from '../../../../../../../../../../src/plugins/kibana_react/public'; +import { euiStyled } from '../../../../../../../../observability/public'; +import { HttpStart } from '../../../../../../../../../../src/core/public'; + +export const SubscriptionSplashContent: React.FC = () => { + const { services } = useKibana<{ http: HttpStart }>(); + const { loadState, isTrialAvailable, checkTrialAvailability } = useTrialStatus(); + + useEffect(() => { + checkTrialAvailability(); + }, [checkTrialAvailability]); + + if (loadState === 'pending') { + return ( + + ); + } + + const canStartTrial = isTrialAvailable && loadState === 'resolved'; + + let title; + let description; + let cta; + + if (canStartTrial) { + title = ( + + ); + + description = ( + + ); + + cta = ( + + + + ); + } else { + title = ( + + ); + + description = ( + + ); + + cta = ( + + + + ); + } + + return ( + + + + + + +

{title}

+
+ + +

{description}

+
+ +
{cta}
+
+ + + +
+ + +

+ +

+
+ + + +
+
+
+
+ ); +}; + +const SubscriptionPage = euiStyled(EuiPage)` + height: 100% +`; + +const SubscriptionPageContent = euiStyled(EuiPageContent)` + max-width: 768px !important; +`; + +const SubscriptionPageFooter = euiStyled.div` + background: ${(props) => props.theme.eui.euiColorLightestShade}; + margin: 0 -${(props) => props.theme.eui.paddingSizes.l} -${(props) => + props.theme.eui.paddingSizes.l}; + padding: ${(props) => props.theme.eui.paddingSizes.l}; +`; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx index 6e031c8396f076..dbbfb0f49c0e9c 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx @@ -22,7 +22,7 @@ export const IntervalLabel = ({ intervalAsString }: Props) => {

diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts new file mode 100644 index 00000000000000..f755057d0b76d5 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_hosts_anomalies.ts @@ -0,0 +1,318 @@ +/* + * 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 { useMemo, useState, useCallback, useEffect, useReducer } from 'react'; +import { + INFA_ML_GET_METRICS_HOSTS_ANOMALIES_PATH, + Sort, + Pagination, + PaginationCursor, + getMetricsHostsAnomaliesRequestPayloadRT, + MetricsHostsAnomaly, + getMetricsHostsAnomaliesSuccessReponsePayloadRT, +} from '../../../../../common/http_api/infra_ml'; +import { useTrackedPromise } from '../../../../utils/use_tracked_promise'; +import { npStart } from '../../../../legacy_singletons'; +import { decodeOrThrow } from '../../../../../common/runtime_types'; + +export type SortOptions = Sort; +export type PaginationOptions = Pick; +export type Page = number; +export type FetchNextPage = () => void; +export type FetchPreviousPage = () => void; +export type ChangeSortOptions = (sortOptions: Sort) => void; +export type ChangePaginationOptions = (paginationOptions: PaginationOptions) => void; +export type MetricsHostsAnomalies = MetricsHostsAnomaly[]; +interface PaginationCursors { + previousPageCursor: PaginationCursor; + nextPageCursor: PaginationCursor; +} + +interface ReducerState { + page: number; + lastReceivedCursors: PaginationCursors | undefined; + paginationCursor: Pagination['cursor'] | undefined; + hasNextPage: boolean; + paginationOptions: PaginationOptions; + sortOptions: Sort; + timeRange: { + start: number; + end: number; + }; + filteredDatasets?: string[]; +} + +type ReducerStateDefaults = Pick< + ReducerState, + 'page' | 'lastReceivedCursors' | 'paginationCursor' | 'hasNextPage' +>; + +type ReducerAction = + | { type: 'changePaginationOptions'; payload: { paginationOptions: PaginationOptions } } + | { type: 'changeSortOptions'; payload: { sortOptions: Sort } } + | { type: 'fetchNextPage' } + | { type: 'fetchPreviousPage' } + | { type: 'changeHasNextPage'; payload: { hasNextPage: boolean } } + | { type: 'changeLastReceivedCursors'; payload: { lastReceivedCursors: PaginationCursors } } + | { type: 'changeTimeRange'; payload: { timeRange: { start: number; end: number } } } + | { type: 'changeFilteredDatasets'; payload: { filteredDatasets?: string[] } }; + +const stateReducer = (state: ReducerState, action: ReducerAction): ReducerState => { + const resetPagination = { + page: 1, + paginationCursor: undefined, + }; + switch (action.type) { + case 'changePaginationOptions': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + case 'changeSortOptions': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + case 'changeHasNextPage': + return { + ...state, + ...action.payload, + }; + case 'changeLastReceivedCursors': + return { + ...state, + ...action.payload, + }; + case 'fetchNextPage': + return state.lastReceivedCursors + ? { + ...state, + page: state.page + 1, + paginationCursor: { searchAfter: state.lastReceivedCursors.nextPageCursor }, + } + : state; + case 'fetchPreviousPage': + return state.lastReceivedCursors + ? { + ...state, + page: state.page - 1, + paginationCursor: { searchBefore: state.lastReceivedCursors.previousPageCursor }, + } + : state; + case 'changeTimeRange': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + case 'changeFilteredDatasets': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + default: + return state; + } +}; + +const STATE_DEFAULTS: ReducerStateDefaults = { + // NOTE: This piece of state is purely for the client side, it could be extracted out of the hook. + page: 1, + // Cursor from the last request + lastReceivedCursors: undefined, + // Cursor to use for the next request. For the first request, and therefore not paging, this will be undefined. + paginationCursor: undefined, + hasNextPage: false, +}; + +export const useMetricsHostsAnomaliesResults = ({ + endTime, + startTime, + sourceId, + defaultSortOptions, + defaultPaginationOptions, + onGetMetricsHostsAnomaliesDatasetsError, + filteredDatasets, +}: { + endTime: number; + startTime: number; + sourceId: string; + defaultSortOptions: Sort; + defaultPaginationOptions: Pick; + onGetMetricsHostsAnomaliesDatasetsError?: (error: Error) => void; + filteredDatasets?: string[]; +}) => { + const initStateReducer = (stateDefaults: ReducerStateDefaults): ReducerState => { + return { + ...stateDefaults, + paginationOptions: defaultPaginationOptions, + sortOptions: defaultSortOptions, + filteredDatasets, + timeRange: { + start: startTime, + end: endTime, + }, + }; + }; + + const [reducerState, dispatch] = useReducer(stateReducer, STATE_DEFAULTS, initStateReducer); + + const [metricsHostsAnomalies, setMetricsHostsAnomalies] = useState([]); + + const [getMetricsHostsAnomaliesRequest, getMetricsHostsAnomalies] = useTrackedPromise( + { + cancelPreviousOn: 'creation', + createPromise: async () => { + const { + timeRange: { start: queryStartTime, end: queryEndTime }, + sortOptions, + paginationOptions, + paginationCursor, + } = reducerState; + return await callGetMetricHostsAnomaliesAPI( + sourceId, + queryStartTime, + queryEndTime, + sortOptions, + { + ...paginationOptions, + cursor: paginationCursor, + } + ); + }, + onResolve: ({ data: { anomalies, paginationCursors: requestCursors, hasMoreEntries } }) => { + const { paginationCursor } = reducerState; + if (requestCursors) { + dispatch({ + type: 'changeLastReceivedCursors', + payload: { lastReceivedCursors: requestCursors }, + }); + } + // Check if we have more "next" entries. "Page" covers the "previous" scenario, + // since we need to know the page we're on anyway. + if (!paginationCursor || (paginationCursor && 'searchAfter' in paginationCursor)) { + dispatch({ type: 'changeHasNextPage', payload: { hasNextPage: hasMoreEntries } }); + } else if (paginationCursor && 'searchBefore' in paginationCursor) { + // We've requested a previous page, therefore there is a next page. + dispatch({ type: 'changeHasNextPage', payload: { hasNextPage: true } }); + } + setMetricsHostsAnomalies(anomalies); + }, + }, + [ + sourceId, + dispatch, + reducerState.timeRange, + reducerState.sortOptions, + reducerState.paginationOptions, + reducerState.paginationCursor, + reducerState.filteredDatasets, + ] + ); + + const changeSortOptions = useCallback( + (nextSortOptions: Sort) => { + dispatch({ type: 'changeSortOptions', payload: { sortOptions: nextSortOptions } }); + }, + [dispatch] + ); + + const changePaginationOptions = useCallback( + (nextPaginationOptions: PaginationOptions) => { + dispatch({ + type: 'changePaginationOptions', + payload: { paginationOptions: nextPaginationOptions }, + }); + }, + [dispatch] + ); + + // Time range has changed + useEffect(() => { + dispatch({ + type: 'changeTimeRange', + payload: { timeRange: { start: startTime, end: endTime } }, + }); + }, [startTime, endTime]); + + // Selected datasets have changed + useEffect(() => { + dispatch({ + type: 'changeFilteredDatasets', + payload: { filteredDatasets }, + }); + }, [filteredDatasets]); + + useEffect(() => { + getMetricsHostsAnomalies(); + }, [getMetricsHostsAnomalies]); // TODO: FIgure out the deps here. + + const handleFetchNextPage = useCallback(() => { + if (reducerState.lastReceivedCursors) { + dispatch({ type: 'fetchNextPage' }); + } + }, [dispatch, reducerState]); + + const handleFetchPreviousPage = useCallback(() => { + if (reducerState.lastReceivedCursors) { + dispatch({ type: 'fetchPreviousPage' }); + } + }, [dispatch, reducerState]); + + const isLoadingMetricsHostsAnomalies = useMemo( + () => getMetricsHostsAnomaliesRequest.state === 'pending', + [getMetricsHostsAnomaliesRequest.state] + ); + + const hasFailedLoadingMetricsHostsAnomalies = useMemo( + () => getMetricsHostsAnomaliesRequest.state === 'rejected', + [getMetricsHostsAnomaliesRequest.state] + ); + + return { + metricsHostsAnomalies, + getMetricsHostsAnomalies, + isLoadingMetricsHostsAnomalies, + hasFailedLoadingMetricsHostsAnomalies, + changeSortOptions, + sortOptions: reducerState.sortOptions, + changePaginationOptions, + paginationOptions: reducerState.paginationOptions, + fetchPreviousPage: reducerState.page > 1 ? handleFetchPreviousPage : undefined, + fetchNextPage: reducerState.hasNextPage ? handleFetchNextPage : undefined, + page: reducerState.page, + }; +}; + +export const callGetMetricHostsAnomaliesAPI = async ( + sourceId: string, + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) => { + const response = await npStart.http.fetch(INFA_ML_GET_METRICS_HOSTS_ANOMALIES_PATH, { + method: 'POST', + body: JSON.stringify( + getMetricsHostsAnomaliesRequestPayloadRT.encode({ + data: { + sourceId, + timeRange: { + startTime, + endTime, + }, + sort, + pagination, + }, + }) + ), + }); + + return decodeOrThrow(getMetricsHostsAnomaliesSuccessReponsePayloadRT)(response); +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts new file mode 100644 index 00000000000000..4a7b78e1fdf921 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_metrics_k8s_anomalies.ts @@ -0,0 +1,322 @@ +/* + * 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 { useMemo, useState, useCallback, useEffect, useReducer } from 'react'; +import { + Sort, + Pagination, + PaginationCursor, + INFA_ML_GET_METRICS_K8S_ANOMALIES_PATH, + getMetricsK8sAnomaliesSuccessReponsePayloadRT, + getMetricsK8sAnomaliesRequestPayloadRT, + MetricsK8sAnomaly, +} from '../../../../../common/http_api/infra_ml'; +import { useTrackedPromise } from '../../../../utils/use_tracked_promise'; +import { npStart } from '../../../../legacy_singletons'; +import { decodeOrThrow } from '../../../../../common/runtime_types'; + +export type SortOptions = Sort; +export type PaginationOptions = Pick; +export type Page = number; +export type FetchNextPage = () => void; +export type FetchPreviousPage = () => void; +export type ChangeSortOptions = (sortOptions: Sort) => void; +export type ChangePaginationOptions = (paginationOptions: PaginationOptions) => void; +export type MetricsK8sAnomalies = MetricsK8sAnomaly[]; +interface PaginationCursors { + previousPageCursor: PaginationCursor; + nextPageCursor: PaginationCursor; +} + +interface ReducerState { + page: number; + lastReceivedCursors: PaginationCursors | undefined; + paginationCursor: Pagination['cursor'] | undefined; + hasNextPage: boolean; + paginationOptions: PaginationOptions; + sortOptions: Sort; + timeRange: { + start: number; + end: number; + }; + filteredDatasets?: string[]; +} + +type ReducerStateDefaults = Pick< + ReducerState, + 'page' | 'lastReceivedCursors' | 'paginationCursor' | 'hasNextPage' +>; + +type ReducerAction = + | { type: 'changePaginationOptions'; payload: { paginationOptions: PaginationOptions } } + | { type: 'changeSortOptions'; payload: { sortOptions: Sort } } + | { type: 'fetchNextPage' } + | { type: 'fetchPreviousPage' } + | { type: 'changeHasNextPage'; payload: { hasNextPage: boolean } } + | { type: 'changeLastReceivedCursors'; payload: { lastReceivedCursors: PaginationCursors } } + | { type: 'changeTimeRange'; payload: { timeRange: { start: number; end: number } } } + | { type: 'changeFilteredDatasets'; payload: { filteredDatasets?: string[] } }; + +const stateReducer = (state: ReducerState, action: ReducerAction): ReducerState => { + const resetPagination = { + page: 1, + paginationCursor: undefined, + }; + switch (action.type) { + case 'changePaginationOptions': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + case 'changeSortOptions': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + case 'changeHasNextPage': + return { + ...state, + ...action.payload, + }; + case 'changeLastReceivedCursors': + return { + ...state, + ...action.payload, + }; + case 'fetchNextPage': + return state.lastReceivedCursors + ? { + ...state, + page: state.page + 1, + paginationCursor: { searchAfter: state.lastReceivedCursors.nextPageCursor }, + } + : state; + case 'fetchPreviousPage': + return state.lastReceivedCursors + ? { + ...state, + page: state.page - 1, + paginationCursor: { searchBefore: state.lastReceivedCursors.previousPageCursor }, + } + : state; + case 'changeTimeRange': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + case 'changeFilteredDatasets': + return { + ...state, + ...resetPagination, + ...action.payload, + }; + default: + return state; + } +}; + +const STATE_DEFAULTS: ReducerStateDefaults = { + // NOTE: This piece of state is purely for the client side, it could be extracted out of the hook. + page: 1, + // Cursor from the last request + lastReceivedCursors: undefined, + // Cursor to use for the next request. For the first request, and therefore not paging, this will be undefined. + paginationCursor: undefined, + hasNextPage: false, +}; + +export const useMetricsK8sAnomaliesResults = ({ + endTime, + startTime, + sourceId, + defaultSortOptions, + defaultPaginationOptions, + onGetMetricsHostsAnomaliesDatasetsError, + filteredDatasets, +}: { + endTime: number; + startTime: number; + sourceId: string; + defaultSortOptions: Sort; + defaultPaginationOptions: Pick; + onGetMetricsHostsAnomaliesDatasetsError?: (error: Error) => void; + filteredDatasets?: string[]; +}) => { + const initStateReducer = (stateDefaults: ReducerStateDefaults): ReducerState => { + return { + ...stateDefaults, + paginationOptions: defaultPaginationOptions, + sortOptions: defaultSortOptions, + filteredDatasets, + timeRange: { + start: startTime, + end: endTime, + }, + }; + }; + + const [reducerState, dispatch] = useReducer(stateReducer, STATE_DEFAULTS, initStateReducer); + + const [metricsK8sAnomalies, setMetricsK8sAnomalies] = useState([]); + + const [getMetricsK8sAnomaliesRequest, getMetricsK8sAnomalies] = useTrackedPromise( + { + cancelPreviousOn: 'creation', + createPromise: async () => { + const { + timeRange: { start: queryStartTime, end: queryEndTime }, + sortOptions, + paginationOptions, + paginationCursor, + filteredDatasets: queryFilteredDatasets, + } = reducerState; + return await callGetMetricsK8sAnomaliesAPI( + sourceId, + queryStartTime, + queryEndTime, + sortOptions, + { + ...paginationOptions, + cursor: paginationCursor, + }, + queryFilteredDatasets + ); + }, + onResolve: ({ data: { anomalies, paginationCursors: requestCursors, hasMoreEntries } }) => { + const { paginationCursor } = reducerState; + if (requestCursors) { + dispatch({ + type: 'changeLastReceivedCursors', + payload: { lastReceivedCursors: requestCursors }, + }); + } + // Check if we have more "next" entries. "Page" covers the "previous" scenario, + // since we need to know the page we're on anyway. + if (!paginationCursor || (paginationCursor && 'searchAfter' in paginationCursor)) { + dispatch({ type: 'changeHasNextPage', payload: { hasNextPage: hasMoreEntries } }); + } else if (paginationCursor && 'searchBefore' in paginationCursor) { + // We've requested a previous page, therefore there is a next page. + dispatch({ type: 'changeHasNextPage', payload: { hasNextPage: true } }); + } + setMetricsK8sAnomalies(anomalies); + }, + }, + [ + sourceId, + dispatch, + reducerState.timeRange, + reducerState.sortOptions, + reducerState.paginationOptions, + reducerState.paginationCursor, + reducerState.filteredDatasets, + ] + ); + + const changeSortOptions = useCallback( + (nextSortOptions: Sort) => { + dispatch({ type: 'changeSortOptions', payload: { sortOptions: nextSortOptions } }); + }, + [dispatch] + ); + + const changePaginationOptions = useCallback( + (nextPaginationOptions: PaginationOptions) => { + dispatch({ + type: 'changePaginationOptions', + payload: { paginationOptions: nextPaginationOptions }, + }); + }, + [dispatch] + ); + + // Time range has changed + useEffect(() => { + dispatch({ + type: 'changeTimeRange', + payload: { timeRange: { start: startTime, end: endTime } }, + }); + }, [startTime, endTime]); + + // Selected datasets have changed + useEffect(() => { + dispatch({ + type: 'changeFilteredDatasets', + payload: { filteredDatasets }, + }); + }, [filteredDatasets]); + + useEffect(() => { + getMetricsK8sAnomalies(); + }, [getMetricsK8sAnomalies]); + + const handleFetchNextPage = useCallback(() => { + if (reducerState.lastReceivedCursors) { + dispatch({ type: 'fetchNextPage' }); + } + }, [dispatch, reducerState]); + + const handleFetchPreviousPage = useCallback(() => { + if (reducerState.lastReceivedCursors) { + dispatch({ type: 'fetchPreviousPage' }); + } + }, [dispatch, reducerState]); + + const isLoadingMetricsK8sAnomalies = useMemo( + () => getMetricsK8sAnomaliesRequest.state === 'pending', + [getMetricsK8sAnomaliesRequest.state] + ); + + const hasFailedLoadingMetricsK8sAnomalies = useMemo( + () => getMetricsK8sAnomaliesRequest.state === 'rejected', + [getMetricsK8sAnomaliesRequest.state] + ); + + return { + metricsK8sAnomalies, + getMetricsK8sAnomalies, + isLoadingMetricsK8sAnomalies, + hasFailedLoadingMetricsK8sAnomalies, + changeSortOptions, + sortOptions: reducerState.sortOptions, + changePaginationOptions, + paginationOptions: reducerState.paginationOptions, + fetchPreviousPage: reducerState.page > 1 ? handleFetchPreviousPage : undefined, + fetchNextPage: reducerState.hasNextPage ? handleFetchNextPage : undefined, + page: reducerState.page, + }; +}; + +export const callGetMetricsK8sAnomaliesAPI = async ( + sourceId: string, + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination, + datasets?: string[] +) => { + const response = await npStart.http.fetch(INFA_ML_GET_METRICS_K8S_ANOMALIES_PATH, { + method: 'POST', + body: JSON.stringify( + getMetricsK8sAnomaliesRequestPayloadRT.encode({ + data: { + sourceId, + timeRange: { + startTime, + endTime, + }, + sort, + pagination, + datasets, + }, + }) + ), + }); + + return decodeOrThrow(getMetricsK8sAnomaliesSuccessReponsePayloadRT)(response); +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts index 650eda0362d9e2..acf9011ac7ddd4 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts @@ -28,21 +28,28 @@ const ONE_MINUTE = 60; const ONE_HOUR = ONE_MINUTE * 60; const ONE_DAY = ONE_HOUR * 24; const ONE_WEEK = ONE_DAY * 7; +const ONE_MONTH = ONE_DAY * 30; + +const getDisplayInterval = (interval: string | undefined) => { + if (interval) { + const intervalInSeconds = getIntervalInSeconds(interval); + if (intervalInSeconds < 300) return '5m'; + } + return interval; +}; const getTimeLengthFromInterval = (interval: string | undefined) => { if (interval) { const intervalInSeconds = getIntervalInSeconds(interval); - const multiplier = - intervalInSeconds < ONE_MINUTE - ? ONE_HOUR / intervalInSeconds - : intervalInSeconds < ONE_HOUR - ? 60 - : intervalInSeconds < ONE_DAY - ? 7 - : intervalInSeconds < ONE_WEEK - ? 30 - : 1; - const timeLength = intervalInSeconds * multiplier; + // Get up to 288 datapoints based on interval + const timeLength = + intervalInSeconds <= ONE_MINUTE * 15 + ? ONE_DAY + : intervalInSeconds <= ONE_MINUTE * 35 + ? ONE_DAY * 3 + : intervalInSeconds <= ONE_HOUR * 2.5 + ? ONE_WEEK + : ONE_MONTH; return { timeLength, intervalInSeconds }; } else { return { timeLength: 0, intervalInSeconds: 0 }; @@ -67,15 +74,19 @@ export function useTimeline( ); }; - const timeLengthResult = useMemo(() => getTimeLengthFromInterval(interval), [interval]); + const displayInterval = useMemo(() => getDisplayInterval(interval), [interval]); + + const timeLengthResult = useMemo(() => getTimeLengthFromInterval(displayInterval), [ + displayInterval, + ]); const { timeLength, intervalInSeconds } = timeLengthResult; const timerange: InfraTimerangeInput = { - interval: interval ?? '', + interval: displayInterval ?? '', to: currentTime + intervalInSeconds * 1000, from: currentTime - timeLength * 1000, - lookbackSize: 0, ignoreLookback: true, + forceInterval: true, }; const { error, loading, response, makeRequest } = useHTTPRequest( diff --git a/x-pack/plugins/infra/server/infra_server.ts b/x-pack/plugins/infra/server/infra_server.ts index a72e40e25b4794..206fffdd2e1888 100644 --- a/x-pack/plugins/infra/server/infra_server.ts +++ b/x-pack/plugins/infra/server/infra_server.ts @@ -21,6 +21,8 @@ import { initGetLogEntryAnomaliesRoute, initGetLogEntryAnomaliesDatasetsRoute, } from './routes/log_analysis'; +import { initGetK8sAnomaliesRoute } from './routes/infra_ml'; +import { initGetHostsAnomaliesRoute } from './routes/infra_ml'; import { initMetricExplorerRoute } from './routes/metrics_explorer'; import { initMetadataRoute } from './routes/metadata'; import { initSnapshotRoute } from './routes/snapshot'; @@ -56,6 +58,8 @@ export const initInfraServer = (libs: InfraBackendLibs) => { initGetLogEntryRateRoute(libs); initGetLogEntryAnomaliesRoute(libs); initGetLogEntryAnomaliesDatasetsRoute(libs); + initGetK8sAnomaliesRoute(libs); + initGetHostsAnomaliesRoute(libs); initSnapshotRoute(libs); initNodeDetailsRoute(libs); initSourceRoute(libs); diff --git a/x-pack/plugins/infra/server/lib/infra_ml/common.ts b/x-pack/plugins/infra/server/lib/infra_ml/common.ts new file mode 100644 index 00000000000000..4d2be94c7cd628 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/common.ts @@ -0,0 +1,89 @@ +/* + * 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 type { MlAnomalyDetectors, MlSystem } from '../../types'; +import { NoLogAnalysisMlJobError } from './errors'; + +import { + CompositeDatasetKey, + createLogEntryDatasetsQuery, + LogEntryDatasetBucket, + logEntryDatasetsResponseRT, +} from './queries/log_entry_data_sets'; +import { decodeOrThrow } from '../../../common/runtime_types'; +import { startTracingSpan, TracingSpan } from '../../../common/performance_tracing'; + +export async function fetchMlJob(mlAnomalyDetectors: MlAnomalyDetectors, jobId: string) { + const finalizeMlGetJobSpan = startTracingSpan('Fetch ml job from ES'); + const { + jobs: [mlJob], + } = await mlAnomalyDetectors.jobs(jobId); + + const mlGetJobSpan = finalizeMlGetJobSpan(); + + if (mlJob == null) { + throw new NoLogAnalysisMlJobError(`Failed to find ml job ${jobId}.`); + } + + return { + mlJob, + timing: { + spans: [mlGetJobSpan], + }, + }; +} + +const COMPOSITE_AGGREGATION_BATCH_SIZE = 1000; + +// Finds datasets related to ML job ids +export async function getLogEntryDatasets( + mlSystem: MlSystem, + startTime: number, + endTime: number, + jobIds: string[] +) { + const finalizeLogEntryDatasetsSpan = startTracingSpan('get data sets'); + + let logEntryDatasetBuckets: LogEntryDatasetBucket[] = []; + let afterLatestBatchKey: CompositeDatasetKey | undefined; + let esSearchSpans: TracingSpan[] = []; + + while (true) { + const finalizeEsSearchSpan = startTracingSpan('fetch log entry dataset batch from ES'); + + const logEntryDatasetsResponse = decodeOrThrow(logEntryDatasetsResponseRT)( + await mlSystem.mlAnomalySearch( + createLogEntryDatasetsQuery( + jobIds, + startTime, + endTime, + COMPOSITE_AGGREGATION_BATCH_SIZE, + afterLatestBatchKey + ) + ) + ); + + const { after_key: afterKey, buckets: latestBatchBuckets = [] } = + logEntryDatasetsResponse.aggregations?.dataset_buckets ?? {}; + + logEntryDatasetBuckets = [...logEntryDatasetBuckets, ...latestBatchBuckets]; + afterLatestBatchKey = afterKey; + esSearchSpans = [...esSearchSpans, finalizeEsSearchSpan()]; + + if (latestBatchBuckets.length < COMPOSITE_AGGREGATION_BATCH_SIZE) { + break; + } + } + + const logEntryDatasetsSpan = finalizeLogEntryDatasetsSpan(); + + return { + data: logEntryDatasetBuckets.map((logEntryDatasetBucket) => logEntryDatasetBucket.key.dataset), + timing: { + spans: [logEntryDatasetsSpan, ...esSearchSpans], + }, + }; +} diff --git a/x-pack/plugins/infra/server/lib/infra_ml/errors.ts b/x-pack/plugins/infra/server/lib/infra_ml/errors.ts new file mode 100644 index 00000000000000..ad46ebf7102663 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/errors.ts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +/* eslint-disable max-classes-per-file */ + +import { + UnknownMLCapabilitiesError, + InsufficientMLCapabilities, + MLPrivilegesUninitialized, +} from '../../../../ml/server'; + +export class NoLogAnalysisMlJobError extends Error { + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export class InsufficientLogAnalysisMlJobConfigurationError extends Error { + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export class UnknownCategoryError extends Error { + constructor(categoryId: number) { + super(`Unknown ml category ${categoryId}`); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export class InsufficientAnomalyMlJobsConfigured extends Error { + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export const isMlPrivilegesError = (error: any) => { + return ( + error instanceof UnknownMLCapabilitiesError || + error instanceof InsufficientMLCapabilities || + error instanceof MLPrivilegesUninitialized + ); +}; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/index.ts b/x-pack/plugins/infra/server/lib/infra_ml/index.ts new file mode 100644 index 00000000000000..536f0a44d58906 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './errors'; +export * from './metrics_hosts_anomalies'; +export * from './metrics_k8s_anomalies'; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts new file mode 100644 index 00000000000000..e0afa458aac88f --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/metrics_hosts_anomalies.ts @@ -0,0 +1,289 @@ +/* + * 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 { RequestHandlerContext } from 'src/core/server'; +import { InfraRequestHandlerContext } from '../../types'; +import { TracingSpan, startTracingSpan } from '../../../common/performance_tracing'; +import { fetchMlJob, getLogEntryDatasets } from './common'; +import { getJobId, metricsHostsJobTypes } from '../../../common/infra_ml'; +import { Sort, Pagination } from '../../../common/http_api/infra_ml'; +import type { MlSystem, MlAnomalyDetectors } from '../../types'; +import { InsufficientAnomalyMlJobsConfigured, isMlPrivilegesError } from './errors'; +import { decodeOrThrow } from '../../../common/runtime_types'; +import { + metricsHostsAnomaliesResponseRT, + createMetricsHostsAnomaliesQuery, +} from './queries/metrics_hosts_anomalies'; + +interface MappedAnomalyHit { + id: string; + anomalyScore: number; + dataset: string; + typical: number; + actual: number; + jobId: string; + startTime: number; + duration: number; + hostName: string[]; + categoryId?: string; +} + +async function getCompatibleAnomaliesJobIds( + spaceId: string, + sourceId: string, + mlAnomalyDetectors: MlAnomalyDetectors +) { + const metricsHostsJobIds = metricsHostsJobTypes.map((jt) => getJobId(spaceId, sourceId, jt)); + + const jobIds: string[] = []; + let jobSpans: TracingSpan[] = []; + + try { + await Promise.all( + metricsHostsJobIds.map((id) => { + return (async () => { + const { + timing: { spans }, + } = await fetchMlJob(mlAnomalyDetectors, id); + jobIds.push(id); + jobSpans = [...jobSpans, ...spans]; + })(); + }) + ); + } catch (e) { + if (isMlPrivilegesError(e)) { + throw e; + } + // An error is also thrown when no jobs are found + } + + return { + jobIds, + timing: { spans: jobSpans }, + }; +} + +export async function getMetricsHostsAnomalies( + context: RequestHandlerContext & { infra: Required }, + sourceId: string, + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) { + const finalizeMetricsHostsAnomaliesSpan = startTracingSpan('get metrics hosts entry anomalies'); + + const { + jobIds, + timing: { spans: jobSpans }, + } = await getCompatibleAnomaliesJobIds( + context.infra.spaceId, + sourceId, + context.infra.mlAnomalyDetectors + ); + + if (jobIds.length === 0) { + throw new InsufficientAnomalyMlJobsConfigured( + 'Metrics Hosts ML jobs need to be configured to search anomalies' + ); + } + + try { + const { + anomalies, + paginationCursors, + hasMoreEntries, + timing: { spans: fetchLogEntryAnomaliesSpans }, + } = await fetchMetricsHostsAnomalies( + context.infra.mlSystem, + jobIds, + startTime, + endTime, + sort, + pagination + ); + + const data = anomalies.map((anomaly) => { + const { jobId } = anomaly; + + return parseAnomalyResult(anomaly, jobId); + }); + + const metricsHostsAnomaliesSpan = finalizeMetricsHostsAnomaliesSpan(); + + return { + data, + paginationCursors, + hasMoreEntries, + timing: { + spans: [metricsHostsAnomaliesSpan, ...jobSpans, ...fetchLogEntryAnomaliesSpans], + }, + }; + } catch (e) { + throw new Error(e); + } +} + +const parseAnomalyResult = (anomaly: MappedAnomalyHit, jobId: string) => { + const { + id, + anomalyScore, + dataset, + typical, + actual, + duration, + hostName, + startTime: anomalyStartTime, + } = anomaly; + + return { + id, + anomalyScore, + dataset, + typical, + actual, + duration, + hostName, + startTime: anomalyStartTime, + type: 'metrics_hosts' as const, + jobId, + }; +}; + +async function fetchMetricsHostsAnomalies( + mlSystem: MlSystem, + jobIds: string[], + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) { + // We'll request 1 extra entry on top of our pageSize to determine if there are + // more entries to be fetched. This avoids scenarios where the client side can't + // determine if entries.length === pageSize actually means there are more entries / next page + // or not. + const expandedPagination = { ...pagination, pageSize: pagination.pageSize + 1 }; + + const finalizeFetchLogEntryAnomaliesSpan = startTracingSpan('fetch metrics hosts anomalies'); + + // console.log( + // 'data', + // JSON.stringify( + // await mlSystem.mlAnomalySearch( + // createMetricsHostsAnomaliesQuery(jobIds, startTime, endTime, sort, expandedPagination) + // ), + // null, + // 2 + // ) + // ); + const results = decodeOrThrow(metricsHostsAnomaliesResponseRT)( + await mlSystem.mlAnomalySearch( + createMetricsHostsAnomaliesQuery(jobIds, startTime, endTime, sort, expandedPagination) + ) + ); + + const { + hits: { hits }, + } = results; + const hasMoreEntries = hits.length > pagination.pageSize; + + // An extra entry was found and hasMoreEntries has been determined, the extra entry can be removed. + if (hasMoreEntries) { + hits.pop(); + } + + // To "search_before" the sort order will have been reversed for ES. + // The results are now reversed back, to match the requested sort. + if (pagination.cursor && 'searchBefore' in pagination.cursor) { + hits.reverse(); + } + + const paginationCursors = + hits.length > 0 + ? { + previousPageCursor: hits[0].sort, + nextPageCursor: hits[hits.length - 1].sort, + } + : undefined; + + const anomalies = hits.map((result) => { + const { + // eslint-disable-next-line @typescript-eslint/naming-convention + job_id, + record_score: anomalyScore, + typical, + actual, + bucket_span: duration, + timestamp: anomalyStartTime, + by_field_value: categoryId, + } = result._source; + + return { + id: result._id, + anomalyScore, + dataset: '', + typical: typical[0], + actual: actual[0], + jobId: job_id, + hostName: result._source['host.name'], + startTime: anomalyStartTime, + duration: duration * 1000, + categoryId, + }; + }); + + const fetchLogEntryAnomaliesSpan = finalizeFetchLogEntryAnomaliesSpan(); + + return { + anomalies, + paginationCursors, + hasMoreEntries, + timing: { + spans: [fetchLogEntryAnomaliesSpan], + }, + }; +} + +// TODO: FIgure out why we need datasets +export async function getMetricsHostsAnomaliesDatasets( + context: { + infra: { + mlSystem: MlSystem; + mlAnomalyDetectors: MlAnomalyDetectors; + spaceId: string; + }; + }, + sourceId: string, + startTime: number, + endTime: number +) { + const { + jobIds, + timing: { spans: jobSpans }, + } = await getCompatibleAnomaliesJobIds( + context.infra.spaceId, + sourceId, + context.infra.mlAnomalyDetectors + ); + + if (jobIds.length === 0) { + throw new InsufficientAnomalyMlJobsConfigured( + 'Log rate or categorisation ML jobs need to be configured to search for anomaly datasets' + ); + } + + const { + data: datasets, + timing: { spans: datasetsSpans }, + } = await getLogEntryDatasets(context.infra.mlSystem, startTime, endTime, jobIds); + + return { + datasets, + timing: { + spans: [...jobSpans, ...datasetsSpans], + }, + }; +} diff --git a/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts new file mode 100644 index 00000000000000..29507900e1847f --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/metrics_k8s_anomalies.ts @@ -0,0 +1,272 @@ +/* + * 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 { RequestHandlerContext } from 'src/core/server'; +import { InfraRequestHandlerContext } from '../../types'; +import { TracingSpan, startTracingSpan } from '../../../common/performance_tracing'; +import { fetchMlJob, getLogEntryDatasets } from './common'; +import { getJobId, metricsK8SJobTypes } from '../../../common/infra_ml'; +import { Sort, Pagination } from '../../../common/http_api/infra_ml'; +import type { MlSystem, MlAnomalyDetectors } from '../../types'; +import { InsufficientAnomalyMlJobsConfigured, isMlPrivilegesError } from './errors'; +import { decodeOrThrow } from '../../../common/runtime_types'; +import { + metricsK8sAnomaliesResponseRT, + createMetricsK8sAnomaliesQuery, +} from './queries/metrics_k8s_anomalies'; + +interface MappedAnomalyHit { + id: string; + anomalyScore: number; + // dataset: string; + typical: number; + actual: number; + jobId: string; + startTime: number; + duration: number; + categoryId?: string; +} + +async function getCompatibleAnomaliesJobIds( + spaceId: string, + sourceId: string, + mlAnomalyDetectors: MlAnomalyDetectors +) { + const metricsK8sJobIds = metricsK8SJobTypes.map((jt) => getJobId(spaceId, sourceId, jt)); + + const jobIds: string[] = []; + let jobSpans: TracingSpan[] = []; + + try { + await Promise.all( + metricsK8sJobIds.map((id) => { + return (async () => { + const { + timing: { spans }, + } = await fetchMlJob(mlAnomalyDetectors, id); + jobIds.push(id); + jobSpans = [...jobSpans, ...spans]; + })(); + }) + ); + } catch (e) { + if (isMlPrivilegesError(e)) { + throw e; + } + // An error is also thrown when no jobs are found + } + + return { + jobIds, + timing: { spans: jobSpans }, + }; +} + +export async function getMetricK8sAnomalies( + context: RequestHandlerContext & { infra: Required }, + sourceId: string, + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) { + const finalizeMetricsK8sAnomaliesSpan = startTracingSpan('get metrics k8s entry anomalies'); + + const { + jobIds, + timing: { spans: jobSpans }, + } = await getCompatibleAnomaliesJobIds( + context.infra.spaceId, + sourceId, + context.infra.mlAnomalyDetectors + ); + + if (jobIds.length === 0) { + throw new InsufficientAnomalyMlJobsConfigured( + 'Log rate or categorisation ML jobs need to be configured to search anomalies' + ); + } + + const { + anomalies, + paginationCursors, + hasMoreEntries, + timing: { spans: fetchLogEntryAnomaliesSpans }, + } = await fetchMetricK8sAnomalies( + context.infra.mlSystem, + jobIds, + startTime, + endTime, + sort, + pagination + ); + + const data = anomalies.map((anomaly) => { + const { jobId } = anomaly; + + return parseAnomalyResult(anomaly, jobId); + }); + + const metricsK8sAnomaliesSpan = finalizeMetricsK8sAnomaliesSpan(); + + return { + data, + paginationCursors, + hasMoreEntries, + timing: { + spans: [metricsK8sAnomaliesSpan, ...jobSpans, ...fetchLogEntryAnomaliesSpans], + }, + }; +} + +const parseAnomalyResult = (anomaly: MappedAnomalyHit, jobId: string) => { + const { + id, + anomalyScore, + // dataset, + typical, + actual, + duration, + startTime: anomalyStartTime, + } = anomaly; + + return { + id, + anomalyScore, + // dataset, + typical, + actual, + duration, + startTime: anomalyStartTime, + type: 'metrics_k8s' as const, + jobId, + }; +}; + +async function fetchMetricK8sAnomalies( + mlSystem: MlSystem, + jobIds: string[], + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) { + // We'll request 1 extra entry on top of our pageSize to determine if there are + // more entries to be fetched. This avoids scenarios where the client side can't + // determine if entries.length === pageSize actually means there are more entries / next page + // or not. + const expandedPagination = { ...pagination, pageSize: pagination.pageSize + 1 }; + + const finalizeFetchLogEntryAnomaliesSpan = startTracingSpan('fetch metrics k8s anomalies'); + + const results = decodeOrThrow(metricsK8sAnomaliesResponseRT)( + await mlSystem.mlAnomalySearch( + createMetricsK8sAnomaliesQuery(jobIds, startTime, endTime, sort, expandedPagination) + ) + ); + + const { + hits: { hits }, + } = results; + const hasMoreEntries = hits.length > pagination.pageSize; + + // An extra entry was found and hasMoreEntries has been determined, the extra entry can be removed. + if (hasMoreEntries) { + hits.pop(); + } + + // To "search_before" the sort order will have been reversed for ES. + // The results are now reversed back, to match the requested sort. + if (pagination.cursor && 'searchBefore' in pagination.cursor) { + hits.reverse(); + } + + const paginationCursors = + hits.length > 0 + ? { + previousPageCursor: hits[0].sort, + nextPageCursor: hits[hits.length - 1].sort, + } + : undefined; + + const anomalies = hits.map((result) => { + const { + // eslint-disable-next-line @typescript-eslint/naming-convention + job_id, + record_score: anomalyScore, + typical, + actual, + // partition_field_value: dataset, + bucket_span: duration, + timestamp: anomalyStartTime, + by_field_value: categoryId, + } = result._source; + + return { + id: result._id, + anomalyScore, + // dataset, + typical: typical[0], + actual: actual[0], + jobId: job_id, + startTime: anomalyStartTime, + duration: duration * 1000, + categoryId, + }; + }); + + const fetchLogEntryAnomaliesSpan = finalizeFetchLogEntryAnomaliesSpan(); + + return { + anomalies, + paginationCursors, + hasMoreEntries, + timing: { + spans: [fetchLogEntryAnomaliesSpan], + }, + }; +} + +// TODO: FIgure out why we need datasets +export async function getMetricK8sAnomaliesDatasets( + context: { + infra: { + mlSystem: MlSystem; + mlAnomalyDetectors: MlAnomalyDetectors; + spaceId: string; + }; + }, + sourceId: string, + startTime: number, + endTime: number +) { + const { + jobIds, + timing: { spans: jobSpans }, + } = await getCompatibleAnomaliesJobIds( + context.infra.spaceId, + sourceId, + context.infra.mlAnomalyDetectors + ); + + if (jobIds.length === 0) { + throw new InsufficientAnomalyMlJobsConfigured( + 'Log rate or categorisation ML jobs need to be configured to search for anomaly datasets' + ); + } + + const { + data: datasets, + timing: { spans: datasetsSpans }, + } = await getLogEntryDatasets(context.infra.mlSystem, startTime, endTime, jobIds); + + return { + datasets, + timing: { + spans: [...jobSpans, ...datasetsSpans], + }, + }; +} diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts new file mode 100644 index 00000000000000..63e39ef022392a --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const defaultRequestParameters = { + allowNoIndices: true, + ignoreUnavailable: true, + trackScores: false, + trackTotalHits: false, +}; + +export const createJobIdFilters = (jobId: string) => [ + { + term: { + job_id: { + value: jobId, + }, + }, + }, +]; + +export const createJobIdsFilters = (jobIds: string[]) => [ + { + terms: { + job_id: jobIds, + }, + }, +]; + +export const createTimeRangeFilters = (startTime: number, endTime: number) => [ + { + range: { + timestamp: { + gte: startTime, + lte: endTime, + }, + }, + }, +]; + +export const createResultTypeFilters = (resultTypes: Array<'model_plot' | 'record'>) => [ + { + terms: { + result_type: resultTypes, + }, + }, +]; + +export const createCategoryIdFilters = (categoryIds: number[]) => [ + { + terms: { + category_id: categoryIds, + }, + }, +]; + +export const createDatasetsFilters = (datasets?: string[]) => + datasets && datasets.length > 0 + ? [ + { + terms: { + partition_field_value: datasets, + }, + }, + ] + : []; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/index.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/index.ts new file mode 100644 index 00000000000000..5a42011e1cea12 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export * from './metrics_k8s_anomalies'; +export * from './metrics_hosts_anomalies'; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/log_entry_data_sets.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/log_entry_data_sets.ts new file mode 100644 index 00000000000000..53971a91d86b14 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/log_entry_data_sets.ts @@ -0,0 +1,84 @@ +/* + * 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 * as rt from 'io-ts'; +import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; +import { + createJobIdsFilters, + createResultTypeFilters, + createTimeRangeFilters, + defaultRequestParameters, +} from './common'; + +export const createLogEntryDatasetsQuery = ( + jobIds: string[], + startTime: number, + endTime: number, + size: number, + afterKey?: CompositeDatasetKey +) => ({ + ...defaultRequestParameters, + body: { + query: { + bool: { + filter: [ + ...createJobIdsFilters(jobIds), + ...createTimeRangeFilters(startTime, endTime), + ...createResultTypeFilters(['model_plot']), + ], + }, + }, + aggs: { + dataset_buckets: { + composite: { + after: afterKey, + size, + sources: [ + { + dataset: { + terms: { + field: 'partition_field_value', + order: 'asc', + }, + }, + }, + ], + }, + }, + }, + }, + size: 0, +}); + +const compositeDatasetKeyRT = rt.type({ + dataset: rt.string, +}); + +export type CompositeDatasetKey = rt.TypeOf; + +const logEntryDatasetBucketRT = rt.type({ + key: compositeDatasetKeyRT, +}); + +export type LogEntryDatasetBucket = rt.TypeOf; + +export const logEntryDatasetsResponseRT = rt.intersection([ + commonSearchSuccessResponseFieldsRT, + rt.partial({ + aggregations: rt.type({ + dataset_buckets: rt.intersection([ + rt.type({ + buckets: rt.array(logEntryDatasetBucketRT), + }), + rt.partial({ + after_key: compositeDatasetKeyRT, + }), + ]), + }), + }), +]); + +export type LogEntryDatasetsResponse = rt.TypeOf; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts new file mode 100644 index 00000000000000..b61119b60bc184 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_hosts_anomalies.ts @@ -0,0 +1,131 @@ +/* + * 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 * as rt from 'io-ts'; +import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; +import { + createJobIdsFilters, + createTimeRangeFilters, + createResultTypeFilters, + defaultRequestParameters, +} from './common'; +import { Sort, Pagination } from '../../../../common/http_api/infra_ml'; + +// TODO: Reassess validity of this against ML docs +const TIEBREAKER_FIELD = '_doc'; + +const sortToMlFieldMap = { + dataset: 'partition_field_value', + anomalyScore: 'record_score', + startTime: 'timestamp', +}; + +export const createMetricsHostsAnomaliesQuery = ( + jobIds: string[], + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) => { + const { field } = sort; + const { pageSize } = pagination; + + const filters = [ + ...createJobIdsFilters(jobIds), + ...createTimeRangeFilters(startTime, endTime), + ...createResultTypeFilters(['record']), + ]; + + const sourceFields = [ + 'job_id', + 'record_score', + 'typical', + 'actual', + 'partition_field_value', + 'timestamp', + 'bucket_span', + 'by_field_value', + 'host.name', + 'influencers.influencer_field_name', + 'influencers.influencer_field_values', + ]; + + const { querySortDirection, queryCursor } = parsePaginationCursor(sort, pagination); + + const sortOptions = [ + { [sortToMlFieldMap[field]]: querySortDirection }, + { [TIEBREAKER_FIELD]: querySortDirection }, // Tiebreaker + ]; + + const resultsQuery = { + ...defaultRequestParameters, + body: { + query: { + bool: { + filter: filters, + }, + }, + search_after: queryCursor, + sort: sortOptions, + size: pageSize, + _source: sourceFields, + }, + }; + + return resultsQuery; +}; + +export const metricsHostsAnomalyHitRT = rt.type({ + _id: rt.string, + _source: rt.intersection([ + rt.type({ + job_id: rt.string, + record_score: rt.number, + typical: rt.array(rt.number), + actual: rt.array(rt.number), + 'host.name': rt.array(rt.string), + bucket_span: rt.number, + timestamp: rt.number, + }), + rt.partial({ + by_field_value: rt.string, + }), + ]), + sort: rt.tuple([rt.union([rt.string, rt.number]), rt.union([rt.string, rt.number])]), +}); + +export type MetricsHostsAnomalyHit = rt.TypeOf; + +export const metricsHostsAnomaliesResponseRT = rt.intersection([ + commonSearchSuccessResponseFieldsRT, + rt.type({ + hits: rt.type({ + hits: rt.array(metricsHostsAnomalyHitRT), + }), + }), +]); + +export type MetricsHostsAnomaliesResponseRT = rt.TypeOf; + +const parsePaginationCursor = (sort: Sort, pagination: Pagination) => { + const { cursor } = pagination; + const { direction } = sort; + + if (!cursor) { + return { querySortDirection: direction, queryCursor: undefined }; + } + + // We will always use ES's search_after to paginate, to mimic "search_before" behaviour we + // need to reverse the user's chosen search direction for the ES query. + if ('searchBefore' in cursor) { + return { + querySortDirection: direction === 'desc' ? 'asc' : 'desc', + queryCursor: cursor.searchBefore, + }; + } else { + return { querySortDirection: direction, queryCursor: cursor.searchAfter }; + } +}; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts new file mode 100644 index 00000000000000..84ed8b064c5ca8 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/metrics_k8s_anomalies.ts @@ -0,0 +1,128 @@ +/* + * 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 * as rt from 'io-ts'; +import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; +import { + createJobIdsFilters, + createTimeRangeFilters, + createResultTypeFilters, + defaultRequestParameters, +} from './common'; +import { Sort, Pagination } from '../../../../common/http_api/infra_ml'; + +// TODO: Reassess validity of this against ML docs +const TIEBREAKER_FIELD = '_doc'; + +const sortToMlFieldMap = { + dataset: 'partition_field_value', + anomalyScore: 'record_score', + startTime: 'timestamp', +}; + +export const createMetricsK8sAnomaliesQuery = ( + jobIds: string[], + startTime: number, + endTime: number, + sort: Sort, + pagination: Pagination +) => { + const { field } = sort; + const { pageSize } = pagination; + + const filters = [ + ...createJobIdsFilters(jobIds), + ...createTimeRangeFilters(startTime, endTime), + ...createResultTypeFilters(['record']), + ]; + + const sourceFields = [ + 'job_id', + 'record_score', + 'typical', + 'actual', + 'partition_field_value', + 'timestamp', + 'bucket_span', + 'by_field_value', + ]; + + const { querySortDirection, queryCursor } = parsePaginationCursor(sort, pagination); + + const sortOptions = [ + { [sortToMlFieldMap[field]]: querySortDirection }, + { [TIEBREAKER_FIELD]: querySortDirection }, // Tiebreaker + ]; + + const resultsQuery = { + ...defaultRequestParameters, + body: { + query: { + bool: { + filter: filters, + }, + }, + search_after: queryCursor, + sort: sortOptions, + size: pageSize, + _source: sourceFields, + }, + }; + + return resultsQuery; +}; + +export const metricsK8sAnomalyHitRT = rt.type({ + _id: rt.string, + _source: rt.intersection([ + rt.type({ + job_id: rt.string, + record_score: rt.number, + typical: rt.array(rt.number), + actual: rt.array(rt.number), + // partition_field_value: rt.string, + bucket_span: rt.number, + timestamp: rt.number, + }), + rt.partial({ + by_field_value: rt.string, + }), + ]), + sort: rt.tuple([rt.union([rt.string, rt.number]), rt.union([rt.string, rt.number])]), +}); + +export type MetricsK8sAnomalyHit = rt.TypeOf; + +export const metricsK8sAnomaliesResponseRT = rt.intersection([ + commonSearchSuccessResponseFieldsRT, + rt.type({ + hits: rt.type({ + hits: rt.array(metricsK8sAnomalyHitRT), + }), + }), +]); + +export type MetricsK8sAnomaliesResponseRT = rt.TypeOf; + +const parsePaginationCursor = (sort: Sort, pagination: Pagination) => { + const { cursor } = pagination; + const { direction } = sort; + + if (!cursor) { + return { querySortDirection: direction, queryCursor: undefined }; + } + + // We will always use ES's search_after to paginate, to mimic "search_before" behaviour we + // need to reverse the user's chosen search direction for the ES query. + if ('searchBefore' in cursor) { + return { + querySortDirection: direction === 'desc' ? 'asc' : 'desc', + queryCursor: cursor.searchBefore, + }; + } else { + return { querySortDirection: direction, queryCursor: cursor.searchAfter }; + } +}; diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/ml_jobs.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/ml_jobs.ts new file mode 100644 index 00000000000000..ee4ccbfaeb5a7d --- /dev/null +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/ml_jobs.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as rt from 'io-ts'; + +export const createMlJobsQuery = (jobIds: string[]) => ({ + method: 'GET', + path: `/_ml/anomaly_detectors/${jobIds.join(',')}`, + query: { + allow_no_jobs: true, + }, +}); + +export const mlJobRT = rt.type({ + job_id: rt.string, + custom_settings: rt.unknown, +}); + +export const mlJobsResponseRT = rt.type({ + jobs: rt.array(mlJobRT), +}); diff --git a/x-pack/plugins/infra/server/routes/infra_ml/index.ts b/x-pack/plugins/infra/server/routes/infra_ml/index.ts new file mode 100644 index 00000000000000..38684cb22e237f --- /dev/null +++ b/x-pack/plugins/infra/server/routes/infra_ml/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './results'; diff --git a/x-pack/plugins/infra/server/routes/infra_ml/results/index.ts b/x-pack/plugins/infra/server/routes/infra_ml/results/index.ts new file mode 100644 index 00000000000000..82e30291faa207 --- /dev/null +++ b/x-pack/plugins/infra/server/routes/infra_ml/results/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './metrics_hosts_anomalies'; +export * from './metrics_k8s_anomalies'; diff --git a/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts new file mode 100644 index 00000000000000..29122ae159cdc3 --- /dev/null +++ b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_hosts_anomalies.ts @@ -0,0 +1,125 @@ +/* + * 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 Boom from 'boom'; +import { InfraBackendLibs } from '../../../lib/infra_types'; +import { + INFA_ML_GET_METRICS_HOSTS_ANOMALIES_PATH, + getMetricsHostsAnomaliesSuccessReponsePayloadRT, + getMetricsHostsAnomaliesRequestPayloadRT, + GetMetricsHostsAnomaliesRequestPayload, + Sort, + Pagination, +} from '../../../../common/http_api/infra_ml'; +import { createValidationFunction } from '../../../../common/runtime_types'; +import { assertHasInfraMlPlugins } from '../../../utils/request_context'; + +import { isMlPrivilegesError } from '../../../lib/infra_ml/errors'; +import { getMetricsHostsAnomalies } from '../../../lib/infra_ml'; + +export const initGetHostsAnomaliesRoute = ({ framework }: InfraBackendLibs) => { + framework.registerRoute( + { + method: 'post', + path: INFA_ML_GET_METRICS_HOSTS_ANOMALIES_PATH, + validate: { + body: createValidationFunction(getMetricsHostsAnomaliesRequestPayloadRT), + }, + }, + framework.router.handleLegacyErrors(async (requestContext, request, response) => { + const { + data: { + sourceId, + timeRange: { startTime, endTime }, + sort: sortParam, + pagination: paginationParam, + }, + } = request.body; + + const { sort, pagination } = getSortAndPagination(sortParam, paginationParam); + + try { + assertHasInfraMlPlugins(requestContext); + + const { + data: anomalies, + paginationCursors, + hasMoreEntries, + timing, + } = await getMetricsHostsAnomalies( + requestContext, + sourceId, + startTime, + endTime, + sort, + pagination + ); + + // console.log('---- anomalies', anomalies); + + return response.ok({ + body: getMetricsHostsAnomaliesSuccessReponsePayloadRT.encode({ + data: { + anomalies, + hasMoreEntries, + paginationCursors, + }, + timing, + }), + }); + } catch (error) { + if (Boom.isBoom(error)) { + throw error; + } + + if (isMlPrivilegesError(error)) { + return response.customError({ + statusCode: 403, + body: { + message: error.message, + }, + }); + } + + return response.customError({ + statusCode: error.statusCode ?? 500, + body: { + message: error.message ?? 'An unexpected error occurred', + }, + }); + } + }) + ); +}; + +const getSortAndPagination = ( + sort: Partial = {}, + pagination: Partial = {} +): { + sort: Sort; + pagination: Pagination; +} => { + const sortDefaults = { + field: 'anomalyScore' as const, + direction: 'desc' as const, + }; + + const sortWithDefaults = { + ...sortDefaults, + ...sort, + }; + + const paginationDefaults = { + pageSize: 50, + }; + + const paginationWithDefaults = { + ...paginationDefaults, + ...pagination, + }; + + return { sort: sortWithDefaults, pagination: paginationWithDefaults }; +}; diff --git a/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts new file mode 100644 index 00000000000000..5260c55836c59d --- /dev/null +++ b/x-pack/plugins/infra/server/routes/infra_ml/results/metrics_k8s_anomalies.ts @@ -0,0 +1,122 @@ +/* + * 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 Boom from 'boom'; +import { InfraBackendLibs } from '../../../lib/infra_types'; +import { + INFA_ML_GET_METRICS_K8S_ANOMALIES_PATH, + getMetricsK8sAnomaliesSuccessReponsePayloadRT, + getMetricsK8sAnomaliesRequestPayloadRT, + GetMetricsK8sAnomaliesRequestPayload, + Sort, + Pagination, +} from '../../../../common/http_api/infra_ml'; +import { createValidationFunction } from '../../../../common/runtime_types'; +import { assertHasInfraMlPlugins } from '../../../utils/request_context'; +import { getMetricK8sAnomalies } from '../../../lib/infra_ml'; +import { isMlPrivilegesError } from '../../../lib/infra_ml/errors'; + +export const initGetK8sAnomaliesRoute = ({ framework }: InfraBackendLibs) => { + framework.registerRoute( + { + method: 'post', + path: INFA_ML_GET_METRICS_K8S_ANOMALIES_PATH, + validate: { + body: createValidationFunction(getMetricsK8sAnomaliesRequestPayloadRT), + }, + }, + framework.router.handleLegacyErrors(async (requestContext, request, response) => { + const { + data: { + sourceId, + timeRange: { startTime, endTime }, + sort: sortParam, + pagination: paginationParam, + }, + } = request.body; + + const { sort, pagination } = getSortAndPagination(sortParam, paginationParam); + + try { + assertHasInfraMlPlugins(requestContext); + + const { + data: anomalies, + paginationCursors, + hasMoreEntries, + timing, + } = await getMetricK8sAnomalies( + requestContext, + sourceId, + startTime, + endTime, + sort, + pagination + ); + + return response.ok({ + body: getMetricsK8sAnomaliesSuccessReponsePayloadRT.encode({ + data: { + anomalies, + hasMoreEntries, + paginationCursors, + }, + timing, + }), + }); + } catch (error) { + if (Boom.isBoom(error)) { + throw error; + } + + if (isMlPrivilegesError(error)) { + return response.customError({ + statusCode: 403, + body: { + message: error.message, + }, + }); + } + + return response.customError({ + statusCode: error.statusCode ?? 500, + body: { + message: error.message ?? 'An unexpected error occurred', + }, + }); + } + }) + ); +}; + +const getSortAndPagination = ( + sort: Partial = {}, + pagination: Partial = {} +): { + sort: Sort; + pagination: Pagination; +} => { + const sortDefaults = { + field: 'anomalyScore' as const, + direction: 'desc' as const, + }; + + const sortWithDefaults = { + ...sortDefaults, + ...sort, + }; + + const paginationDefaults = { + pageSize: 50, + }; + + const paginationWithDefaults = { + ...paginationDefaults, + ...pagination, + }; + + return { sort: sortWithDefaults, pagination: paginationWithDefaults }; +}; diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts index 814ec5e74ff339..b18b45f4935d20 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { findInventoryFields } from '../../../../common/inventory_models'; +import { findInventoryFields, findInventoryModel } from '../../../../common/inventory_models'; import { MetricsAPIRequest, SnapshotRequest } from '../../../../common/http_api'; import { ESSearchClient } from '../../../lib/metrics/types'; import { InfraSource } from '../../../lib/sources'; @@ -34,7 +34,7 @@ export const transformRequestToMetricsAPIRequest = async ( interval: timeRangeWithIntervalApplied.interval, }, metrics: transformSnapshotMetricsToMetricsAPIMetrics(snapshotRequest), - limit: snapshotRequest.overrideCompositeSize ? snapshotRequest.overrideCompositeSize : 10, + limit: snapshotRequest.overrideCompositeSize ? snapshotRequest.overrideCompositeSize : 5, alignDataToEnd: true, }; @@ -52,6 +52,11 @@ export const transformRequestToMetricsAPIRequest = async ( filters.push({ term: { 'cloud.region': snapshotRequest.region } }); } + const inventoryModel = findInventoryModel(snapshotRequest.nodeType); + if (inventoryModel && inventoryModel.nodeFilter) { + inventoryModel.nodeFilter?.forEach((f) => filters.push(f)); + } + const inventoryFields = findInventoryFields( snapshotRequest.nodeType, source.configuration.fields diff --git a/x-pack/plugins/ingest_manager/common/constants/routes.ts b/x-pack/plugins/ingest_manager/common/constants/routes.ts index d899739a74ef00..69672dfb9ec6cc 100644 --- a/x-pack/plugins/ingest_manager/common/constants/routes.ts +++ b/x-pack/plugins/ingest_manager/common/constants/routes.ts @@ -90,6 +90,7 @@ export const AGENT_API_ROUTES = { REASSIGN_PATTERN: `${FLEET_API_ROOT}/agents/{agentId}/reassign`, BULK_REASSIGN_PATTERN: `${FLEET_API_ROOT}/agents/bulk_reassign`, STATUS_PATTERN: `${FLEET_API_ROOT}/agent-status`, + UPGRADE_PATTERN: `${FLEET_API_ROOT}/agents/{agentId}/upgrade`, }; export const ENROLLMENT_API_KEY_ROUTES = { diff --git a/x-pack/plugins/ingest_manager/common/services/agent_status.ts b/x-pack/plugins/ingest_manager/common/services/agent_status.ts index fe4e094e1bb229..70f4d7f9344f97 100644 --- a/x-pack/plugins/ingest_manager/common/services/agent_status.ts +++ b/x-pack/plugins/ingest_manager/common/services/agent_status.ts @@ -19,6 +19,9 @@ export function getAgentStatus(agent: Agent, now: number = Date.now()): AgentSta if (!agent.last_checkin) { return 'enrolling'; } + if (agent.upgrade_started_at && !agent.upgraded_at) { + return 'upgrading'; + } const msLastCheckIn = new Date(lastCheckIn || 0).getTime(); const msSinceLastCheckIn = new Date().getTime() - msLastCheckIn; diff --git a/x-pack/plugins/ingest_manager/common/types/models/agent.ts b/x-pack/plugins/ingest_manager/common/types/models/agent.ts index a204373fe2e56b..7110fd4ce52eac 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/agent.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/agent.ts @@ -19,10 +19,10 @@ export type AgentStatus = | 'warning' | 'enrolling' | 'unenrolling' + | 'upgrading' | 'degraded'; -export type AgentActionType = 'CONFIG_CHANGE' | 'UNENROLL'; - +export type AgentActionType = 'CONFIG_CHANGE' | 'UNENROLL' | 'UPGRADE'; export interface NewAgentAction { type: AgentActionType; data?: any; @@ -65,7 +65,6 @@ export type AgentPolicyActionSOAttributes = CommonAgentActionSOAttributes & { policy_id: string; policy_revision: number; }; - export type BaseAgentActionSOAttributes = AgentActionSOAttributes | AgentPolicyActionSOAttributes; export interface NewAgentEvent { @@ -110,6 +109,8 @@ interface AgentBase { enrolled_at: string; unenrolled_at?: string; unenrollment_started_at?: string; + upgraded_at?: string; + upgrade_started_at?: string; shared_id?: string; access_api_key_id?: string; default_api_key?: string; diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts index 1a10d4930656f6..ab4c372c4e1d61 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts @@ -113,6 +113,11 @@ export interface PostAgentUnenrollRequest { // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PostAgentUnenrollResponse {} +export interface PostAgentUpgradeRequest { + params: { + agentId: string; + }; +} export interface PostBulkAgentUnenrollRequest { body: { agents: string[] | string; @@ -120,6 +125,8 @@ export interface PostBulkAgentUnenrollRequest { }; } +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface PostAgentUpgradeResponse {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PostBulkAgentUnenrollResponse {} diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/index.ts b/x-pack/plugins/ingest_manager/server/routes/agent/index.ts index eafc726ea166d2..73ed276ba02e74 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent/index.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent/index.ts @@ -29,6 +29,7 @@ import { PutAgentReassignRequestSchema, PostBulkAgentReassignRequestSchema, PostAgentEnrollRequestBodyJSONSchema, + PostAgentUpgradeRequestSchema, } from '../../types'; import { getAgentsHandler, @@ -48,6 +49,7 @@ import { postNewAgentActionHandlerBuilder } from './actions_handlers'; import { appContextService } from '../../services'; import { postAgentUnenrollHandler, postBulkAgentsUnenrollHandler } from './unenroll_handler'; import { IngestManagerConfigType } from '../..'; +import { postAgentUpgradeHandler } from './upgrade_handler'; const ajv = new Ajv({ coerceTypes: true, @@ -215,7 +217,15 @@ export const registerRoutes = (router: IRouter, config: IngestManagerConfigType) }, getAgentStatusForAgentPolicyHandler ); - + // upgrade agent + router.post( + { + path: AGENT_API_ROUTES.UPGRADE_PATTERN, + validate: PostAgentUpgradeRequestSchema, + options: { tags: [`access:${PLUGIN_ID}-all`] }, + }, + postAgentUpgradeHandler + ); // Bulk reassign router.post( { diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/ingest_manager/server/routes/agent/upgrade_handler.ts new file mode 100644 index 00000000000000..e5d7a44c007682 --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/routes/agent/upgrade_handler.ts @@ -0,0 +1,47 @@ +/* + * 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 { RequestHandler } from 'src/core/server'; +import { TypeOf } from '@kbn/config-schema'; +import { PostAgentUpgradeResponse } from '../../../common/types'; +import { PostAgentUpgradeRequestSchema } from '../../types'; +import * as AgentService from '../../services/agents'; +import { appContextService } from '../../services'; +import { defaultIngestErrorHandler } from '../../errors'; + +export const postAgentUpgradeHandler: RequestHandler< + TypeOf, + undefined, + TypeOf +> = async (context, request, response) => { + const soClient = context.core.savedObjects.client; + const { version, source_uri: sourceUri } = request.body; + + // temporarily only allow upgrading to the same version as the installed kibana version + const kibanaVersion = appContextService.getKibanaVersion(); + if (kibanaVersion !== version) { + return response.customError({ + statusCode: 400, + body: { + message: `cannot upgrade agent to ${version} because it is different than the installed kibana version ${kibanaVersion}`, + }, + }); + } + + try { + await AgentService.sendUpgradeAgentAction({ + soClient, + agentId: request.params.agentId, + version, + sourceUri, + }); + + const body: PostAgentUpgradeResponse = {}; + return response.ok({ body }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); + } +}; diff --git a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts b/x-pack/plugins/ingest_manager/server/saved_objects/index.ts index e86f7b24e2c784..fd08b76a3916b3 100644 --- a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts +++ b/x-pack/plugins/ingest_manager/server/saved_objects/index.ts @@ -68,6 +68,8 @@ const savedObjectTypes: { [key: string]: SavedObjectsType } = { enrolled_at: { type: 'date' }, unenrolled_at: { type: 'date' }, unenrollment_started_at: { type: 'date' }, + upgraded_at: { type: 'date' }, + upgrade_started_at: { type: 'date' }, access_api_key_id: { type: 'keyword' }, version: { type: 'keyword' }, user_provided_metadata: { type: 'flattened' }, diff --git a/x-pack/plugins/ingest_manager/server/services/agents/acks.ts b/x-pack/plugins/ingest_manager/server/services/agents/acks.ts index 1392710eb0eff4..e22ee4256b0e29 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/acks.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/acks.ts @@ -28,6 +28,7 @@ import { } from '../../constants'; import { getAgentActionByIds } from './actions'; import { forceUnenrollAgent } from './unenroll'; +import { ackAgentUpgraded } from './upgrade'; const ALLOWED_ACKNOWLEDGEMENT_TYPE: string[] = ['ACTION_RESULT']; @@ -80,6 +81,11 @@ export async function acknowledgeAgentActions( await forceUnenrollAgent(soClient, agent.id); } + const upgradeAction = actions.find((action) => action.type === 'UPGRADE'); + if (upgradeAction) { + await ackAgentUpgraded(soClient, upgradeAction); + } + const configChangeAction = getLatestConfigChangePolicyActionIfUpdated(agent, actions); await soClient.bulkUpdate([ diff --git a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts b/x-pack/plugins/ingest_manager/server/services/agents/actions.ts index 1d4db44edf88ae..f018eea61e4f31 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/actions.ts @@ -225,7 +225,11 @@ export async function getAgentPolicyActionByIds( ); } -export async function getNewActionsSince(soClient: SavedObjectsClientContract, timestamp: string) { +export async function getNewActionsSince( + soClient: SavedObjectsClientContract, + timestamp: string, + decryptData: boolean = true +) { const filter = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode( 'not', @@ -243,14 +247,33 @@ export async function getNewActionsSince(soClient: SavedObjectsClientContract, t } ), ]); - const res = await soClient.find({ - type: AGENT_ACTION_SAVED_OBJECT_TYPE, - filter, - }); - return res.saved_objects + const actions = ( + await soClient.find({ + type: AGENT_ACTION_SAVED_OBJECT_TYPE, + filter, + }) + ).saved_objects .filter(isAgentActionSavedObject) .map((so) => savedObjectToAgentAction(so)); + + if (!decryptData) { + return actions; + } + + return await Promise.all( + actions.map(async (action) => { + // Get decrypted actions + return savedObjectToAgentAction( + await appContextService + .getEncryptedSavedObjects() + .getDecryptedAsInternalUser( + AGENT_ACTION_SAVED_OBJECT_TYPE, + action.id + ) + ); + }) + ); } export async function getLatestConfigChangeAction( diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.test.ts b/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.test.ts new file mode 100644 index 00000000000000..5e84e3a50bb440 --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.test.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { TestScheduler } from 'rxjs/testing'; +import { createRateLimiter } from './rxjs_utils'; + +describe('createRateLimiter', () => { + it('should rate limit correctly with 1 request per 10ms', async () => { + const scheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + + scheduler.run(({ expectObservable, cold }) => { + const source = cold('a-b-c-d-e-f|'); + const rateLimiter = createRateLimiter(10, 1, 2, scheduler); + const obs = source.pipe(rateLimiter()); + const results = 'a 9ms b 9ms c 9ms d 9ms e 9ms (f|)'; + expectObservable(obs).toBe(results); + }); + }); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.ts b/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.ts index dddade68414604..3bbfbbd4ec1bfb 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.ts @@ -5,6 +5,7 @@ */ import * as Rx from 'rxjs'; +import { concatMap, delay } from 'rxjs/operators'; export class AbortError extends Error {} @@ -45,63 +46,35 @@ export const toPromiseAbortable = ( export function createRateLimiter( ratelimitIntervalMs: number, - ratelimitRequestPerInterval: number + ratelimitRequestPerInterval: number, + maxDelay: number, + scheduler = Rx.asyncScheduler ) { - function createCurrentInterval() { - return { - startedAt: Rx.asyncScheduler.now(), - numRequests: 0, - }; - } + let intervalEnd = 0; + let countInCurrentInterval = 0; - let currentInterval: { startedAt: number; numRequests: number } = createCurrentInterval(); - let observers: Array<[Rx.Subscriber, any]> = []; - let timerSubscription: Rx.Subscription | undefined; + function createRateLimitOperator(): Rx.OperatorFunction { + return Rx.pipe( + concatMap(function rateLimit(value: T) { + const now = scheduler.now(); + if (intervalEnd <= now) { + countInCurrentInterval = 1; + intervalEnd = now + ratelimitIntervalMs; + return Rx.of(value); + } else if (intervalEnd >= now + maxDelay) { + // re-rate limit in the future to avoid to schedule too far in the future as some observer can unsubscribe + return Rx.of(value).pipe(delay(maxDelay, scheduler), createRateLimitOperator()); + } else { + if (++countInCurrentInterval > ratelimitRequestPerInterval) { + countInCurrentInterval = 1; + intervalEnd += ratelimitIntervalMs; + } - function createTimeout() { - if (timerSubscription) { - return; - } - timerSubscription = Rx.asyncScheduler.schedule(() => { - timerSubscription = undefined; - currentInterval = createCurrentInterval(); - for (const [waitingObserver, value] of observers) { - if (currentInterval.numRequests >= ratelimitRequestPerInterval) { - createTimeout(); - continue; + const wait = intervalEnd - ratelimitIntervalMs - now; + return wait > 0 ? Rx.of(value).pipe(delay(wait, scheduler)) : Rx.of(value); } - currentInterval.numRequests++; - waitingObserver.next(value); - } - }, ratelimitIntervalMs); + }) + ); } - - return function limit(): Rx.MonoTypeOperatorFunction { - return (observable) => - new Rx.Observable((observer) => { - const subscription = observable.subscribe({ - next(value) { - if (currentInterval.numRequests < ratelimitRequestPerInterval) { - currentInterval.numRequests++; - observer.next(value); - return; - } - - observers = [...observers, [observer, value]]; - createTimeout(); - }, - error(err) { - observer.error(err); - }, - complete() { - observer.complete(); - }, - }); - - return () => { - observers = observers.filter((o) => o[0] !== observer); - subscription.unsubscribe(); - }; - }); - }; + return createRateLimitOperator; } diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts index 4122677a615ca8..fbbed87b031e24 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts @@ -10,7 +10,6 @@ import { shareReplay, distinctUntilKeyChanged, switchMap, - mergeMap, merge, filter, timeout, @@ -33,6 +32,8 @@ import { import { appContextService } from '../../app_context'; import { toPromiseAbortable, AbortError, createRateLimiter } from './rxjs_utils'; +const RATE_LIMIT_MAX_DELAY_MS = 5 * 60 * 1000; // 5 minutes + function getInternalUserSOClient() { const fakeRequest = ({ headers: {}, @@ -135,11 +136,19 @@ export function agentCheckinStateNewActionsFactory() { const agentPolicies$ = new Map>(); const newActions$ = createNewActionsSharedObservable(); // Rx operators - const rateLimiter = createRateLimiter( + const pollingTimeoutMs = appContextService.getConfig()?.fleet.pollingRequestTimeout ?? 0; + const rateLimiterIntervalMs = appContextService.getConfig()?.fleet.agentPolicyRolloutRateLimitIntervalMs ?? - AGENT_POLICY_ROLLOUT_RATE_LIMIT_INTERVAL_MS, + AGENT_POLICY_ROLLOUT_RATE_LIMIT_INTERVAL_MS; + const rateLimiterRequestPerInterval = appContextService.getConfig()?.fleet.agentPolicyRolloutRateLimitRequestPerInterval ?? - AGENT_POLICY_ROLLOUT_RATE_LIMIT_REQUEST_PER_INTERVAL + AGENT_POLICY_ROLLOUT_RATE_LIMIT_REQUEST_PER_INTERVAL; + const rateLimiterMaxDelay = Math.min(RATE_LIMIT_MAX_DELAY_MS, pollingTimeoutMs); + + const rateLimiter = createRateLimiter( + rateLimiterIntervalMs, + rateLimiterRequestPerInterval, + rateLimiterMaxDelay ); async function subscribeToNewActions( @@ -162,7 +171,7 @@ export function agentCheckinStateNewActionsFactory() { const stream$ = agentPolicy$.pipe( timeout( // Set a timeout 3s before the real timeout to have a chance to respond an empty response before socket timeout - Math.max((appContextService.getConfig()?.fleet.pollingRequestTimeout ?? 0) - 3000, 3000) + Math.max(pollingTimeoutMs - 3000, 3000) ), filter( (action) => @@ -173,9 +182,9 @@ export function agentCheckinStateNewActionsFactory() { (!agent.policy_revision || action.policy_revision > agent.policy_revision) ), rateLimiter(), - mergeMap((policyAction) => createAgentActionFromPolicyAction(soClient, agent, policyAction)), + switchMap((policyAction) => createAgentActionFromPolicyAction(soClient, agent, policyAction)), merge(newActions$), - mergeMap(async (data) => { + switchMap(async (data) => { if (!data) { return; } diff --git a/x-pack/plugins/ingest_manager/server/services/agents/index.ts b/x-pack/plugins/ingest_manager/server/services/agents/index.ts index 400c099af4e936..c878b666bde886 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/index.ts @@ -9,6 +9,7 @@ export * from './events'; export * from './checkin'; export * from './enroll'; export * from './unenroll'; +export * from './upgrade'; export * from './status'; export * from './crud'; export * from './update'; diff --git a/x-pack/plugins/ingest_manager/server/services/agents/upgrade.ts b/x-pack/plugins/ingest_manager/server/services/agents/upgrade.ts new file mode 100644 index 00000000000000..cee3bc69f25dba --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/agents/upgrade.ts @@ -0,0 +1,61 @@ +/* + * 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 { SavedObjectsClientContract } from 'src/core/server'; +import { AgentSOAttributes, AgentAction, AgentActionSOAttributes } from '../../types'; +import { AGENT_ACTION_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE } from '../../constants'; +import { createAgentAction } from './actions'; + +export async function sendUpgradeAgentAction({ + soClient, + agentId, + version, + sourceUri, +}: { + soClient: SavedObjectsClientContract; + agentId: string; + version: string; + sourceUri: string; +}) { + const now = new Date().toISOString(); + const data = { + version, + source_uri: sourceUri, + }; + await createAgentAction(soClient, { + agent_id: agentId, + created_at: now, + data, + ack_data: data, + type: 'UPGRADE', + }); + await soClient.update(AGENT_SAVED_OBJECT_TYPE, agentId, { + upgraded_at: undefined, + upgrade_started_at: now, + }); +} + +export async function ackAgentUpgraded( + soClient: SavedObjectsClientContract, + agentAction: AgentAction +) { + const { + attributes: { ack_data: ackData }, + } = await soClient.get(AGENT_ACTION_SAVED_OBJECT_TYPE, agentAction.id); + if (!ackData) throw new Error('data missing from UPGRADE action'); + const { version } = JSON.parse(ackData); + if (!version) throw new Error('version missing from UPGRADE action'); + await soClient.update(AGENT_SAVED_OBJECT_TYPE, agentAction.agent_id, { + upgraded_at: new Date().toISOString(), + local_metadata: { + elastic: { + agent: { + version, + }, + }, + }, + }); +} diff --git a/x-pack/plugins/ingest_manager/server/types/models/agent.ts b/x-pack/plugins/ingest_manager/server/types/models/agent.ts index b249705fe6c2fd..15004e60a6fa46 100644 --- a/x-pack/plugins/ingest_manager/server/types/models/agent.ts +++ b/x-pack/plugins/ingest_manager/server/types/models/agent.ts @@ -62,7 +62,12 @@ export const AgentEventSchema = schema.object({ }); export const NewAgentActionSchema = schema.object({ - type: schema.oneOf([schema.literal('CONFIG_CHANGE'), schema.literal('UNENROLL')]), + type: schema.oneOf([ + schema.literal('CONFIG_CHANGE'), + schema.literal('UNENROLL'), + schema.literal('UPGRADE'), + ]), data: schema.maybe(schema.any()), + ack_data: schema.maybe(schema.any()), sent_at: schema.maybe(schema.string()), }); diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/agent.ts b/x-pack/plugins/ingest_manager/server/types/rest_spec/agent.ts index 4aefa56e0ca0a1..3866ef095563e4 100644 --- a/x-pack/plugins/ingest_manager/server/types/rest_spec/agent.ts +++ b/x-pack/plugins/ingest_manager/server/types/rest_spec/agent.ts @@ -172,6 +172,16 @@ export const PostAgentUnenrollRequestSchema = { ), }; +export const PostAgentUpgradeRequestSchema = { + params: schema.object({ + agentId: schema.string(), + }), + body: schema.object({ + source_uri: schema.string(), + version: schema.string(), + }), +}; + export const PostBulkAgentUnenrollRequestSchema = { body: schema.object({ agents: schema.oneOf([schema.arrayOf(schema.string()), schema.string()]), diff --git a/x-pack/plugins/lens/common/constants.ts b/x-pack/plugins/lens/common/constants.ts index ea2331a577743f..d30ab5962667d4 100644 --- a/x-pack/plugins/lens/common/constants.ts +++ b/x-pack/plugins/lens/common/constants.ts @@ -8,15 +8,16 @@ export const PLUGIN_ID = 'lens'; export const LENS_EMBEDDABLE_TYPE = 'lens'; export const NOT_INTERNATIONALIZED_PRODUCT_NAME = 'Lens Visualizations'; export const BASE_API_URL = '/api/lens'; +export const LENS_EDIT_BY_VALUE = 'edit_by_value'; export function getBasePath() { return `#/`; } -export function getEditPath(id: string) { - return `#/edit/${encodeURIComponent(id)}`; +export function getEditPath(id: string | undefined) { + return id ? `#/edit/${encodeURIComponent(id)}` : `#/${LENS_EDIT_BY_VALUE}`; } -export function getFullPath(id: string) { - return `/app/${PLUGIN_ID}${getEditPath(id)}`; +export function getFullPath(id?: string) { + return `/app/${PLUGIN_ID}${id ? getEditPath(id) : getBasePath()}`; } diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index 67d9d5ef644834..f5fba766e60eea 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -13,7 +13,7 @@ "dashboard", "charts" ], - "optionalPlugins": ["embeddable", "usageCollection", "taskManager", "uiActions"], + "optionalPlugins": ["embeddable", "usageCollection", "taskManager", "uiActions", "globalSearch"], "configPath": ["xpack", "lens"], "extraPublicDirs": ["common/constants"], "requiredBundles": ["savedObjects", "kibanaUtils", "kibanaReact", "embeddable"] diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 63c2a6b9b2f292..24114e2b315181 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -9,29 +9,36 @@ import { Observable } from 'rxjs'; import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { App } from './app'; +import { LensAppProps, LensAppServices } from './types'; import { EditorFrameInstance } from '../types'; -import { AppMountParameters } from 'kibana/public'; -import { Storage } from '../../../../../src/plugins/kibana_utils/public'; -import { Document, SavedObjectStore } from '../persistence'; +import { Document, DOC_TYPE } from '../persistence'; import { mount } from 'enzyme'; +import { I18nProvider } from '@kbn/i18n/react'; import { SavedObjectSaveModal, checkForDuplicateTitle, } from '../../../../../src/plugins/saved_objects/public'; -import { createMemoryHistory, History } from 'history'; +import { createMemoryHistory } from 'history'; import { + DataPublicPluginStart, esFilters, FilterManager, IFieldType, IIndexPattern, UI_SETTINGS, } from '../../../../../src/plugins/data/public'; -import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; -const dataStartMock = dataPluginMock.createStartContract(); - import { navigationPluginMock } from '../../../../../src/plugins/navigation/public/mocks'; import { TopNavMenuData } from '../../../../../src/plugins/navigation/public'; import { coreMock } from 'src/core/public/mocks'; +import { + LensByValueInput, + LensSavedObjectAttributes, + LensByReferenceInput, +} from '../editor_frame_service/embeddable/embeddable'; +import { SavedObjectReference } from '../../../../../src/core/types'; +import { mockAttributeService } from '../../../../../src/plugins/dashboard/public/mocks'; +import { LensAttributeService } from '../lens_attribute_service'; +import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; jest.mock('../editor_frame_service/editor_frame/expression_helpers'); jest.mock('src/core/public'); @@ -120,39 +127,68 @@ function createMockTimefilter() { } describe('Lens App', () => { - let frame: jest.Mocked; let core: ReturnType; - let instance: ReactWrapper; - - function makeDefaultArgs(): jest.Mocked<{ - editorFrame: EditorFrameInstance; - data: typeof dataStartMock; - navigation: typeof navigationStartMock; - core: typeof core; - storage: Storage; - docId?: string; - docStorage: SavedObjectStore; - redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; - originatingApp: string | undefined; - onAppLeave: AppMountParameters['onAppLeave']; - setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; - history: History; - getAppNameFromId?: (appId: string) => string | undefined; - }> { - return ({ - navigation: navigationStartMock, + let defaultDoc: Document; + let defaultSavedObjectId: string; + + const navMenuItems = { + expectedSaveButton: { emphasize: true, testId: 'lnsApp_saveButton' }, + expectedSaveAsButton: { emphasize: false, testId: 'lnsApp_saveButton' }, + expectedSaveAndReturnButton: { emphasize: true, testId: 'lnsApp_saveAndReturnButton' }, + }; + + function makeAttributeService(): LensAttributeService { + const attributeServiceMock = mockAttributeService< + LensSavedObjectAttributes, + LensByValueInput, + LensByReferenceInput + >( + DOC_TYPE, + { + customSaveMethod: jest.fn(), + customUnwrapMethod: jest.fn(), + }, + core + ); + attributeServiceMock.unwrapAttributes = jest.fn().mockResolvedValue(defaultDoc); + attributeServiceMock.wrapAttributes = jest + .fn() + .mockResolvedValue({ savedObjectId: defaultSavedObjectId }); + return attributeServiceMock; + } + + function makeDefaultProps(): jest.Mocked { + return { editorFrame: createMockFrame(), - core: { - ...core, - application: { - ...core.application, - capabilities: { - ...core.application.capabilities, - visualize: { save: true, saveQuery: true, show: true }, - }, + history: createMemoryHistory(), + redirectTo: jest.fn(), + redirectToOrigin: jest.fn(), + onAppLeave: jest.fn(), + setHeaderActionMenu: jest.fn(), + }; + } + + function makeDefaultServices(): jest.Mocked { + return { + http: core.http, + chrome: core.chrome, + overlays: core.overlays, + uiSettings: core.uiSettings, + navigation: navigationStartMock, + notifications: core.notifications, + attributeService: makeAttributeService(), + savedObjectsClient: core.savedObjects.client, + dashboardFeatureFlag: { allowByValueEmbeddables: false }, + getOriginatingAppName: jest.fn(() => 'defaultOriginatingApp'), + application: { + ...core.application, + capabilities: { + ...core.application.capabilities, + visualize: { save: true, saveQuery: true, show: true }, }, + getUrlForApp: jest.fn((appId: string) => `/testbasepath/app/${appId}#/`), }, - data: { + data: ({ query: { filterManager: createMockFilterManager(), timefilter: { @@ -166,38 +202,52 @@ describe('Lens App', () => { return new Promise((resolve) => resolve({ id })); }), }, - }, + } as unknown) as DataPublicPluginStart, storage: { get: jest.fn(), + set: jest.fn(), + remove: jest.fn(), + clear: jest.fn(), }, - docStorage: { - load: jest.fn(), - save: jest.fn(), - }, - redirectTo: jest.fn((id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => {}), - onAppLeave: jest.fn(), - setHeaderActionMenu: jest.fn(), - history: createMemoryHistory(), - } as unknown) as jest.Mocked<{ - navigation: typeof navigationStartMock; - editorFrame: EditorFrameInstance; - data: typeof dataStartMock; - core: typeof core; - storage: Storage; - docId?: string; - docStorage: SavedObjectStore; - redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; - originatingApp: string | undefined; - onAppLeave: AppMountParameters['onAppLeave']; - setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; - history: History; - getAppNameFromId?: (appId: string) => string | undefined; - }>; + }; + } + + function mountWith({ + props: incomingProps, + services: incomingServices, + }: { + props?: jest.Mocked; + services?: jest.Mocked; + }) { + const props = incomingProps ?? makeDefaultProps(); + const services = incomingServices ?? makeDefaultServices(); + const wrappingComponent: React.FC<{ + children: React.ReactNode; + }> = ({ children }) => { + return ( + + {children} + + ); + }; + const frame = props.editorFrame as ReturnType; + const component = mount(, { wrappingComponent }); + return { component, frame, props, services }; } beforeEach(() => { - frame = createMockFrame(); core = coreMock.createStart({ basePath: '/testbasepath' }); + defaultSavedObjectId = '1234'; + defaultDoc = ({ + savedObjectId: defaultSavedObjectId, + title: 'An extremely cool default document!', + expression: 'definitely a valid expression', + state: { + query: 'kuery', + filters: [{ query: { match_phrase: { src: 'test' } } }], + }, + references: [{ type: 'index-pattern', id: '1', name: 'index-pattern-0' }], + } as unknown) as Document; core.uiSettings.get.mockImplementation( jest.fn((type) => { @@ -215,10 +265,7 @@ describe('Lens App', () => { }); it('renders the editor frame', () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - - mount(); + const { frame } = mountWith({}); expect(frame.mount.mock.calls).toMatchInlineSnapshot(` Array [ @@ -248,23 +295,22 @@ describe('Lens App', () => { }); it('clears app filters on load', () => { - const defaultArgs = makeDefaultArgs(); - mount(); - - expect(defaultArgs.data.query.filterManager.setAppFilters).toHaveBeenCalledWith([]); + const { services } = mountWith({}); + expect(services.data.query.filterManager.setAppFilters).toHaveBeenCalledWith([]); }); it('passes global filters to frame', async () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; + const services = makeDefaultServices(); const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern; const pinnedField = ({ name: 'pinnedField' } as unknown) as IFieldType; const pinnedFilter = esFilters.buildExistsFilter(pinnedField, indexPattern); - args.data.query.filterManager.getFilters = jest.fn().mockImplementation(() => { + services.data.query.filterManager.getFilters = jest.fn().mockImplementation(() => { return [pinnedFilter]; }); - const component = mount(); + const { component, frame } = mountWith({ services }); + component.update(); + expect(frame.mount).toHaveBeenCalledWith( expect.any(Element), expect.objectContaining({ @@ -275,103 +321,81 @@ describe('Lens App', () => { ); }); - it('sets breadcrumbs when the document title changes', async () => { - const defaultArgs = makeDefaultArgs(); - instance = mount(); - - expect(core.chrome.setBreadcrumbs).toHaveBeenCalledWith([ - { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, - { text: 'Create' }, - ]); + it('displays errors from the frame in a toast', () => { + const { component, frame, services } = mountWith({}); + const onError = frame.mount.mock.calls[0][1].onError; + onError({ message: 'error' }); + component.update(); + expect(services.notifications.toasts.addDanger).toHaveBeenCalled(); + }); - (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', + describe('breadcrumbs', () => { + const breadcrumbDocSavedObjectId = defaultSavedObjectId; + const breadcrumbDoc = ({ + savedObjectId: breadcrumbDocSavedObjectId, title: 'Daaaaaaadaumching!', state: { query: 'fake query', filters: [], }, references: [], - }); - await act(async () => { - instance.setProps({ docId: '1234' }); - }); + } as unknown) as Document; - expect(defaultArgs.core.chrome.setBreadcrumbs).toHaveBeenCalledWith([ - { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, - { text: 'Daaaaaaadaumching!' }, - ]); - }); + it('sets breadcrumbs when the document title changes', async () => { + const { component, services } = mountWith({}); - it('adds to the recently viewed list on load', async () => { - const defaultArgs = makeDefaultArgs(); - instance = mount(); + expect(services.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, + { text: 'Create' }, + ]); - (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', - title: 'Daaaaaaadaumching!', - state: { - query: 'fake query', - filters: [], - }, - references: [], - }); - await act(async () => { - instance.setProps({ docId: '1234' }); + services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue(breadcrumbDoc); + await act(async () => { + component.setProps({ initialInput: { savedObjectId: breadcrumbDocSavedObjectId } }); + }); + + expect(services.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, + { text: 'Daaaaaaadaumching!' }, + ]); }); - expect(defaultArgs.core.chrome.recentlyAccessed.add).toHaveBeenCalledWith( - '/app/lens#/edit/1234', - 'Daaaaaaadaumching!', - '1234' - ); - }); - it('sets originatingApp breadcrumb when the document title changes', async () => { - const defaultArgs = makeDefaultArgs(); - defaultArgs.originatingApp = 'ultraCoolDashboard'; - defaultArgs.getAppNameFromId = () => 'The Coolest Container Ever Made'; - instance = mount(); + it('sets originatingApp breadcrumb when the document title changes', async () => { + const props = makeDefaultProps(); + const services = makeDefaultServices(); + props.incomingState = { originatingApp: 'coolContainer' }; + services.getOriginatingAppName = jest.fn(() => 'The Coolest Container Ever Made'); + const { component } = mountWith({ props, services }); + + expect(services.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { text: 'The Coolest Container Ever Made', onClick: expect.anything() }, + { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, + { text: 'Create' }, + ]); - expect(core.chrome.setBreadcrumbs).toHaveBeenCalledWith([ - { text: 'The Coolest Container Ever Made', onClick: expect.anything() }, - { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, - { text: 'Create' }, - ]); + services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue(breadcrumbDoc); + await act(async () => { + component.setProps({ initialInput: { savedObjectId: breadcrumbDocSavedObjectId } }); + }); - (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', - title: 'Daaaaaaadaumching!', - state: { - query: 'fake query', - filters: [], - }, - references: [], - }); - await act(async () => { - instance.setProps({ docId: '1234' }); + expect(services.chrome.setBreadcrumbs).toHaveBeenCalledWith([ + { text: 'The Coolest Container Ever Made', onClick: expect.anything() }, + { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, + { text: 'Daaaaaaadaumching!' }, + ]); }); - - expect(defaultArgs.core.chrome.setBreadcrumbs).toHaveBeenCalledWith([ - { text: 'The Coolest Container Ever Made', onClick: expect.anything() }, - { text: 'Visualize', href: '/testbasepath/app/visualize#/', onClick: expect.anything() }, - { text: 'Daaaaaaadaumching!' }, - ]); }); describe('persistence', () => { - it('does not load a document if there is no document id', () => { - const args = makeDefaultArgs(); - - mount(); - - expect(args.docStorage.load).not.toHaveBeenCalled(); + it('does not load a document if there is no initial input', () => { + const { services } = mountWith({}); + expect(services.attributeService.unwrapAttributes).not.toHaveBeenCalled(); }); - it('loads a document and uses query and filters if there is a document id', async () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - (args.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', + it('loads a document and uses query and filters if initial input is provided', async () => { + const { component, frame, services } = mountWith({}); + services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({ + savedObjectId: defaultSavedObjectId, state: { query: 'fake query', filters: [{ query: { match_phrase: { src: 'test' } } }], @@ -379,15 +403,15 @@ describe('Lens App', () => { references: [{ type: 'index-pattern', id: '1', name: 'index-pattern-0' }], }); - instance = mount(); - await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - expect(args.docStorage.load).toHaveBeenCalledWith('1234'); - expect(args.data.indexPatterns.get).toHaveBeenCalledWith('1'); - expect(args.data.query.filterManager.setAppFilters).toHaveBeenCalledWith([ + expect(services.attributeService.unwrapAttributes).toHaveBeenCalledWith({ + savedObjectId: defaultSavedObjectId, + }); + expect(services.data.indexPatterns.get).toHaveBeenCalledWith('1'); + expect(services.data.query.filterManager.setAppFilters).toHaveBeenCalledWith([ { query: { match_phrase: { src: 'test' } } }, ]); expect(TopNavMenu).toHaveBeenCalledWith( @@ -401,7 +425,7 @@ describe('Lens App', () => { expect.any(Element), expect.objectContaining({ doc: expect.objectContaining({ - id: '1234', + savedObjectId: defaultSavedObjectId, state: expect.objectContaining({ query: 'fake query', filters: [{ query: { match_phrase: { src: 'test' } } }], @@ -412,65 +436,59 @@ describe('Lens App', () => { }); it('does not load documents on sequential renders unless the id changes', async () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - (args.docStorage.load as jest.Mock).mockResolvedValue({ id: '1234' }); + const { services, component } = mountWith({}); - instance = mount(); await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - - expect(args.docStorage.load).toHaveBeenCalledTimes(1); + expect(services.attributeService.unwrapAttributes).toHaveBeenCalledTimes(1); await act(async () => { - instance.setProps({ docId: '9876' }); + component.setProps({ initialInput: { savedObjectId: '5678' } }); }); - expect(args.docStorage.load).toHaveBeenCalledTimes(2); + expect(services.attributeService.unwrapAttributes).toHaveBeenCalledTimes(2); }); it('handles document load errors', async () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - (args.docStorage.load as jest.Mock).mockRejectedValue('failed to load'); - - instance = mount(); + const services = makeDefaultServices(); + services.attributeService.unwrapAttributes = jest.fn().mockRejectedValue('failed to load'); + const { component, props } = mountWith({ services }); await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - expect(args.docStorage.load).toHaveBeenCalledWith('1234'); - expect(args.core.notifications.toasts.addDanger).toHaveBeenCalled(); - expect(args.redirectTo).toHaveBeenCalled(); + expect(services.attributeService.unwrapAttributes).toHaveBeenCalledWith({ + savedObjectId: defaultSavedObjectId, + }); + expect(services.notifications.toasts.addDanger).toHaveBeenCalled(); + expect(props.redirectTo).toHaveBeenCalled(); }); - describe('save button', () => { + it('adds to the recently accessed list on load', async () => { + const { component, services } = mountWith({}); + + await act(async () => { + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); + }); + expect(services.chrome.recentlyAccessed.add).toHaveBeenCalledWith( + '/app/lens#/edit/1234', + 'An extremely cool default document!', + '1234' + ); + }); + + describe('save buttons', () => { interface SaveProps { newCopyOnSave: boolean; returnToOrigin?: boolean; newTitle: string; } - let defaultArgs: ReturnType; - - beforeEach(() => { - defaultArgs = makeDefaultArgs(); - (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', - title: 'My cool doc', - expression: 'valid expression', - state: { - query: 'kuery', - }, - } as jest.ResolvedValue); - }); - function getButton(inst: ReactWrapper): TopNavMenuData { return (inst .find('[data-test-subj="lnsApp_topNav"]') @@ -495,135 +513,195 @@ describe('Lens App', () => { filters: [], }, }, - initialDocId, + initialSavedObjectId, ...saveProps }: SaveProps & { lastKnownDoc?: object; - initialDocId?: string; + initialSavedObjectId?: string; }) { - const args = { - ...defaultArgs, - docId: initialDocId, + const props = { + ...makeDefaultProps(), + initialInput: initialSavedObjectId + ? { savedObjectId: initialSavedObjectId, id: '5678' } + : undefined, }; - args.editorFrame = frame; - (args.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', + + const services = makeDefaultServices(); + services.attributeService.wrapAttributes = jest + .fn() + .mockImplementation(async ({ savedObjectId }) => ({ + savedObjectId: savedObjectId || 'aaa', + })); + services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({ + savedObjectId: initialSavedObjectId ?? 'aaa', references: [], state: { query: 'fake query', filters: [], }, - }); - (args.docStorage.save as jest.Mock).mockImplementation(async ({ id }) => ({ - id: id || 'aaa', - })); + } as jest.ResolvedValue); + let frame: jest.Mocked = {} as jest.Mocked; + let component: ReactWrapper = {} as ReactWrapper; await act(async () => { - instance = mount(); + const { frame: newFrame, component: newComponent } = mountWith({ services, props }); + frame = newFrame; + component = newComponent; }); - if (initialDocId) { - expect(args.docStorage.load).toHaveBeenCalledTimes(1); + if (initialSavedObjectId) { + expect(services.attributeService.unwrapAttributes).toHaveBeenCalledTimes(1); } else { - expect(args.docStorage.load).not.toHaveBeenCalled(); + expect(services.attributeService.unwrapAttributes).not.toHaveBeenCalled(); } const onChange = frame.mount.mock.calls[0][1].onChange; + act(() => onChange({ filterableIndexPatterns: [], - doc: { id: initialDocId, ...lastKnownDoc } as Document, + doc: { savedObjectId: initialSavedObjectId, ...lastKnownDoc } as Document, isSaveable: true, }) ); - - instance.update(); - - expect(getButton(instance).disableButton).toEqual(false); - + component.update(); + expect(getButton(component).disableButton).toEqual(false); await act(async () => { - testSave(instance, { ...saveProps }); + testSave(component, { ...saveProps }); }); - - return { args, instance }; + return { props, services, component, frame }; } it('shows a disabled save button when the user does not have permissions', async () => { - const args = defaultArgs; - args.core.application = { - ...args.core.application, + const services = makeDefaultServices(); + services.application = { + ...services.application, capabilities: { - ...args.core.application.capabilities, + ...services.application.capabilities, visualize: { save: false, saveQuery: false, show: true }, }, }; - args.editorFrame = frame; - - instance = mount(); - - expect(getButton(instance).disableButton).toEqual(true); - + const { component, frame } = mountWith({ services }); + expect(getButton(component).disableButton).toEqual(true); const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], - doc: ({ id: 'will save this' } as unknown) as Document, + doc: ({ savedObjectId: 'will save this' } as unknown) as Document, isSaveable: true, }) ); - instance.update(); - expect(getButton(instance).disableButton).toEqual(true); + component.update(); + expect(getButton(component).disableButton).toEqual(true); }); - it('shows a save button that is enabled when the frame has provided its state', async () => { - const args = defaultArgs; - args.editorFrame = frame; - - instance = mount(); - - expect(getButton(instance).disableButton).toEqual(true); - + it('shows a save button that is enabled when the frame has provided its state and does not show save and return or save as', async () => { + const { component, frame } = mountWith({}); + expect(getButton(component).disableButton).toEqual(true); const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], - doc: ({ id: 'will save this' } as unknown) as Document, + doc: ({ savedObjectId: 'will save this' } as unknown) as Document, isSaveable: true, }) ); - instance.update(); + component.update(); + expect(getButton(component).disableButton).toEqual(false); - expect(getButton(instance).disableButton).toEqual(false); + await act(async () => { + const topNavMenuConfig = component.find(TopNavMenu).prop('config'); + expect(topNavMenuConfig).not.toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveAndReturnButton) + ); + expect(topNavMenuConfig).not.toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveAsButton) + ); + expect(topNavMenuConfig).toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveButton) + ); + }); + }); + + it('Shows Save and Return and Save As buttons in create by value mode', async () => { + const props = makeDefaultProps(); + const services = makeDefaultServices(); + services.dashboardFeatureFlag = { allowByValueEmbeddables: true }; + props.incomingState = { + originatingApp: 'ultraDashboard', + valueInput: { + id: 'whatchaGonnaDoWith', + attributes: { + title: + 'whatcha gonna do with all these references? All these references in your value Input', + references: [] as SavedObjectReference[], + }, + } as LensByValueInput, + }; + + const { component } = mountWith({ props, services }); + + await act(async () => { + const topNavMenuConfig = component.find(TopNavMenu).prop('config'); + expect(topNavMenuConfig).toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveAndReturnButton) + ); + expect(topNavMenuConfig).toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveAsButton) + ); + expect(topNavMenuConfig).not.toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveButton) + ); + }); + }); + + it('Shows Save and Return and Save As buttons in edit by reference mode', async () => { + const props = makeDefaultProps(); + props.initialInput = { savedObjectId: defaultSavedObjectId, id: '5678' }; + props.incomingState = { + originatingApp: 'ultraDashboard', + }; + + const { component } = mountWith({ props }); + + await act(async () => { + const topNavMenuConfig = component.find(TopNavMenu).prop('config'); + expect(topNavMenuConfig).toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveAndReturnButton) + ); + expect(topNavMenuConfig).toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveAsButton) + ); + expect(topNavMenuConfig).not.toContainEqual( + expect.objectContaining(navMenuItems.expectedSaveButton) + ); + }); }); it('saves new docs', async () => { - const { args, instance: inst } = await save({ - initialDocId: undefined, + const { props, services } = await save({ + initialSavedObjectId: undefined, newCopyOnSave: false, newTitle: 'hello there', }); - - expect(args.docStorage.save).toHaveBeenCalledWith( + expect(services.attributeService.wrapAttributes).toHaveBeenCalledWith( expect.objectContaining({ - id: undefined, + savedObjectId: undefined, title: 'hello there', - }) + }), + true, + undefined ); - - expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, true); - - inst.setProps({ docId: 'aaa' }); - - expect(args.docStorage.load).not.toHaveBeenCalled(); + expect(props.redirectTo).toHaveBeenCalledWith('aaa'); }); - it('adds to the recently viewed list on save', async () => { - const { args } = await save({ - initialDocId: undefined, + it('adds to the recently accessed list on save', async () => { + const { services } = await save({ + initialSavedObjectId: undefined, newCopyOnSave: false, newTitle: 'hello there', }); - expect(args.core.chrome.recentlyAccessed.add).toHaveBeenCalledWith( + expect(services.chrome.recentlyAccessed.add).toHaveBeenCalledWith( '/app/lens#/edit/aaa', 'hello there', 'aaa' @@ -631,54 +709,53 @@ describe('Lens App', () => { }); it('saves the latest doc as a copy', async () => { - const { args, instance: inst } = await save({ - initialDocId: '1234', + const { props, services, component } = await save({ + initialSavedObjectId: defaultSavedObjectId, newCopyOnSave: true, newTitle: 'hello there', }); - - expect(args.docStorage.save).toHaveBeenCalledWith( + expect(services.attributeService.wrapAttributes).toHaveBeenCalledWith( expect.objectContaining({ - id: undefined, + savedObjectId: undefined, title: 'hello there', - }) + }), + true, + undefined ); - - expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, true); - - inst.setProps({ docId: 'aaa' }); - - expect(args.docStorage.load).toHaveBeenCalledTimes(1); + expect(props.redirectTo).toHaveBeenCalledWith('aaa'); + await act(async () => { + component.setProps({ initialInput: { savedObjectId: 'aaa' } }); + }); + expect(services.attributeService.wrapAttributes).toHaveBeenCalledTimes(1); }); it('saves existing docs', async () => { - const { args, instance: inst } = await save({ - initialDocId: '1234', + const { props, services, component } = await save({ + initialSavedObjectId: defaultSavedObjectId, newCopyOnSave: false, newTitle: 'hello there', }); - - expect(args.docStorage.save).toHaveBeenCalledWith( + expect(services.attributeService.wrapAttributes).toHaveBeenCalledWith( expect.objectContaining({ - id: '1234', + savedObjectId: defaultSavedObjectId, title: 'hello there', - }) + }), + true, + { id: '5678', savedObjectId: defaultSavedObjectId } ); - - expect(args.redirectTo).not.toHaveBeenCalled(); - - inst.setProps({ docId: '1234' }); - - expect(args.docStorage.load).toHaveBeenCalledTimes(1); + expect(props.redirectTo).not.toHaveBeenCalled(); + await act(async () => { + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); + }); + expect(services.attributeService.unwrapAttributes).toHaveBeenCalledTimes(1); }); it('handles save failure by showing a warning, but still allows another save', async () => { - const args = defaultArgs; - args.editorFrame = frame; - (args.docStorage.save as jest.Mock).mockRejectedValue({ message: 'failed' }); - - instance = mount(); - + const services = makeDefaultServices(); + services.attributeService.wrapAttributes = jest + .fn() + .mockRejectedValue({ message: 'failed' }); + const { component, props, frame } = mountWith({ services }); const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ @@ -687,51 +764,48 @@ describe('Lens App', () => { isSaveable: true, }) ); - - instance.update(); + component.update(); await act(async () => { - testSave(instance, { newCopyOnSave: false, newTitle: 'hello there' }); + testSave(component, { newCopyOnSave: false, newTitle: 'hello there' }); }); - - expect(args.core.notifications.toasts.addDanger).toHaveBeenCalled(); - expect(args.redirectTo).not.toHaveBeenCalled(); - - expect(getButton(instance).disableButton).toEqual(false); + expect(services.notifications.toasts.addDanger).toHaveBeenCalled(); + expect(props.redirectTo).not.toHaveBeenCalled(); + expect(getButton(component).disableButton).toEqual(false); }); it('saves new doc and redirects to originating app', async () => { - const { args } = await save({ - initialDocId: undefined, + const { props, services } = await save({ + initialSavedObjectId: undefined, returnToOrigin: true, newCopyOnSave: false, newTitle: 'hello there', }); - - expect(args.docStorage.save).toHaveBeenCalledWith( + expect(services.attributeService.wrapAttributes).toHaveBeenCalledWith( expect.objectContaining({ - id: undefined, + savedObjectId: undefined, title: 'hello there', - }) + }), + true, + undefined ); - - expect(args.redirectTo).toHaveBeenCalledWith('aaa', true, true); + expect(props.redirectToOrigin).toHaveBeenCalledWith({ + input: { savedObjectId: 'aaa' }, + isCopied: false, + }); }); it('saves app filters and does not save pinned filters', async () => { const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern; const field = ({ name: 'myfield' } as unknown) as IFieldType; const pinnedField = ({ name: 'pinnedField' } as unknown) as IFieldType; - const unpinned = esFilters.buildExistsFilter(field, indexPattern); const pinned = esFilters.buildExistsFilter(pinnedField, indexPattern); - await act(async () => { FilterManager.setFiltersStore([pinned], esFilters.FilterStateStore.GLOBAL_STATE); }); - - const { args } = await save({ - initialDocId: '1234', + const { services } = await save({ + initialSavedObjectId: defaultSavedObjectId, newCopyOnSave: false, newTitle: 'hello there2', lastKnownDoc: { @@ -741,42 +815,42 @@ describe('Lens App', () => { }, }, }); - - expect(args.docStorage.save).toHaveBeenCalledWith({ - id: '1234', - title: 'hello there2', - expression: 'kibana 3', - state: { - filters: [unpinned], + expect(services.attributeService.wrapAttributes).toHaveBeenCalledWith( + { + savedObjectId: defaultSavedObjectId, + title: 'hello there2', + expression: 'kibana 3', + state: { + filters: [unpinned], + }, }, - }); + true, + { id: '5678', savedObjectId: defaultSavedObjectId } + ); }); it('checks for duplicate title before saving', async () => { - const args = defaultArgs; - args.editorFrame = frame; - (args.docStorage.save as jest.Mock).mockReturnValue(Promise.resolve({ id: '123' })); - - instance = mount(); - + const services = makeDefaultServices(); + services.attributeService.wrapAttributes = jest + .fn() + .mockReturnValue(Promise.resolve({ savedObjectId: '123' })); + const { component, frame } = mountWith({ services }); const onChange = frame.mount.mock.calls[0][1].onChange; await act(async () => onChange({ filterableIndexPatterns: [], - doc: ({ id: '123' } as unknown) as Document, + doc: ({ savedObjectId: '123' } as unknown) as Document, isSaveable: true, }) ); - instance.update(); + component.update(); await act(async () => { - getButton(instance).run(instance.getDOMNode()); + getButton(component).run(component.getDOMNode()); }); - instance.update(); - + component.update(); const onTitleDuplicate = jest.fn(); - await act(async () => { - instance.find(SavedObjectSaveModal).prop('onSave')({ + component.find(SavedObjectSaveModal).prop('onSave')({ onTitleDuplicate, isTitleDuplicateConfirmed: false, newCopyOnSave: false, @@ -784,9 +858,8 @@ describe('Lens App', () => { newTitle: 'test', }); }); - expect(checkForDuplicateTitle).toHaveBeenCalledWith( - expect.objectContaining({ id: '123' }), + expect.objectContaining({ savedObjectId: '123' }), false, onTitleDuplicate, expect.anything() @@ -794,11 +867,7 @@ describe('Lens App', () => { }); it('does not show the copy button on first save', async () => { - const args = defaultArgs; - args.editorFrame = frame; - - instance = mount(); - + const { component, frame } = mountWith({}); const onChange = frame.mount.mock.calls[0][1].onChange; await act(async () => onChange({ @@ -807,36 +876,17 @@ describe('Lens App', () => { isSaveable: true, }) ); - instance.update(); - await act(async () => getButton(instance).run(instance.getDOMNode())); - instance.update(); - - expect(instance.find(SavedObjectSaveModal).prop('showCopyOnSave')).toEqual(false); + component.update(); + await act(async () => getButton(component).run(component.getDOMNode())); + component.update(); + expect(component.find(SavedObjectSaveModal).prop('showCopyOnSave')).toEqual(false); }); }); }); describe('query bar state management', () => { - let defaultArgs: ReturnType; - - beforeEach(() => { - defaultArgs = makeDefaultArgs(); - (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', - title: 'My cool doc', - expression: 'valid expression', - state: { - query: 'kuery', - }, - } as jest.ResolvedValue); - }); - it('uses the default time and query language settings', () => { - const args = defaultArgs; - args.editorFrame = frame; - - mount(); - + const { frame } = mountWith({}); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ query: { query: '', language: 'kuery' }, @@ -855,20 +905,14 @@ describe('Lens App', () => { }); it('updates the index patterns when the editor frame is changed', async () => { - const args = defaultArgs; - args.editorFrame = frame; - - instance = mount(); - + const { component, frame } = mountWith({}); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ indexPatterns: [], }), {} ); - const onChange = frame.mount.mock.calls[0][1].onChange; - await act(async () => { onChange({ filterableIndexPatterns: ['1'], @@ -876,18 +920,14 @@ describe('Lens App', () => { isSaveable: true, }); }); - - instance.update(); - + component.update(); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ indexPatterns: [{ id: '1' }], }), {} ); - // Do it again to verify that the dirty checking is done right - await act(async () => { onChange({ filterableIndexPatterns: ['2'], @@ -895,9 +935,7 @@ describe('Lens App', () => { isSaveable: true, }); }); - - instance.update(); - + component.update(); expect(TopNavMenu).toHaveBeenLastCalledWith( expect.objectContaining({ indexPatterns: [{ id: '2' }], @@ -905,21 +943,16 @@ describe('Lens App', () => { {} ); }); - it('updates the editor frame when the user changes query or time in the search bar', () => { - const args = defaultArgs; - args.editorFrame = frame; - - instance = mount(); + it('updates the editor frame when the user changes query or time in the search bar', () => { + const { component, frame } = mountWith({}); act(() => - instance.find(TopNavMenu).prop('onQuerySubmit')!({ + component.find(TopNavMenu).prop('onQuerySubmit')!({ dateRange: { from: 'now-14d', to: 'now-7d' }, query: { query: 'new', language: 'lucene' }, }) ); - - instance.update(); - + component.update(); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ query: { query: 'new', language: 'lucene' }, @@ -938,19 +971,15 @@ describe('Lens App', () => { }); it('updates the filters when the user changes them', () => { - const args = defaultArgs; - args.editorFrame = frame; - - instance = mount(); + const { component, frame, services } = mountWith({}); const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern; const field = ({ name: 'myfield' } as unknown) as IFieldType; - act(() => - args.data.query.filterManager.setFilters([esFilters.buildExistsFilter(field, indexPattern)]) + services.data.query.filterManager.setFilters([ + esFilters.buildExistsFilter(field, indexPattern), + ]) ); - - instance.update(); - + component.update(); expect(frame.mount).toHaveBeenCalledWith( expect.any(Element), expect.objectContaining({ @@ -962,17 +991,15 @@ describe('Lens App', () => { describe('saved query handling', () => { it('does not allow saving when the user is missing the saveQuery permission', () => { - const args = makeDefaultArgs(); - args.core.application = { - ...args.core.application, + const services = makeDefaultServices(); + services.application = { + ...services.application, capabilities: { - ...args.core.application.capabilities, + ...services.application.capabilities, visualize: { save: false, saveQuery: false, show: true }, }, }; - - mount(); - + mountWith({ services }); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ showSaveQuery: false }), {} @@ -980,11 +1007,7 @@ describe('Lens App', () => { }); it('persists the saved query ID when the query is saved', () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - - instance = mount(); - + const { component } = mountWith({}); expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ showSaveQuery: true, @@ -995,9 +1018,8 @@ describe('Lens App', () => { }), {} ); - act(() => { - instance.find(TopNavMenu).prop('onSaved')!({ + component.find(TopNavMenu).prop('onSaved')!({ id: '1', attributes: { title: '', @@ -1006,7 +1028,6 @@ describe('Lens App', () => { }, }); }); - expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ savedQuery: { @@ -1023,13 +1044,9 @@ describe('Lens App', () => { }); it('changes the saved query ID when the query is updated', () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - - instance = mount(); - + const { component } = mountWith({}); act(() => { - instance.find(TopNavMenu).prop('onSaved')!({ + component.find(TopNavMenu).prop('onSaved')!({ id: '1', attributes: { title: '', @@ -1038,9 +1055,8 @@ describe('Lens App', () => { }, }); }); - act(() => { - instance.find(TopNavMenu).prop('onSavedQueryUpdated')!({ + component.find(TopNavMenu).prop('onSavedQueryUpdated')!({ id: '2', attributes: { title: 'new title', @@ -1049,7 +1065,6 @@ describe('Lens App', () => { }, }); }); - expect(TopNavMenu).toHaveBeenCalledWith( expect.objectContaining({ savedQuery: { @@ -1066,32 +1081,23 @@ describe('Lens App', () => { }); it('clears all existing unpinned filters when the active saved query is cleared', () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - - instance = mount(); - + const { component, frame, services } = mountWith({}); act(() => - instance.find(TopNavMenu).prop('onQuerySubmit')!({ + component.find(TopNavMenu).prop('onQuerySubmit')!({ dateRange: { from: 'now-14d', to: 'now-7d' }, query: { query: 'new', language: 'lucene' }, }) ); - const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern; const field = ({ name: 'myfield' } as unknown) as IFieldType; const pinnedField = ({ name: 'pinnedField' } as unknown) as IFieldType; - const unpinned = esFilters.buildExistsFilter(field, indexPattern); const pinned = esFilters.buildExistsFilter(pinnedField, indexPattern); FilterManager.setFiltersStore([pinned], esFilters.FilterStateStore.GLOBAL_STATE); - - act(() => args.data.query.filterManager.setFilters([pinned, unpinned])); - instance.update(); - - act(() => instance.find(TopNavMenu).prop('onClearSavedQuery')!()); - instance.update(); - + act(() => services.data.query.filterManager.setFilters([pinned, unpinned])); + component.update(); + act(() => component.find(TopNavMenu).prop('onClearSavedQuery')!()); + component.update(); expect(frame.mount).toHaveBeenLastCalledWith( expect.any(Element), expect.objectContaining({ @@ -1101,191 +1107,127 @@ describe('Lens App', () => { }); }); - it('displays errors from the frame in a toast', () => { - const args = makeDefaultArgs(); - args.editorFrame = frame; - - instance = mount(); - - const onError = frame.mount.mock.calls[0][1].onError; - onError({ message: 'error' }); - - instance.update(); - - expect(args.core.notifications.toasts.addDanger).toHaveBeenCalled(); - }); - describe('showing a confirm message when leaving', () => { - let defaultArgs: ReturnType; let defaultLeave: jest.Mock; let confirmLeave: jest.Mock; beforeEach(() => { - defaultArgs = makeDefaultArgs(); defaultLeave = jest.fn(); confirmLeave = jest.fn(); - (defaultArgs.docStorage.load as jest.Mock).mockResolvedValue({ - id: '1234', - title: 'My cool doc', - state: { - query: 'kuery', - filters: [], - }, - references: [], - } as jest.ResolvedValue); }); it('should not show a confirm message if there is no expression to save', () => { - instance = mount(); - - const lastCall = - defaultArgs.onAppLeave.mock.calls[defaultArgs.onAppLeave.mock.calls.length - 1][0]; + const { props } = mountWith({}); + const lastCall = props.onAppLeave.mock.calls[props.onAppLeave.mock.calls.length - 1][0]; lastCall({ default: defaultLeave, confirm: confirmLeave }); - expect(defaultLeave).toHaveBeenCalled(); expect(confirmLeave).not.toHaveBeenCalled(); }); it('does not confirm if the user is missing save permissions', () => { - const args = defaultArgs; - args.core.application = { - ...args.core.application, + const services = makeDefaultServices(); + services.application = { + ...services.application, capabilities: { - ...args.core.application.capabilities, + ...services.application.capabilities, visualize: { save: false, saveQuery: false, show: true }, }, }; - args.editorFrame = frame; - - instance = mount(); - + const { component, frame, props } = mountWith({ services }); const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], doc: ({ - id: undefined, - + savedObjectId: undefined, references: [], } as unknown) as Document, isSaveable: true, }) ); - instance.update(); - - const lastCall = - defaultArgs.onAppLeave.mock.calls[defaultArgs.onAppLeave.mock.calls.length - 1][0]; + component.update(); + const lastCall = props.onAppLeave.mock.calls[props.onAppLeave.mock.calls.length - 1][0]; lastCall({ default: defaultLeave, confirm: confirmLeave }); - expect(defaultLeave).toHaveBeenCalled(); expect(confirmLeave).not.toHaveBeenCalled(); }); it('should confirm when leaving with an unsaved doc', () => { - defaultArgs.editorFrame = frame; - instance = mount(); - + const { component, frame, props } = mountWith({}); const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], - doc: ({ id: undefined, state: {} } as unknown) as Document, + doc: ({ savedObjectId: undefined, state: {} } as unknown) as Document, isSaveable: true, }) ); - instance.update(); - - const lastCall = - defaultArgs.onAppLeave.mock.calls[defaultArgs.onAppLeave.mock.calls.length - 1][0]; + component.update(); + const lastCall = props.onAppLeave.mock.calls[props.onAppLeave.mock.calls.length - 1][0]; lastCall({ default: defaultLeave, confirm: confirmLeave }); - expect(confirmLeave).toHaveBeenCalled(); expect(defaultLeave).not.toHaveBeenCalled(); }); it('should confirm when leaving with unsaved changes to an existing doc', async () => { - defaultArgs.editorFrame = frame; - instance = mount(); + const { component, frame, props } = mountWith({}); await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], doc: ({ - id: '1234', - + savedObjectId: defaultSavedObjectId, references: [], } as unknown) as Document, isSaveable: true, }) ); - instance.update(); - - const lastCall = - defaultArgs.onAppLeave.mock.calls[defaultArgs.onAppLeave.mock.calls.length - 1][0]; + component.update(); + const lastCall = props.onAppLeave.mock.calls[props.onAppLeave.mock.calls.length - 1][0]; lastCall({ default: defaultLeave, confirm: confirmLeave }); - expect(confirmLeave).toHaveBeenCalled(); expect(defaultLeave).not.toHaveBeenCalled(); }); it('should not confirm when changes are saved', async () => { - defaultArgs.editorFrame = frame; - instance = mount(); + const { component, frame, props } = mountWith({}); await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], - doc: ({ - id: '1234', - title: 'My cool doc', - references: [], - state: { - query: 'kuery', - filters: [], - }, - } as unknown) as Document, + doc: defaultDoc, isSaveable: true, }) ); - instance.update(); - - const lastCall = - defaultArgs.onAppLeave.mock.calls[defaultArgs.onAppLeave.mock.calls.length - 1][0]; + component.update(); + const lastCall = props.onAppLeave.mock.calls[props.onAppLeave.mock.calls.length - 1][0]; lastCall({ default: defaultLeave, confirm: confirmLeave }); - expect(defaultLeave).toHaveBeenCalled(); expect(confirmLeave).not.toHaveBeenCalled(); }); it('should confirm when the latest doc is invalid', async () => { - defaultArgs.editorFrame = frame; - instance = mount(); + const { component, frame, props } = mountWith({}); await act(async () => { - instance.setProps({ docId: '1234' }); + component.setProps({ initialInput: { savedObjectId: defaultSavedObjectId } }); }); - const onChange = frame.mount.mock.calls[0][1].onChange; act(() => onChange({ filterableIndexPatterns: [], - doc: ({ id: '1234', references: [] } as unknown) as Document, + doc: ({ savedObjectId: defaultSavedObjectId, references: [] } as unknown) as Document, isSaveable: true, }) ); - instance.update(); - - const lastCall = - defaultArgs.onAppLeave.mock.calls[defaultArgs.onAppLeave.mock.calls.length - 1][0]; + component.update(); + const lastCall = props.onAppLeave.mock.calls[props.onAppLeave.mock.calls.length - 1][0]; lastCall({ default: defaultLeave, confirm: confirmLeave }); - expect(confirmLeave).toHaveBeenCalled(); expect(defaultLeave).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index bfdf4ceaaabd32..d2ccbe0cb2fee8 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -6,108 +6,82 @@ import _ from 'lodash'; import React, { useState, useEffect, useCallback } from 'react'; -import { I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; -import { AppMountContext, AppMountParameters, NotificationsStart } from 'kibana/public'; -import { History } from 'history'; +import { NotificationsStart } from 'kibana/public'; import { EuiBreadcrumb } from '@elastic/eui'; -import { - Query, - DataPublicPluginStart, - syncQueryStateWithUrl, -} from '../../../../../src/plugins/data/public'; import { createKbnUrlStateStorage, - IStorageWrapper, withNotifyOnErrors, } from '../../../../../src/plugins/kibana_utils/public'; -import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { - SavedObjectSaveModalOrigin, OnSaveProps, checkForDuplicateTitle, + SavedObjectSaveModalOrigin, } from '../../../../../src/plugins/saved_objects/public'; -import { Document, SavedObjectStore, injectFilterReferences } from '../persistence'; -import { EditorFrameInstance } from '../types'; +import { injectFilterReferences } from '../persistence'; import { NativeRenderer } from '../native_renderer'; import { trackUiEvent } from '../lens_ui_telemetry'; import { esFilters, - Filter, IndexPattern as IndexPatternInstance, IndexPatternsContract, - SavedQuery, + syncQueryStateWithUrl, } from '../../../../../src/plugins/data/public'; -import { getFullPath } from '../../common'; - -interface State { - indicateNoData: boolean; - isLoading: boolean; - isSaveModalVisible: boolean; - indexPatternsForTopNav: IndexPatternInstance[]; - originatingApp?: string; - persistedDoc?: Document; - lastKnownDoc?: Document; - - // Properties needed to interface with TopNav - dateRange: { - fromDate: string; - toDate: string; - }; - query: Query; - filters: Filter[]; - savedQuery?: SavedQuery; - isSaveable: boolean; -} +import { LENS_EMBEDDABLE_TYPE, getFullPath } from '../../common'; +import { LensAppProps, LensAppServices, LensAppState } from './types'; +import { getLensTopNavConfig } from './lens_top_nav'; +import { + LensByReferenceInput, + LensEmbeddableInput, +} from '../editor_frame_service/embeddable/embeddable'; export function App({ - editorFrame, - data, - core, - storage, - docId, - docStorage, - redirectTo, - originatingApp, - navigation, + history, onAppLeave, + redirectTo, + editorFrame, + initialInput, + incomingState, + redirectToOrigin, setHeaderActionMenu, - history, - getAppNameFromId, -}: { - editorFrame: EditorFrameInstance; - data: DataPublicPluginStart; - navigation: NavigationPublicPluginStart; - core: AppMountContext['core']; - storage: IStorageWrapper; - docId?: string; - docStorage: SavedObjectStore; - redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; - originatingApp?: string | undefined; - onAppLeave: AppMountParameters['onAppLeave']; - setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; - history: History; - getAppNameFromId?: (appId: string) => string | undefined; -}) { - const [state, setState] = useState(() => { +}: LensAppProps) { + const { + data, + chrome, + overlays, + navigation, + uiSettings, + application, + notifications, + attributeService, + savedObjectsClient, + getOriginatingAppName, + + // Temporarily required until the 'by value' paradigm is default. + dashboardFeatureFlag, + } = useKibana().services; + + const [state, setState] = useState(() => { const currentRange = data.query.timefilter.timefilter.getTime(); return { - isLoading: !!docId, - isSaveModalVisible: false, - indexPatternsForTopNav: [], query: data.query.queryString.getDefaultQuery(), + filters: data.query.filterManager.getFilters(), + isLoading: Boolean(initialInput), + indexPatternsForTopNav: [], dateRange: { fromDate: currentRange.from, toDate: currentRange.to, }, - originatingApp, - filters: data.query.filterManager.getFilters(), + isLinkedToOriginatingApp: Boolean(incomingState?.originatingApp), + isSaveModalVisible: false, indicateNoData: false, isSaveable: false, }; }); + const { lastKnownDoc } = state; + const showNoDataPopover = useCallback(() => { setState((prevState) => ({ ...prevState, indicateNoData: true })); }, [setState]); @@ -125,9 +99,44 @@ export function App({ state.indexPatternsForTopNav, ]); - const { lastKnownDoc } = state; + const onError = useCallback( + (e: { message: string }) => + notifications.toasts.addDanger({ + title: e.message, + }), + [notifications.toasts] + ); + + const getLastKnownDocWithoutPinnedFilters = useCallback( + function () { + if (!lastKnownDoc) return undefined; + const [pinnedFilters, appFilters] = _.partition( + injectFilterReferences(lastKnownDoc.state?.filters || [], lastKnownDoc.references), + esFilters.isFilterPinned + ); + return pinnedFilters?.length + ? { + ...lastKnownDoc, + state: { + ...lastKnownDoc.state, + filters: appFilters, + }, + } + : lastKnownDoc; + }, + [lastKnownDoc] + ); - const savingPermitted = state.isSaveable && core.application.capabilities.visualize.save; + const getIsByValueMode = useCallback( + () => + Boolean( + // Temporarily required until the 'by value' paradigm is default. + dashboardFeatureFlag.allowByValueEmbeddables && + state.isLinkedToOriginatingApp && + !(initialInput as LensByReferenceInput)?.savedObjectId + ), + [dashboardFeatureFlag.allowByValueEmbeddables, state.isLinkedToOriginatingApp, initialInput] + ); useEffect(() => { // Clear app-specific filters when navigating to Lens. Necessary because Lens @@ -156,8 +165,8 @@ export function App({ const kbnUrlStateStorage = createKbnUrlStateStorage({ history, - useHash: core.uiSettings.get('state:storeInSessionStorage'), - ...withNotifyOnErrors(core.notifications.toasts), + useHash: uiSettings.get('state:storeInSessionStorage'), + ...withNotifyOnErrors(notifications.toasts), }); const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( data.query, @@ -172,38 +181,18 @@ export function App({ }, [ data.query.filterManager, data.query.timefilter.timefilter, - core.notifications.toasts, - core.uiSettings, + notifications.toasts, + uiSettings, data.query, history, ]); - const getLastKnownDocWithoutPinnedFilters = useCallback( - function () { - if (!lastKnownDoc) return undefined; - const [pinnedFilters, appFilters] = _.partition( - injectFilterReferences(lastKnownDoc.state?.filters || [], lastKnownDoc.references), - esFilters.isFilterPinned - ); - return pinnedFilters?.length - ? { - ...lastKnownDoc, - state: { - ...lastKnownDoc.state, - filters: appFilters, - }, - } - : lastKnownDoc; - }, - [lastKnownDoc] - ); - useEffect(() => { onAppLeave((actions) => { // Confirm when the user has made any changes to an existing doc // or when the user has configured something without saving if ( - core.application.capabilities.visualize.save && + application.capabilities.visualize.save && !_.isEqual(state.persistedDoc?.state, getLastKnownDocWithoutPinnedFilters()?.state) && (state.isSaveable || state.persistedDoc) ) { @@ -220,379 +209,430 @@ export function App({ } }); }, [ - lastKnownDoc, onAppLeave, - state.persistedDoc, + lastKnownDoc, state.isSaveable, - core.application.capabilities.visualize.save, + state.persistedDoc, getLastKnownDocWithoutPinnedFilters, + application.capabilities.visualize.save, ]); // Sync Kibana breadcrumbs any time the saved document's title changes useEffect(() => { - core.chrome.setBreadcrumbs([ - ...(originatingApp && getAppNameFromId - ? [ - { - onClick: (e) => { - core.application.navigateToApp(originatingApp); - }, - text: getAppNameFromId(originatingApp), - } as EuiBreadcrumb, - ] - : []), - { - href: core.http.basePath.prepend(`/app/visualize#/`), + const isByValueMode = getIsByValueMode(); + const breadcrumbs: EuiBreadcrumb[] = []; + if (state.isLinkedToOriginatingApp && getOriginatingAppName() && redirectToOrigin) { + breadcrumbs.push({ + onClick: () => { + redirectToOrigin(); + }, + text: getOriginatingAppName(), + }); + } + if (!isByValueMode) { + breadcrumbs.push({ + href: application.getUrlForApp('visualize'), onClick: (e) => { - core.application.navigateToApp('visualize', { path: '/' }); + application.navigateToApp('visualize', { path: '/' }); e.preventDefault(); }, text: i18n.translate('xpack.lens.breadcrumbsTitle', { defaultMessage: 'Visualize', }), - }, - { - text: state.persistedDoc - ? state.persistedDoc.title - : i18n.translate('xpack.lens.breadcrumbsCreate', { defaultMessage: 'Create' }), - }, - ]); + }); + } + let currentDocTitle = i18n.translate('xpack.lens.breadcrumbsCreate', { + defaultMessage: 'Create', + }); + if (state.persistedDoc) { + currentDocTitle = isByValueMode + ? i18n.translate('xpack.lens.breadcrumbsByValue', { defaultMessage: 'Edit visualization' }) + : state.persistedDoc.title; + } + breadcrumbs.push({ text: currentDocTitle }); + chrome.setBreadcrumbs(breadcrumbs); }, [ - core.application, - core.chrome, - core.http.basePath, + dashboardFeatureFlag.allowByValueEmbeddables, + state.isLinkedToOriginatingApp, + getOriginatingAppName, state.persistedDoc, - originatingApp, - redirectTo, - getAppNameFromId, + redirectToOrigin, + getIsByValueMode, + initialInput, + application, + chrome, ]); - useEffect( - () => { - if (docId && (!state.persistedDoc || state.persistedDoc.id !== docId)) { - setState((s) => ({ ...s, isLoading: true })); - docStorage - .load(docId) - .then((doc) => { - core.chrome.recentlyAccessed.add(getFullPath(docId), doc.title, docId); - getAllIndexPatterns( - _.uniq( - doc.references.filter(({ type }) => type === 'index-pattern').map(({ id }) => id) - ), - data.indexPatterns, - core.notifications - ) - .then((indexPatterns) => { - // Don't overwrite any pinned filters - data.query.filterManager.setAppFilters( - injectFilterReferences(doc.state.filters, doc.references) - ); - setState((s) => ({ - ...s, - isLoading: false, - persistedDoc: doc, - lastKnownDoc: doc, - query: doc.state.query, - indexPatternsForTopNav: indexPatterns, - })); - }) - .catch((e) => { - setState((s) => ({ ...s, isLoading: false })); - - redirectTo(); - }); + useEffect(() => { + if ( + !initialInput || + (attributeService.inputIsRefType(initialInput) && + initialInput.savedObjectId === state.persistedDoc?.savedObjectId) + ) { + return; + } + + setState((s) => ({ ...s, isLoading: true })); + attributeService + .unwrapAttributes(initialInput) + .then((attributes) => { + if (!initialInput) { + return; + } + const doc = { + ...initialInput, + ...attributes, + type: LENS_EMBEDDABLE_TYPE, + }; + + if (attributeService.inputIsRefType(initialInput)) { + chrome.recentlyAccessed.add( + getFullPath(initialInput.savedObjectId), + attributes.title, + initialInput.savedObjectId + ); + } + getAllIndexPatterns( + _.uniq(doc.references.filter(({ type }) => type === 'index-pattern').map(({ id }) => id)), + data.indexPatterns, + notifications + ) + .then((indexPatterns) => { + // Don't overwrite any pinned filters + data.query.filterManager.setAppFilters( + injectFilterReferences(doc.state.filters, doc.references) + ); + setState((s) => ({ + ...s, + isLoading: false, + persistedDoc: doc, + lastKnownDoc: doc, + query: doc.state.query, + indexPatternsForTopNav: indexPatterns, + })); }) .catch((e) => { setState((s) => ({ ...s, isLoading: false })); - - core.notifications.toasts.addDanger( - i18n.translate('xpack.lens.app.docLoadingError', { - defaultMessage: 'Error loading saved document', - }) - ); - redirectTo(); }); - } - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [ - core.notifications, - data.indexPatterns, - data.query.filterManager, - docId, - // TODO: These dependencies are changing too often - // docStorage, - // redirectTo, - // state.persistedDoc, - ] - ); + }) + .catch((e) => { + setState((s) => ({ ...s, isLoading: false })); + notifications.toasts.addDanger( + i18n.translate('xpack.lens.app.docLoadingError', { + defaultMessage: 'Error loading saved document', + }) + ); + + redirectTo(); + }); + }, [ + notifications, + data.indexPatterns, + data.query.filterManager, + initialInput, + attributeService, + redirectTo, + chrome.recentlyAccessed, + state.persistedDoc?.savedObjectId, + state.persistedDoc?.state, + ]); const runSave = async ( saveProps: Omit & { returnToOrigin: boolean; onTitleDuplicate?: OnSaveProps['onTitleDuplicate']; newDescription?: string; - } + }, + options: { saveToLibrary: boolean } ) => { if (!lastKnownDoc) { return; } - - const doc = { + const docToSave = { ...getLastKnownDocWithoutPinnedFilters()!, description: saveProps.newDescription, - id: saveProps.newCopyOnSave ? undefined : lastKnownDoc.id, + savedObjectId: saveProps.newCopyOnSave ? undefined : lastKnownDoc.savedObjectId, title: saveProps.newTitle, }; - await checkForDuplicateTitle( - { - ...doc, - copyOnSave: saveProps.newCopyOnSave, - lastSavedTitle: lastKnownDoc?.title, - getEsType: () => 'lens', - getDisplayName: () => - i18n.translate('xpack.lens.app.saveModalType', { - defaultMessage: 'Lens visualization', - }), - }, - saveProps.isTitleDuplicateConfirmed, - saveProps.onTitleDuplicate, - { - savedObjectsClient: core.savedObjects.client, - overlays: core.overlays, + // Required to serialize filters in by value mode until + // https://github.com/elastic/kibana/issues/77588 is fixed + if (getIsByValueMode()) { + docToSave.state.filters.forEach((filter) => { + if (typeof filter.meta.value === 'function') { + delete filter.meta.value; + } + }); + } + + const originalInput = saveProps.newCopyOnSave ? undefined : initialInput; + const originalSavedObjectId = (originalInput as LensByReferenceInput)?.savedObjectId; + if (options.saveToLibrary && !originalInput) { + await checkForDuplicateTitle( + { + ...docToSave, + copyOnSave: saveProps.newCopyOnSave, + lastSavedTitle: lastKnownDoc.title, + getEsType: () => 'lens', + getDisplayName: () => + i18n.translate('xpack.lens.app.saveModalType', { + defaultMessage: 'Lens visualization', + }), + }, + saveProps.isTitleDuplicateConfirmed, + saveProps.onTitleDuplicate, + { + savedObjectsClient, + overlays, + } + ); + } + try { + const newInput = (await attributeService.wrapAttributes( + docToSave, + options.saveToLibrary, + originalInput + )) as LensEmbeddableInput; + + if (saveProps.returnToOrigin && redirectToOrigin) { + // disabling the validation on app leave because the document has been saved. + onAppLeave((actions) => { + return actions.default(); + }); + redirectToOrigin({ input: newInput, isCopied: saveProps.newCopyOnSave }); + return; } - ); - const newlyCreated: boolean = saveProps.newCopyOnSave || !lastKnownDoc?.id; - docStorage - .save(doc) - .then(({ id }) => { - core.chrome.recentlyAccessed.add(getFullPath(id), doc.title, id); - // Prevents unnecessary network request and disables save button - const newDoc = { ...doc, id }; - const currentOriginatingApp = state.originatingApp; + if ( + attributeService.inputIsRefType(newInput) && + newInput.savedObjectId !== originalSavedObjectId + ) { + chrome.recentlyAccessed.add( + getFullPath(newInput.savedObjectId), + docToSave.title, + newInput.savedObjectId + ); setState((s) => ({ ...s, isSaveModalVisible: false, - originatingApp: - newlyCreated && !saveProps.returnToOrigin ? undefined : currentOriginatingApp, - persistedDoc: newDoc, - lastKnownDoc: newDoc, + isLinkedToOriginatingApp: false, })); - if (docId !== id || saveProps.returnToOrigin) { - redirectTo(id, saveProps.returnToOrigin, newlyCreated); - } - }) - .catch((e) => { - // eslint-disable-next-line no-console - console.dir(e); - trackUiEvent('save_failed'); - core.notifications.toasts.addDanger( - i18n.translate('xpack.lens.app.docSavingError', { - defaultMessage: 'Error saving document', - }) - ); - setState((s) => ({ ...s, isSaveModalVisible: false })); - }); - }; + redirectTo(newInput.savedObjectId); + return; + } - const onError = useCallback( - (e: { message: string }) => - core.notifications.toasts.addDanger({ - title: e.message, - }), - [core.notifications.toasts] - ); + const newDoc = { + ...docToSave, + ...newInput, + }; + setState((s) => ({ + ...s, + persistedDoc: newDoc, + lastKnownDoc: newDoc, + isSaveModalVisible: false, + isLinkedToOriginatingApp: false, + })); + } catch (e) { + // eslint-disable-next-line no-console + console.dir(e); + trackUiEvent('save_failed'); + notifications.toasts.addDanger( + i18n.translate('xpack.lens.app.docSavingError', { + defaultMessage: 'Error saving document', + }) + ); + setState((s) => ({ ...s, isSaveModalVisible: false })); + } + }; const { TopNavMenu } = navigation.ui; + const savingPermitted = Boolean(state.isSaveable && application.capabilities.visualize.save); + const topNavConfig = getLensTopNavConfig({ + showSaveAndReturn: Boolean( + state.isLinkedToOriginatingApp && + // Temporarily required until the 'by value' paradigm is default. + (dashboardFeatureFlag.allowByValueEmbeddables || Boolean(initialInput)) + ), + isByValueMode: getIsByValueMode(), + showCancel: Boolean(state.isLinkedToOriginatingApp), + savingPermitted, + actions: { + saveAndReturn: () => { + if (savingPermitted && lastKnownDoc) { + // disabling the validation on app leave because the document has been saved. + onAppLeave((actions) => { + return actions.default(); + }); + runSave( + { + newTitle: lastKnownDoc.title, + newCopyOnSave: false, + isTitleDuplicateConfirmed: false, + returnToOrigin: true, + }, + { + saveToLibrary: + (initialInput && attributeService.inputIsRefType(initialInput)) ?? false, + } + ); + } + }, + showSaveModal: () => { + if (savingPermitted) { + setState((s) => ({ ...s, isSaveModalVisible: true })); + } + }, + cancel: () => { + if (redirectToOrigin) { + redirectToOrigin(); + } + }, + }, + }); + return ( - - -
-
- { - if (savingPermitted) { - runSave({ - newTitle: lastKnownDoc.title, - newCopyOnSave: false, - isTitleDuplicateConfirmed: false, - returnToOrigin: true, - }); - } - }, - testId: 'lnsApp_saveAndReturnButton', - disableButton: !savingPermitted, - }, - ] - : []), - { - label: - lastKnownDoc?.id && !!state.originatingApp - ? i18n.translate('xpack.lens.app.saveAs', { - defaultMessage: 'Save as', - }) - : i18n.translate('xpack.lens.app.save', { - defaultMessage: 'Save', - }), - emphasize: !state.originatingApp || !lastKnownDoc?.id, - run: () => { - if (savingPermitted) { - setState((s) => ({ ...s, isSaveModalVisible: true })); - } - }, - testId: 'lnsApp_saveButton', - disableButton: !savingPermitted, + <> +
+
+ { + const { dateRange, query } = payload; + if ( + dateRange.from !== state.dateRange.fromDate || + dateRange.to !== state.dateRange.toDate + ) { + data.query.timefilter.timefilter.setTime(dateRange); + trackUiEvent('app_date_change'); + } else { + trackUiEvent('app_query_change'); + } + setState((s) => ({ + ...s, + dateRange: { + fromDate: dateRange.from, + toDate: dateRange.to, }, - ]} - data-test-subj="lnsApp_topNav" - screenTitle={'lens'} - onQuerySubmit={(payload) => { - const { dateRange, query } = payload; + query: query || s.query, + })); + }} + onSaved={(savedQuery) => { + setState((s) => ({ ...s, savedQuery })); + }} + onSavedQueryUpdated={(savedQuery) => { + const savedQueryFilters = savedQuery.attributes.filters || []; + const globalFilters = data.query.filterManager.getGlobalFilters(); + data.query.filterManager.setFilters([...globalFilters, ...savedQueryFilters]); + setState((s) => ({ + ...s, + savedQuery: { ...savedQuery }, // Shallow query for reference issues + dateRange: savedQuery.attributes.timefilter + ? { + fromDate: savedQuery.attributes.timefilter.from, + toDate: savedQuery.attributes.timefilter.to, + } + : s.dateRange, + })); + }} + onClearSavedQuery={() => { + data.query.filterManager.setFilters(data.query.filterManager.getGlobalFilters()); + setState((s) => ({ + ...s, + savedQuery: undefined, + filters: data.query.filterManager.getGlobalFilters(), + query: data.query.queryString.getDefaultQuery(), + })); + }} + query={state.query} + dateRangeFrom={state.dateRange.fromDate} + dateRangeTo={state.dateRange.toDate} + indicateNoData={state.indicateNoData} + /> +
+ {(!state.isLoading || state.persistedDoc) && ( + { + if (isSaveable !== state.isSaveable) { + setState((s) => ({ ...s, isSaveable })); + } + if (!_.isEqual(state.persistedDoc, doc)) { + setState((s) => ({ ...s, lastKnownDoc: doc })); + } + // Update the cached index patterns if the user made a change to any of them if ( - dateRange.from !== state.dateRange.fromDate || - dateRange.to !== state.dateRange.toDate + state.indexPatternsForTopNav.length !== filterableIndexPatterns.length || + filterableIndexPatterns.some( + (id) => + !state.indexPatternsForTopNav.find((indexPattern) => indexPattern.id === id) + ) ) { - data.query.timefilter.timefilter.setTime(dateRange); - trackUiEvent('app_date_change'); - } else { - trackUiEvent('app_query_change'); + getAllIndexPatterns( + filterableIndexPatterns, + data.indexPatterns, + notifications + ).then((indexPatterns) => { + if (indexPatterns) { + setState((s) => ({ ...s, indexPatternsForTopNav: indexPatterns })); + } + }); } - - setState((s) => ({ - ...s, - dateRange: { - fromDate: dateRange.from, - toDate: dateRange.to, - }, - query: query || s.query, - })); - }} - appName={'lens'} - indexPatterns={state.indexPatternsForTopNav} - showSearchBar={true} - showDatePicker={true} - showQueryBar={true} - showFilterBar={true} - showSaveQuery={core.application.capabilities.visualize.saveQuery as boolean} - savedQuery={state.savedQuery} - onSaved={(savedQuery) => { - setState((s) => ({ ...s, savedQuery })); - }} - onSavedQueryUpdated={(savedQuery) => { - const savedQueryFilters = savedQuery.attributes.filters || []; - const globalFilters = data.query.filterManager.getGlobalFilters(); - data.query.filterManager.setFilters([...globalFilters, ...savedQueryFilters]); - setState((s) => ({ - ...s, - savedQuery: { ...savedQuery }, // Shallow query for reference issues - dateRange: savedQuery.attributes.timefilter - ? { - fromDate: savedQuery.attributes.timefilter.from, - toDate: savedQuery.attributes.timefilter.to, - } - : s.dateRange, - })); - }} - onClearSavedQuery={() => { - data.query.filterManager.setFilters(data.query.filterManager.getGlobalFilters()); - setState((s) => ({ - ...s, - savedQuery: undefined, - filters: data.query.filterManager.getGlobalFilters(), - query: data.query.queryString.getDefaultQuery(), - })); - }} - query={state.query} - dateRangeFrom={state.dateRange.fromDate} - dateRangeTo={state.dateRange.toDate} - indicateNoData={state.indicateNoData} - /> -
- - {(!state.isLoading || state.persistedDoc) && ( - { - if (isSaveable !== state.isSaveable) { - setState((s) => ({ ...s, isSaveable })); - } - if (!_.isEqual(state.persistedDoc, doc)) { - setState((s) => ({ ...s, lastKnownDoc: doc })); - } - - // Update the cached index patterns if the user made a change to any of them - if ( - state.indexPatternsForTopNav.length !== filterableIndexPatterns.length || - filterableIndexPatterns.some( - (id) => - !state.indexPatternsForTopNav.find((indexPattern) => indexPattern.id === id) - ) - ) { - getAllIndexPatterns( - filterableIndexPatterns, - data.indexPatterns, - core.notifications - ).then((indexPatterns) => { - if (indexPatterns) { - setState((s) => ({ ...s, indexPatternsForTopNav: indexPatterns })); - } - }); - } - }, - }} - /> - )} -
- {lastKnownDoc && state.isSaveModalVisible && ( - runSave(props)} - onClose={() => setState((s) => ({ ...s, isSaveModalVisible: false }))} - getAppNameFromId={getAppNameFromId} - documentInfo={{ - id: lastKnownDoc.id, - title: lastKnownDoc.title || '', - description: lastKnownDoc.description || '', + }, }} - objectType={i18n.translate('xpack.lens.app.saveModalType', { - defaultMessage: 'Lens visualization', - })} - data-test-subj="lnsApp_saveModalOrigin" /> )} - - +
+ {lastKnownDoc && state.isSaveModalVisible && ( + runSave(props, { saveToLibrary: true })} + onClose={() => { + setState((s) => ({ ...s, isSaveModalVisible: false })); + }} + getAppNameFromId={() => getOriginatingAppName()} + documentInfo={{ + id: lastKnownDoc.savedObjectId, + title: lastKnownDoc.title || '', + description: lastKnownDoc.description || '', + }} + returnToOriginSwitchLabel={ + getIsByValueMode() && initialInput + ? i18n.translate('xpack.lens.app.updatePanel', { + defaultMessage: 'Update panel on {originatingAppName}', + values: { originatingAppName: getOriginatingAppName() }, + }) + : undefined + } + objectType={i18n.translate('xpack.lens.app.saveModalType', { + defaultMessage: 'Lens visualization', + })} + data-test-subj="lnsApp_saveModalOrigin" + /> + )} + ); } diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx new file mode 100644 index 00000000000000..f6234d063d8cdf --- /dev/null +++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { TopNavMenuData } from '../../../../../src/plugins/navigation/public'; +import { LensTopNavActions } from './types'; + +export function getLensTopNavConfig(options: { + showSaveAndReturn: boolean; + showCancel: boolean; + isByValueMode: boolean; + actions: LensTopNavActions; + savingPermitted: boolean; +}): TopNavMenuData[] { + const { showSaveAndReturn, showCancel, actions, savingPermitted } = options; + const topNavMenu: TopNavMenuData[] = []; + + const saveButtonLabel = options.isByValueMode + ? i18n.translate('xpack.lens.app.addToLibrary', { + defaultMessage: 'Save to library', + }) + : options.showSaveAndReturn + ? i18n.translate('xpack.lens.app.saveAs', { + defaultMessage: 'Save as', + }) + : i18n.translate('xpack.lens.app.save', { + defaultMessage: 'Save', + }); + + if (showSaveAndReturn) { + topNavMenu.push({ + label: i18n.translate('xpack.lens.app.saveAndReturn', { + defaultMessage: 'Save and return', + }), + emphasize: true, + iconType: 'check', + run: actions.saveAndReturn, + testId: 'lnsApp_saveAndReturnButton', + disableButton: !savingPermitted, + description: i18n.translate('xpack.lens.app.saveAndReturnButtonAriaLabel', { + defaultMessage: 'Save the current lens visualization and return to the last app', + }), + }); + } + + topNavMenu.push({ + label: saveButtonLabel, + emphasize: !showSaveAndReturn, + run: actions.showSaveModal, + testId: 'lnsApp_saveButton', + description: i18n.translate('xpack.lens.app.saveButtonAriaLabel', { + defaultMessage: 'Save the current lens visualization', + }), + disableButton: !savingPermitted, + }); + + if (showCancel) { + topNavMenu.push({ + label: i18n.translate('xpack.lens.app.cancel', { + defaultMessage: 'cancel', + }), + run: actions.cancel, + testId: 'lnsApp_cancelButton', + description: i18n.translate('xpack.lens.app.cancelButtonAriaLabel', { + defaultMessage: 'Return to the last app without saving changes', + }), + }); + } + return topNavMenu; +} diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index ebc38e4929f6c9..0d50e541d3e48e 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -11,6 +11,7 @@ import { HashRouter, Route, RouteComponentProps, Switch } from 'react-router-dom import { render, unmountComponentAtNode } from 'react-dom'; import { i18n } from '@kbn/i18n'; +import { DashboardFeatureFlagConfig } from 'src/plugins/dashboard/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { LensReportManager, setReportManager, trackUiEvent } from '../lens_ui_telemetry'; @@ -18,76 +19,116 @@ import { LensReportManager, setReportManager, trackUiEvent } from '../lens_ui_te import { App } from './app'; import { EditorFrameStart } from '../types'; import { addHelpMenuToAppChrome } from '../help_menu_util'; -import { SavedObjectIndexStore } from '../persistence'; import { LensPluginStartDependencies } from '../plugin'; -import { LENS_EMBEDDABLE_TYPE } from '../../common'; +import { LENS_EMBEDDABLE_TYPE, LENS_EDIT_BY_VALUE } from '../../common'; +import { + LensEmbeddableInput, + LensByReferenceInput, + LensByValueInput, +} from '../editor_frame_service/embeddable/embeddable'; +import { LensAttributeService } from '../lens_attribute_service'; +import { LensAppServices, RedirectToOriginProps } from './types'; +import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; export async function mountApp( core: CoreSetup, params: AppMountParameters, - createEditorFrame: EditorFrameStart['createInstance'] + mountProps: { + createEditorFrame: EditorFrameStart['createInstance']; + getByValueFeatureFlag: () => Promise; + attributeService: LensAttributeService; + } ) { + const { createEditorFrame, getByValueFeatureFlag, attributeService } = mountProps; const [coreStart, startDependencies] = await core.getStartServices(); - const { data: dataStart, navigation, embeddable } = startDependencies; - const savedObjectsClient = coreStart.savedObjects.client; - addHelpMenuToAppChrome(coreStart.chrome, coreStart.docLinks); + const { data, navigation, embeddable } = startDependencies; + + const instance = await createEditorFrame(); + const storage = new Storage(localStorage); + const stateTransfer = embeddable?.getStateTransfer(params.history); + const embeddableEditorIncomingState = stateTransfer?.getIncomingEditorState(); + + const lensServices: LensAppServices = { + data, + storage, + navigation, + attributeService, + http: coreStart.http, + chrome: coreStart.chrome, + overlays: coreStart.overlays, + uiSettings: coreStart.uiSettings, + application: coreStart.application, + notifications: coreStart.notifications, + savedObjectsClient: coreStart.savedObjects.client, + getOriginatingAppName: () => { + return embeddableEditorIncomingState?.originatingApp + ? stateTransfer?.getAppNameFromId(embeddableEditorIncomingState.originatingApp) + : undefined; + }, + // Temporarily required until the 'by value' paradigm is default. + dashboardFeatureFlag: await getByValueFeatureFlag(), + }; + + addHelpMenuToAppChrome(coreStart.chrome, coreStart.docLinks); coreStart.chrome.docTitle.change( i18n.translate('xpack.lens.pageTitle', { defaultMessage: 'Lens' }) ); - const stateTransfer = embeddable?.getStateTransfer(params.history); - const { originatingApp } = - stateTransfer?.getIncomingEditorState({ keysToRemoveAfterFetch: ['originatingApp'] }) || {}; - - const instance = await createEditorFrame(); - setReportManager( new LensReportManager({ - storage: new Storage(localStorage), http: core.http, + storage, }) ); - const redirectTo = ( - routeProps: RouteComponentProps<{ id?: string }>, - id?: string, - returnToOrigin?: boolean, - newlyCreated?: boolean - ) => { - if (!id) { + + const getInitialInput = ( + routeProps: RouteComponentProps<{ id?: string }> + ): LensEmbeddableInput | undefined => { + if (routeProps.match.params.id) { + return { savedObjectId: routeProps.match.params.id } as LensByReferenceInput; + } + if (embeddableEditorIncomingState?.valueInput) { + return embeddableEditorIncomingState?.valueInput as LensByValueInput; + } + }; + + const redirectTo = (routeProps: RouteComponentProps<{ id?: string }>, savedObjectId?: string) => { + if (!savedObjectId) { routeProps.history.push('/'); - } else if (!originatingApp) { - routeProps.history.push(`/edit/${id}`); - } else if (!!originatingApp && id && returnToOrigin) { - routeProps.history.push(`/edit/${id}`); - - if (newlyCreated && stateTransfer) { - stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { - state: { id, type: LENS_EMBEDDABLE_TYPE }, - }); - } else { - coreStart.application.navigateToApp(originatingApp); - } + } else { + routeProps.history.push(`/edit/${savedObjectId}`); } }; + const redirectToOrigin = (props?: RedirectToOriginProps) => { + if (!embeddableEditorIncomingState?.originatingApp) { + throw new Error('redirectToOrigin called without an originating app'); + } + if (stateTransfer && props?.input) { + const { input, isCopied } = props; + stateTransfer.navigateToWithEmbeddablePackage(embeddableEditorIncomingState?.originatingApp, { + state: { + embeddableId: isCopied ? undefined : embeddableEditorIncomingState.embeddableId, + type: LENS_EMBEDDABLE_TYPE, + input, + }, + }); + } else { + coreStart.application.navigateToApp(embeddableEditorIncomingState?.originatingApp); + } + }; + + // const featureFlagConfig = await getByValueFeatureFlag(); const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => { trackUiEvent('loaded'); - return ( - redirectTo(routeProps, id, returnToOrigin, newlyCreated) - } - originatingApp={originatingApp} - getAppNameFromId={stateTransfer.getAppNameFromId} + initialInput={getInitialInput(routeProps)} + redirectTo={(savedObjectId?: string) => redirectTo(routeProps, savedObjectId)} + redirectToOrigin={redirectToOrigin} onAppLeave={params.onAppLeave} setHeaderActionMenu={params.setHeaderActionMenu} history={routeProps.history} @@ -103,13 +144,16 @@ export async function mountApp( params.element.classList.add('lnsAppWrapper'); render( - - - - - - - + + + + + + + + + + , params.element ); diff --git a/x-pack/plugins/lens/public/app_plugin/types.ts b/x-pack/plugins/lens/public/app_plugin/types.ts new file mode 100644 index 00000000000000..fcdd0b20f8d276 --- /dev/null +++ b/x-pack/plugins/lens/public/app_plugin/types.ts @@ -0,0 +1,102 @@ +/* + * 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 { History } from 'history'; +import { + ApplicationStart, + AppMountParameters, + ChromeStart, + HttpStart, + IUiSettingsClient, + NotificationsStart, + OverlayStart, + SavedObjectsStart, +} from '../../../../../src/core/public'; +import { + DataPublicPluginStart, + Filter, + IndexPattern, + Query, + SavedQuery, +} from '../../../../../src/plugins/data/public'; +import { Document } from '../persistence'; +import { LensEmbeddableInput } from '../editor_frame_service/embeddable/embeddable'; +import { NavigationPublicPluginStart } from '../../../../../src/plugins/navigation/public'; +import { LensAttributeService } from '../lens_attribute_service'; +import { IStorageWrapper } from '../../../../../src/plugins/kibana_utils/public'; +import { DashboardFeatureFlagConfig } from '../../../../../src/plugins/dashboard/public'; +import { EmbeddableEditorState } from '../../../../../src/plugins/embeddable/public'; +import { EditorFrameInstance } from '..'; + +export interface LensAppState { + isLoading: boolean; + persistedDoc?: Document; + lastKnownDoc?: Document; + isSaveModalVisible: boolean; + + // Used to show a popover that guides the user towards changing the date range when no data is available. + indicateNoData: boolean; + + // index patterns used to determine which filters are available in the top nav. + indexPatternsForTopNav: IndexPattern[]; + + // Determines whether the lens editor shows the 'save and return' button, and the originating app breadcrumb. + isLinkedToOriginatingApp?: boolean; + + // Properties needed to interface with TopNav + dateRange: { + fromDate: string; + toDate: string; + }; + query: Query; + filters: Filter[]; + savedQuery?: SavedQuery; + isSaveable: boolean; +} + +export interface RedirectToOriginProps { + input?: LensEmbeddableInput; + isCopied?: boolean; +} + +export interface LensAppProps { + history: History; + editorFrame: EditorFrameInstance; + onAppLeave: AppMountParameters['onAppLeave']; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; + redirectTo: (savedObjectId?: string) => void; + redirectToOrigin?: (props?: RedirectToOriginProps) => void; + + // The initial input passed in by the container when editing. Can be either by reference or by value. + initialInput?: LensEmbeddableInput; + + // State passed in by the container which is used to determine the id of the Originating App. + incomingState?: EmbeddableEditorState; +} + +export interface LensAppServices { + http: HttpStart; + chrome: ChromeStart; + overlays: OverlayStart; + storage: IStorageWrapper; + data: DataPublicPluginStart; + uiSettings: IUiSettingsClient; + application: ApplicationStart; + notifications: NotificationsStart; + navigation: NavigationPublicPluginStart; + attributeService: LensAttributeService; + savedObjectsClient: SavedObjectsStart['client']; + getOriginatingAppName: () => string | undefined; + + // Temporarily required until the 'by value' paradigm is default. + dashboardFeatureFlag: DashboardFeatureFlagConfig; +} + +export interface LensTopNavActions { + saveAndReturn: () => void; + showSaveModal: () => void; + cancel: () => void; +} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts index 6da6d5a8c118fe..4cb523f128a8ce 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts @@ -59,7 +59,7 @@ export function getSavedObjectFormat({ return { doc: { - id: state.persistedId, + savedObjectId: state.persistedId, title: state.title, description: state.description, type: 'lens', diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts index c7f505aeca517b..80d007e17f711c 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts @@ -376,7 +376,7 @@ describe('editor_frame state management', () => { { type: 'VISUALIZATION_LOADED', doc: { - id: 'b', + savedObjectId: 'b', state: { datasourceStates: { a: { foo: 'c' } }, visualization: { bar: 'd' }, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts index 09674ebf2ade2c..fc8daaed059ddf 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts @@ -156,7 +156,7 @@ export const reducer = (state: EditorFrameState, action: Action): EditorFrameSta case 'VISUALIZATION_LOADED': return { ...state, - persistedId: action.doc.id, + persistedId: action.doc.savedObjectId, title: action.doc.title, description: action.doc.description, datasourceStates: Object.entries(action.doc.state.datasourceStates).reduce( diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx index 1e2df28cad7b1a..d48f9ed713caff 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx @@ -5,12 +5,29 @@ */ import { Subject } from 'rxjs'; -import { Embeddable } from './embeddable'; +import { + Embeddable, + LensByValueInput, + LensByReferenceInput, + LensSavedObjectAttributes, + LensEmbeddableInput, +} from './embeddable'; import { ReactExpressionRendererProps } from 'src/plugins/expressions/public'; -import { Query, TimeRange, Filter, TimefilterContract } from 'src/plugins/data/public'; +import { + Query, + TimeRange, + Filter, + TimefilterContract, + IndexPatternsContract, +} from 'src/plugins/data/public'; import { Document } from '../../persistence'; import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; import { VIS_EVENT_TO_TRIGGER } from '../../../../../../src/plugins/visualizations/public/embeddable'; +import { coreMock, httpServiceMock } from '../../../../../../src/core/public/mocks'; +import { IBasePath } from '../../../../../../src/core/public'; +import { AttributeService } from '../../../../../../src/plugins/dashboard/public'; +import { Ast } from '@kbn/interpreter/common'; +import { LensAttributeService } from '../../lens_attribute_service'; jest.mock('../../../../../../src/plugins/inspector/public/', () => ({ isAvailable: false, @@ -29,61 +46,95 @@ const savedVis: Document = { visualizationType: '', }; +const attributeServiceMockFromSavedVis = (document: Document): LensAttributeService => { + const core = coreMock.createStart(); + const service = new AttributeService< + LensSavedObjectAttributes, + LensByValueInput, + LensByReferenceInput + >( + 'lens', + jest.fn(), + core.savedObjects.client, + core.overlays, + core.i18n.Context, + core.notifications.toasts + ); + service.unwrapAttributes = jest.fn((input: LensByValueInput | LensByReferenceInput) => { + return Promise.resolve({ ...document } as LensSavedObjectAttributes); + }); + service.wrapAttributes = jest.fn(); + return service; +}; + describe('embeddable', () => { let mountpoint: HTMLDivElement; let expressionRenderer: jest.Mock; let getTrigger: jest.Mock; let trigger: { exec: jest.Mock }; + let basePath: IBasePath; + let attributeService: AttributeService< + LensSavedObjectAttributes, + LensByValueInput, + LensByReferenceInput + >; beforeEach(() => { mountpoint = document.createElement('div'); expressionRenderer = jest.fn((_props) => null); trigger = { exec: jest.fn() }; getTrigger = jest.fn(() => trigger); + attributeService = attributeServiceMockFromSavedVis(savedVis); + const http = httpServiceMock.createSetupContract({ basePath: '/test' }); + basePath = http.basePath; }); afterEach(() => { mountpoint.remove(); }); - it('should render expression with expression renderer', () => { + it('should render expression with expression renderer', async () => { const embeddable = new Embeddable( - dataPluginMock.createSetupContract().query.timefilter.timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123' } + {} as LensEmbeddableInput ); + await embeddable.initializeSavedVis({} as LensEmbeddableInput); embeddable.render(mountpoint); expect(expressionRenderer).toHaveBeenCalledTimes(1); expect(expressionRenderer.mock.calls[0][0]!.expression).toEqual('my | expression'); }); - it('should re-render if new input is pushed', () => { + it('should re-render if new input is pushed', async () => { const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; const query: Query = { language: 'kquery', query: '' }; const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }]; const embeddable = new Embeddable( - dataPluginMock.createSetupContract().query.timefilter.timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123' } + { id: '123' } as LensEmbeddableInput ); + await embeddable.initializeSavedVis({ id: '123' } as LensEmbeddableInput); embeddable.render(mountpoint); embeddable.updateInput({ @@ -95,61 +146,74 @@ describe('embeddable', () => { expect(expressionRenderer).toHaveBeenCalledTimes(2); }); - it('should pass context to embeddable', () => { + it('should pass context to embeddable', async () => { const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; const query: Query = { language: 'kquery', query: '' }; const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }]; + const input = { savedObjectId: '123', timeRange, query, filters } as LensEmbeddableInput; + const embeddable = new Embeddable( - dataPluginMock.createSetupContract().query.timefilter.timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123', timeRange, query, filters } + input ); + await embeddable.initializeSavedVis(input); embeddable.render(mountpoint); - expect(expressionRenderer.mock.calls[0][0].searchContext).toEqual({ - timeRange, - query: [query, savedVis.state.query], - filters, - }); + expect(expressionRenderer.mock.calls[0][0].searchContext).toEqual( + expect.objectContaining({ + timeRange, + query: [query, savedVis.state.query], + filters, + }) + ); }); - it('should merge external context with query and filters of the saved object', () => { + it('should merge external context with query and filters of the saved object', async () => { const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; const query: Query = { language: 'kquery', query: 'external filter' }; const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }]; + const newSavedVis = { + ...savedVis, + state: { + ...savedVis.state, + query: { language: 'kquery', query: 'saved filter' }, + filters: [ + { meta: { alias: 'test', negate: false, disabled: false, indexRefName: 'filter-0' } }, + ], + }, + references: [{ type: 'index-pattern', name: 'filter-0', id: 'my-index-pattern-id' }], + }; + attributeService = attributeServiceMockFromSavedVis(newSavedVis); + + const input = { savedObjectId: '123', timeRange, query, filters } as LensEmbeddableInput; + const embeddable = new Embeddable( - dataPluginMock.createSetupContract().query.timefilter.timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis: { - ...savedVis, - state: { - ...savedVis.state, - query: { language: 'kquery', query: 'saved filter' }, - filters: [ - { meta: { alias: 'test', negate: false, disabled: false, indexRefName: 'filter-0' } }, - ], - }, - references: [{ type: 'index-pattern', name: 'filter-0', id: 'my-index-pattern-id' }], - }, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123', timeRange, query, filters } + input ); + await embeddable.initializeSavedVis(input); embeddable.render(mountpoint); expect(expressionRenderer.mock.calls[0][0].searchContext).toEqual({ @@ -163,20 +227,22 @@ describe('embeddable', () => { }); }); - it('should execute trigger on event from expression renderer', () => { + it('should execute trigger on event from expression renderer', async () => { const embeddable = new Embeddable( - dataPluginMock.createSetupContract().query.timefilter.timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123' } + { id: '123' } as LensEmbeddableInput ); + await embeddable.initializeSavedVis({ id: '123' } as LensEmbeddableInput); embeddable.render(mountpoint); const onEvent = expressionRenderer.mock.calls[0][0].onEvent!; @@ -190,24 +256,31 @@ describe('embeddable', () => { ); }); - it('should not re-render if only change is in disabled filter', () => { + it('should not re-render if only change is in disabled filter', async () => { const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; const query: Query = { language: 'kquery', query: '' }; const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: true } }]; const embeddable = new Embeddable( - dataPluginMock.createSetupContract().query.timefilter.timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123', timeRange, query, filters } + { id: '123', timeRange, query, filters } as LensEmbeddableInput ); + await embeddable.initializeSavedVis({ + id: '123', + timeRange, + query, + filters, + } as LensEmbeddableInput); embeddable.render(mountpoint); embeddable.updateInput({ @@ -219,7 +292,7 @@ describe('embeddable', () => { expect(expressionRenderer).toHaveBeenCalledTimes(1); }); - it('should re-render on auto refresh fetch observable', () => { + it('should re-render on auto refresh fetch observable', async () => { const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; const query: Query = { language: 'kquery', query: '' }; const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: true } }]; @@ -230,18 +303,25 @@ describe('embeddable', () => { } as unknown) as TimefilterContract; const embeddable = new Embeddable( - timefilter, - expressionRenderer, - getTrigger, { - editPath: '', - editUrl: '', + timefilter, + attributeService, + expressionRenderer, + basePath, + indexPatternService: {} as IndexPatternsContract, editable: true, - savedVis, - expression: 'my | expression', + getTrigger, + documentToExpression: () => Promise.resolve({} as Ast), + toExpressionString: () => 'my | expression', }, - { id: '123', timeRange, query, filters } + { id: '123', timeRange, query, filters } as LensEmbeddableInput ); + await embeddable.initializeSavedVis({ + id: '123', + timeRange, + query, + filters, + } as LensEmbeddableInput); embeddable.render(mountpoint); autoRefreshFetchSubject.next(); diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx index 4df218a3e94e96..61a5d8cacdc4f3 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx @@ -13,10 +13,12 @@ import { Query, TimefilterContract, TimeRange, + IndexPattern, } from 'src/plugins/data/public'; import { ExecutionContextSearch } from 'src/plugins/expressions'; import { Subscription } from 'rxjs'; +import { Ast } from '@kbn/interpreter/common'; import { ExpressionRendererEvent, ReactExpressionRendererType, @@ -28,41 +30,56 @@ import { EmbeddableInput, EmbeddableOutput, IContainer, + SavedObjectEmbeddableInput, + ReferenceOrValueEmbeddable, } from '../../../../../../src/plugins/embeddable/public'; import { DOC_TYPE, Document, injectFilterReferences } from '../../persistence'; import { ExpressionWrapper } from './expression_wrapper'; import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; import { isLensBrushEvent, isLensFilterEvent } from '../../types'; -export interface LensEmbeddableConfiguration { - expression: string | null; - savedVis: Document; - editUrl: string; - editPath: string; - editable: boolean; - indexPatterns?: IIndexPattern[]; -} +import { IndexPatternsContract } from '../../../../../../src/plugins/data/public'; +import { getEditPath } from '../../../common'; +import { IBasePath } from '../../../../../../src/core/public'; +import { LensAttributeService } from '../../lens_attribute_service'; -export interface LensEmbeddableInput extends EmbeddableInput { - timeRange?: TimeRange; - query?: Query; - filters?: Filter[]; -} +export type LensSavedObjectAttributes = Omit; + +export type LensByValueInput = { + attributes: LensSavedObjectAttributes; +} & EmbeddableInput; + +export type LensByReferenceInput = SavedObjectEmbeddableInput & EmbeddableInput; +export type LensEmbeddableInput = LensByValueInput | LensByReferenceInput; export interface LensEmbeddableOutput extends EmbeddableOutput { indexPatterns?: IIndexPattern[]; } -export class Embeddable extends AbstractEmbeddable { +export interface LensEmbeddableDeps { + attributeService: LensAttributeService; + documentToExpression: (doc: Document) => Promise; + toExpressionString: (astObj: Ast, type?: string) => string; + editable: boolean; + indexPatternService: IndexPatternsContract; + expressionRenderer: ReactExpressionRendererType; + timefilter: TimefilterContract; + basePath: IBasePath; + getTrigger?: UiActionsStart['getTrigger'] | undefined; +} + +export class Embeddable + extends AbstractEmbeddable + implements ReferenceOrValueEmbeddable { type = DOC_TYPE; private expressionRenderer: ReactExpressionRendererType; - private getTrigger: UiActionsStart['getTrigger'] | undefined; - private expression: string | null; - private savedVis: Document; + private savedVis: Document | undefined; + private expression: string | undefined | null; private domNode: HTMLElement | Element | undefined; private subscription: Subscription; private autoRefreshFetchSubscription: Subscription; + private isInitialized = false; private externalSearchContext: { timeRange?: TimeRange; @@ -72,50 +89,32 @@ export class Embeddable extends AbstractEmbeddable this.onContainerStateChanged(initialInput)); this.subscription = this.getInput$().subscribe((input) => this.onContainerStateChanged(input)); - this.onContainerStateChanged(initialInput); - this.autoRefreshFetchSubscription = timefilter + this.autoRefreshFetchSubscription = deps.timefilter .getAutoRefreshFetch$() .subscribe(this.reload.bind(this)); } public supportedTriggers() { + if (!this.savedVis) { + return []; + } switch (this.savedVis.visualizationType) { case 'lnsXY': return [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush]; @@ -128,6 +127,22 @@ export class Embeddable extends AbstractEmbeddable !filter.meta.disabled) @@ -144,9 +159,7 @@ export class Embeddable extends AbstractEmbeddable, @@ -173,6 +189,9 @@ export class Embeddable extends AbstractEmbeddable { - if (!this.getTrigger || this.input.disableTriggers) { + if (!this.deps.getTrigger || this.input.disableTriggers) { return; } if (isLensBrushEvent(event)) { - this.getTrigger(VIS_EVENT_TO_TRIGGER[event.name]).exec({ + this.deps.getTrigger(VIS_EVENT_TO_TRIGGER[event.name]).exec({ data: event.data, embeddable: this, }); } if (isLensFilterEvent(event)) { - this.getTrigger(VIS_EVENT_TO_TRIGGER[event.name]).exec({ + this.deps.getTrigger(VIS_EVENT_TO_TRIGGER[event.name]).exec({ data: event.data, embeddable: this, }); } }; - destroy() { - super.destroy(); - if (this.domNode) { - unmountComponentAtNode(this.domNode); - } - if (this.subscription) { - this.subscription.unsubscribe(); - } - this.autoRefreshFetchSubscription.unsubscribe(); - } - - reload() { + async reload() { const currentTime = Date.now(); if (this.externalSearchContext.lastReloadRequestTime !== currentTime) { this.externalSearchContext = { @@ -233,4 +241,68 @@ export class Embeddable extends AbstractEmbeddable type === 'index-pattern') + .map(async ({ id }) => { + try { + return await this.deps.indexPatternService.get(id); + } catch (error) { + // Unable to load index pattern, ignore error as the index patterns are only used to + // configure the filter and query bar - there is still a good chance to get the visualization + // to show. + return null; + } + }) + .filter((promise): promise is Promise => Boolean(promise)); + const indexPatterns = await Promise.all(promises); + // passing edit url and index patterns to the output of this embeddable for + // the container to pick them up and use them to configure filter bar and + // config dropdown correctly. + const input = this.getInput(); + const title = input.hidePanelTitles ? '' : input.title || this.savedVis.title; + const savedObjectId = (input as LensByReferenceInput).savedObjectId; + this.updateOutput({ + ...this.getOutput(), + defaultTitle: this.savedVis.title, + title, + editPath: getEditPath(savedObjectId), + editUrl: this.deps.basePath.prepend(`/app/lens${getEditPath(savedObjectId)}`), + indexPatterns, + }); + } + + public inputIsRefType = ( + input: LensByValueInput | LensByReferenceInput + ): input is LensByReferenceInput => { + return this.deps.attributeService.inputIsRefType(input); + }; + + public getInputAsRefType = async (): Promise => { + const input = this.deps.attributeService.getExplicitInputFromEmbeddable(this); + return this.deps.attributeService.getInputAsRefType(input, { + showSaveModal: true, + saveModalTitle: this.getTitle(), + }); + }; + + public getInputAsValueType = async (): Promise => { + const input = this.deps.attributeService.getExplicitInputFromEmbeddable(this); + return this.deps.attributeService.getInputAsValueType(input); + }; + + destroy() { + super.destroy(); + if (this.domNode) { + unmountComponentAtNode(this.domNode); + } + if (this.subscription) { + this.subscription.unsubscribe(); + } + this.autoRefreshFetchSubscription.unsubscribe(); + } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts index b8f9f8de1d2868..8771d1ebaddb1b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts @@ -4,33 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Capabilities, HttpSetup, SavedObjectsClientContract } from 'kibana/public'; +import { Capabilities, HttpSetup } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { RecursiveReadonly } from '@kbn/utility-types'; import { toExpression, Ast } from '@kbn/interpreter/target/common'; import { IndexPatternsContract, - IndexPattern, TimefilterContract, } from '../../../../../../src/plugins/data/public'; import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; import { EmbeddableFactoryDefinition, - ErrorEmbeddable, - EmbeddableInput, IContainer, } from '../../../../../../src/plugins/embeddable/public'; -import { Embeddable } from './embeddable'; -import { SavedObjectIndexStore, DOC_TYPE } from '../../persistence'; -import { getEditPath } from '../../../common'; +import { Embeddable, LensByReferenceInput, LensEmbeddableInput } from './embeddable'; +import { DOC_TYPE } from '../../persistence'; import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; import { Document } from '../../persistence/saved_object_store'; +import { LensAttributeService } from '../../lens_attribute_service'; -interface StartServices { +export interface LensEmbeddableStartServices { timefilter: TimefilterContract; coreHttp: HttpSetup; + attributeService: LensAttributeService; capabilities: RecursiveReadonly; - savedObjectsClient: SavedObjectsClientContract; expressionRenderer: ReactExpressionRendererType; indexPatternService: IndexPatternsContract; uiActions?: UiActionsStart; @@ -47,7 +44,7 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition { getIconForSavedObject: () => 'lensApp', }; - constructor(private getStartServices: () => Promise) {} + constructor(private getStartServices: () => Promise) {} public isEditable = async () => { const { capabilities } = await this.getStartServices(); @@ -66,59 +63,40 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition { createFromSavedObject = async ( savedObjectId: string, - input: Partial & { id: string }, + input: LensEmbeddableInput, parent?: IContainer ) => { + if (!(input as LensByReferenceInput).savedObjectId) { + (input as LensByReferenceInput).savedObjectId = savedObjectId; + } + return this.create(input, parent); + }; + + async create(input: LensEmbeddableInput, parent?: IContainer) { const { - savedObjectsClient, - coreHttp, - indexPatternService, timefilter, expressionRenderer, documentToExpression, uiActions, + coreHttp, + attributeService, + indexPatternService, } = await this.getStartServices(); - const store = new SavedObjectIndexStore(savedObjectsClient); - const savedVis = await store.load(savedObjectId); - - const promises = savedVis.references - .filter(({ type }) => type === 'index-pattern') - .map(async ({ id }) => { - try { - return await indexPatternService.get(id); - } catch (error) { - // Unable to load index pattern, ignore error as the index patterns are only used to - // configure the filter and query bar - there is still a good chance to get the visualization - // to show. - return null; - } - }); - const indexPatterns = ( - await Promise.all(promises) - ).filter((indexPattern: IndexPattern | null): indexPattern is IndexPattern => - Boolean(indexPattern) - ); - - const expression = await documentToExpression(savedVis); return new Embeddable( - timefilter, - expressionRenderer, - uiActions?.getTrigger, { - savedVis, - editPath: getEditPath(savedObjectId), - editUrl: coreHttp.basePath.prepend(`/app/lens${getEditPath(savedObjectId)}`), + attributeService, + indexPatternService, + timefilter, + expressionRenderer, editable: await this.isEditable(), - indexPatterns, - expression: expression ? toExpression(expression) : null, + basePath: coreHttp.basePath, + getTrigger: uiActions?.getTrigger, + documentToExpression, + toExpressionString: toExpression, }, input, parent ); - }; - - async create(input: EmbeddableInput) { - return new ErrorEmbeddable('Lens can only be created from a saved object', input); } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/service.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/service.test.tsx index 7b1d091c1c8fe9..c1b6d74bb49c00 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/service.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/service.test.tsx @@ -41,7 +41,8 @@ describe('editor_frame service', () => { (async () => { pluginInstance.setup( coreMock.createSetup() as CoreSetup, - pluginSetupDependencies + pluginSetupDependencies, + jest.fn() ); const publicAPI = pluginInstance.start(coreMock.createStart(), pluginStartDependencies); const instance = await publicAPI.createInstance(); @@ -61,7 +62,8 @@ describe('editor_frame service', () => { it('should not have child nodes after unmount', async () => { pluginInstance.setup( coreMock.createSetup() as CoreSetup, - pluginSetupDependencies + pluginSetupDependencies, + jest.fn() ); const publicAPI = pluginInstance.start(coreMock.createStart(), pluginStartDependencies); const instance = await publicAPI.createInstance(); diff --git a/x-pack/plugins/lens/public/editor_frame_service/service.tsx b/x-pack/plugins/lens/public/editor_frame_service/service.tsx index 5fc347179a032b..bebc3e69899026 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/service.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/service.tsx @@ -25,10 +25,12 @@ import { Document } from '../persistence/saved_object_store'; import { EditorFrame } from './editor_frame'; import { mergeTables } from './merge_tables'; import { formatColumn } from './format_column'; -import { EmbeddableFactory } from './embeddable/embeddable_factory'; +import { EmbeddableFactory, LensEmbeddableStartServices } from './embeddable/embeddable_factory'; import { getActiveDatasourceIdFromDoc } from './editor_frame/state_management'; import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { DashboardStart } from '../../../../../src/plugins/dashboard/public'; import { persistedStateToExpression } from './editor_frame/state_helpers'; +import { LensAttributeService } from '../lens_attribute_service'; export interface EditorFrameSetupPlugins { data: DataPublicPluginSetup; @@ -39,6 +41,7 @@ export interface EditorFrameSetupPlugins { export interface EditorFrameStartPlugins { data: DataPublicPluginStart; embeddable?: EmbeddableStart; + dashboard?: DashboardStart; expressions: ExpressionsStart; uiActions?: UiActionsStart; } @@ -78,16 +81,17 @@ export class EditorFrameService { public setup( core: CoreSetup, - plugins: EditorFrameSetupPlugins + plugins: EditorFrameSetupPlugins, + getAttributeService: () => LensAttributeService ): EditorFrameSetup { plugins.expressions.registerFunction(() => mergeTables); plugins.expressions.registerFunction(() => formatColumn); - const getStartServices = async () => { + const getStartServices = async (): Promise => { const [coreStart, deps] = await core.getStartServices(); return { + attributeService: getAttributeService(), capabilities: coreStart.application.capabilities, - savedObjectsClient: coreStart.savedObjects.client, coreHttp: coreStart.http, timefilter: deps.data.query.timefilter.timefilter, expressionRenderer: deps.expressions.ReactExpressionRenderer, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss index 70fb57ee79ee55..155b954e9cf170 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss @@ -10,27 +10,6 @@ margin-bottom: $euiSizeS; } -/** - * 1. Don't cut off the shadow of the field items - */ - -.lnsInnerIndexPatternDataPanel__listWrapper { - @include euiOverflowShadow; - @include euiScrollBar; - margin-left: -$euiSize; /* 1 */ - position: relative; - flex-grow: 1; - overflow: auto; -} - -.lnsInnerIndexPatternDataPanel__list { - padding-top: $euiSizeS; - position: absolute; - top: 0; - left: $euiSize; /* 1 */ - right: $euiSizeXS; /* 1 */ -} - .lnsInnerIndexPatternDataPanel__fieldItems { // Quick fix for making sure the shadow and focus rings are visible outside the accordion bounds padding: $euiSizeXS $euiSizeXS 0; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx index f17bf172b0fb18..7fb64d1613d324 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx @@ -623,11 +623,40 @@ describe('IndexPattern Data Panel', () => { ).toEqual(['client', 'source', 'timestampLabel']); }); + it('should show meta fields accordion', async () => { + const wrapper = mountWithIntl( + + ); + wrapper + .find('[data-test-subj="lnsIndexPatternMetaFields"]') + .find('button') + .first() + .simulate('click'); + expect( + wrapper + .find('[data-test-subj="lnsIndexPatternMetaFields"]') + .find(FieldItem) + .first() + .prop('field').name + ).toEqual('_id'); + }); + it('should display NoFieldsCallout when all fields are empty', async () => { const wrapper = mountWithIntl( ); - expect(wrapper.find(NoFieldsCallout).length).toEqual(1); + expect(wrapper.find(NoFieldsCallout).length).toEqual(2); expect( wrapper .find('[data-test-subj="lnsIndexPatternAvailableFields"]') @@ -654,7 +683,7 @@ describe('IndexPattern Data Panel', () => { .length ).toEqual(1); wrapper.setProps({ existingFields: { idx1: {} } }); - expect(wrapper.find(NoFieldsCallout).length).toEqual(1); + expect(wrapper.find(NoFieldsCallout).length).toEqual(2); }); it('should filter down by name', () => { @@ -699,7 +728,7 @@ describe('IndexPattern Data Panel', () => { expect(wrapper.find(FieldItem).map((fieldItem) => fieldItem.prop('field').name)).toEqual([ 'Records', ]); - expect(wrapper.find(NoFieldsCallout).length).toEqual(2); + expect(wrapper.find(NoFieldsCallout).length).toEqual(3); }); it('should toggle type if clicked again', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index f7adf91e307da4..4e85cb5b5d46c3 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -5,14 +5,13 @@ */ import './datapanel.scss'; -import { uniq, keyBy, groupBy, throttle } from 'lodash'; -import React, { useState, useEffect, memo, useCallback, useMemo } from 'react'; +import { uniq, keyBy, groupBy } from 'lodash'; +import React, { useState, memo, useCallback, useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiContextMenuPanel, EuiContextMenuItem, - EuiContextMenuPanelProps, EuiPopover, EuiCallOut, EuiFormControlLayout, @@ -25,8 +24,6 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { DataPublicPluginStart, EsQueryConfig, Query, Filter } from 'src/plugins/data/public'; import { DatasourceDataPanelProps, DataType, StateSetter } from '../types'; import { ChildDragDropProvider, DragContextState } from '../drag_drop'; -import { FieldItem } from './field_item'; -import { NoFieldsCallout } from './no_fields_callout'; import { IndexPattern, IndexPatternPrivateState, @@ -37,7 +34,6 @@ import { trackUiEvent } from '../lens_ui_telemetry'; import { syncExistingFields } from './loader'; import { fieldExists } from './pure_helpers'; import { Loader } from '../loader'; -import { FieldsAccordion } from './fields_accordion'; import { esQuery, IIndexPattern } from '../../../../../src/plugins/data/public'; export type Props = DatasourceDataPanelProps & { @@ -52,18 +48,13 @@ export type Props = DatasourceDataPanelProps & { import { LensFieldIcon } from './lens_field_icon'; import { ChangeIndexPattern } from './change_indexpattern'; import { ChartsPluginSetup } from '../../../../../src/plugins/charts/public'; - -// TODO the typings for EuiContextMenuPanel are incorrect - watchedItemProps is missing. This can be removed when the types are adjusted -const FixedEuiContextMenuPanel = (EuiContextMenuPanel as unknown) as React.FunctionComponent< - EuiContextMenuPanelProps & { watchedItemProps: string[] } ->; +import { FieldGroups, FieldList } from './field_list'; function sortFields(fieldA: IndexPatternField, fieldB: IndexPatternField) { return fieldA.displayName.localeCompare(fieldB.displayName, undefined, { sensitivity: 'base' }); } const supportedFieldTypes = new Set(['string', 'number', 'boolean', 'date', 'ip', 'document']); -const PAGINATION_SIZE = 50; const fieldTypeNames: Record = { document: i18n.translate('xpack.lens.datatypes.record', { defaultMessage: 'record' }), @@ -212,18 +203,19 @@ interface DataPanelState { isTypeFilterOpen: boolean; isAvailableAccordionOpen: boolean; isEmptyAccordionOpen: boolean; + isMetaAccordionOpen: boolean; } -export interface FieldsGroup { +const defaultFieldGroups: { specialFields: IndexPatternField[]; availableFields: IndexPatternField[]; emptyFields: IndexPatternField[]; -} - -const defaultFieldGroups = { + metaFields: IndexPatternField[]; +} = { specialFields: [], availableFields: [], emptyFields: [], + metaFields: [], }; const fieldFiltersLabel = i18n.translate('xpack.lens.indexPatterns.fieldFiltersLabel', { @@ -261,9 +253,8 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ isTypeFilterOpen: false, isAvailableAccordionOpen: true, isEmptyAccordionOpen: false, + isMetaAccordionOpen: false, }); - const [pageSize, setPageSize] = useState(PAGINATION_SIZE); - const [scrollContainer, setScrollContainer] = useState(undefined); const currentIndexPattern = indexPatterns[currentIndexPatternId]; const allFields = currentIndexPattern.fields; const clearLocalState = () => setLocalState((s) => ({ ...s, nameFilter: '', typeFilter: [] })); @@ -272,17 +263,11 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ (type) => type in fieldTypeNames ); - useEffect(() => { - // Reset the scroll if we have made material changes to the field list - if (scrollContainer) { - scrollContainer.scrollTop = 0; - setPageSize(PAGINATION_SIZE); - } - }, [localState.nameFilter, localState.typeFilter, currentIndexPatternId, scrollContainer]); + const fieldInfoUnavailable = existenceFetchFailed || currentIndexPattern.hasRestrictions; - const fieldGroups: FieldsGroup = useMemo(() => { + const unfilteredFieldGroups: FieldGroups = useMemo(() => { + const fieldByName = keyBy(allFields, 'name'); const containsData = (field: IndexPatternField) => { - const fieldByName = keyBy(allFields, 'name'); const overallField = fieldByName[field.name]; return ( @@ -294,32 +279,105 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ supportedFieldTypes.has(field.type) ); const sorted = allSupportedTypesFields.sort(sortFields); + let groupedFields; // optimization before existingFields are synced if (!hasSyncedExistingFields) { - return { + groupedFields = { ...defaultFieldGroups, ...groupBy(sorted, (field) => { if (field.type === 'document') { return 'specialFields'; + } else if (field.meta) { + return 'metaFields'; } else { return 'emptyFields'; } }), }; } - return { + groupedFields = { ...defaultFieldGroups, ...groupBy(sorted, (field) => { if (field.type === 'document') { return 'specialFields'; + } else if (field.meta) { + return 'metaFields'; } else if (containsData(field)) { return 'availableFields'; } else return 'emptyFields'; }), }; - }, [allFields, existingFields, currentIndexPattern, hasSyncedExistingFields]); - const filteredFieldGroups: FieldsGroup = useMemo(() => { + const fieldGroupDefinitions: FieldGroups = { + SpecialFields: { + fields: groupedFields.specialFields, + fieldCount: 1, + isAffectedByGlobalFilter: false, + isAffectedByTimeFilter: false, + isInitiallyOpen: false, + showInAccordion: false, + title: '', + hideDetails: true, + }, + AvailableFields: { + fields: groupedFields.availableFields, + fieldCount: groupedFields.availableFields.length, + isInitiallyOpen: true, + showInAccordion: true, + title: fieldInfoUnavailable + ? i18n.translate('xpack.lens.indexPattern.allFieldsLabel', { + defaultMessage: 'All fields', + }) + : i18n.translate('xpack.lens.indexPattern.availableFieldsLabel', { + defaultMessage: 'Available fields', + }), + + isAffectedByGlobalFilter: !!filters.length, + isAffectedByTimeFilter: true, + hideDetails: fieldInfoUnavailable, + }, + EmptyFields: { + fields: groupedFields.emptyFields, + fieldCount: groupedFields.emptyFields.length, + isAffectedByGlobalFilter: false, + isAffectedByTimeFilter: false, + isInitiallyOpen: false, + showInAccordion: true, + hideDetails: false, + title: i18n.translate('xpack.lens.indexPattern.emptyFieldsLabel', { + defaultMessage: 'Empty fields', + }), + }, + MetaFields: { + fields: groupedFields.metaFields, + fieldCount: groupedFields.metaFields.length, + isAffectedByGlobalFilter: false, + isAffectedByTimeFilter: false, + isInitiallyOpen: false, + showInAccordion: true, + hideDetails: false, + title: i18n.translate('xpack.lens.indexPattern.metaFieldsLabel', { + defaultMessage: 'Meta fields', + }), + }, + }; + + // do not show empty field accordion if there is no existence information + if (fieldInfoUnavailable) { + delete fieldGroupDefinitions.EmptyFields; + } + + return fieldGroupDefinitions; + }, [ + allFields, + existingFields, + currentIndexPattern, + hasSyncedExistingFields, + fieldInfoUnavailable, + filters.length, + ]); + + const fieldGroups: FieldGroups = useMemo(() => { const filterFieldGroup = (fieldGroup: IndexPatternField[]) => fieldGroup.filter((field) => { if ( @@ -329,76 +387,18 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ ) { return false; } - if (localState.typeFilter.length > 0) { return localState.typeFilter.includes(field.type as DataType); } return true; }); - - return Object.entries(fieldGroups).reduce((acc, [name, fields]) => { - return { - ...acc, - [name]: filterFieldGroup(fields), - }; - }, defaultFieldGroups); - }, [fieldGroups, localState.nameFilter, localState.typeFilter]); - - const lazyScroll = useCallback(() => { - if (scrollContainer) { - const nearBottom = - scrollContainer.scrollTop + scrollContainer.clientHeight > - scrollContainer.scrollHeight * 0.9; - if (nearBottom) { - const displayedFieldsLength = - (localState.isAvailableAccordionOpen ? filteredFieldGroups.availableFields.length : 0) + - (localState.isEmptyAccordionOpen ? filteredFieldGroups.emptyFields.length : 0); - setPageSize( - Math.max( - PAGINATION_SIZE, - Math.min(pageSize + PAGINATION_SIZE * 0.5, displayedFieldsLength) - ) - ); - } - } - }, [ - scrollContainer, - localState.isAvailableAccordionOpen, - localState.isEmptyAccordionOpen, - filteredFieldGroups, - pageSize, - setPageSize, - ]); - - const [paginatedAvailableFields, paginatedEmptyFields]: [ - IndexPatternField[], - IndexPatternField[] - ] = useMemo(() => { - const { availableFields, emptyFields } = filteredFieldGroups; - const isAvailableAccordionOpen = localState.isAvailableAccordionOpen; - const isEmptyAccordionOpen = localState.isEmptyAccordionOpen; - - if (isAvailableAccordionOpen && isEmptyAccordionOpen) { - if (availableFields.length > pageSize) { - return [availableFields.slice(0, pageSize), []]; - } else { - return [availableFields, emptyFields.slice(0, pageSize - availableFields.length)]; - } - } - if (isAvailableAccordionOpen && !isEmptyAccordionOpen) { - return [availableFields.slice(0, pageSize), []]; - } - - if (!isAvailableAccordionOpen && isEmptyAccordionOpen) { - return [[], emptyFields.slice(0, pageSize)]; - } - return [[], []]; - }, [ - localState.isAvailableAccordionOpen, - localState.isEmptyAccordionOpen, - filteredFieldGroups, - pageSize, - ]); + return Object.fromEntries( + Object.entries(unfilteredFieldGroups).map(([name, group]) => [ + name, + { ...group, fields: filterFieldGroup(group.fields) }, + ]) + ); + }, [unfilteredFieldGroups, localState.nameFilter, localState.typeFilter]); const fieldProps = useMemo( () => ({ @@ -423,8 +423,6 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ ] ); - const fieldInfoUnavailable = existenceFetchFailed || currentIndexPattern.hasRestrictions; - return ( } > - ( @@ -545,115 +543,21 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ -
{ - if (el && !el.dataset.dynamicScroll) { - el.dataset.dynamicScroll = 'true'; - setScrollContainer(el); - } + + field.type === 'document' || + fieldExists(existingFields, currentIndexPattern.title, field.name) + } + fieldProps={fieldProps} + fieldGroups={fieldGroups} + hasSyncedExistingFields={!!hasSyncedExistingFields} + filter={{ + nameFilter: localState.nameFilter, + typeFilter: localState.typeFilter, }} - onScroll={throttle(lazyScroll, 100)} - > -
- {filteredFieldGroups.specialFields.map((field: IndexPatternField) => ( - - ))} - - - { - setLocalState((s) => ({ - ...s, - isAvailableAccordionOpen: open, - })); - const displayedFieldLength = - (open ? filteredFieldGroups.availableFields.length : 0) + - (localState.isEmptyAccordionOpen ? filteredFieldGroups.emptyFields.length : 0); - setPageSize( - Math.max(PAGINATION_SIZE, Math.min(pageSize * 1.5, displayedFieldLength)) - ); - }} - showExistenceFetchError={existenceFetchFailed} - renderCallout={ - - } - /> - - {!fieldInfoUnavailable && ( - { - setLocalState((s) => ({ - ...s, - isEmptyAccordionOpen: open, - })); - const displayedFieldLength = - (localState.isAvailableAccordionOpen - ? filteredFieldGroups.availableFields.length - : 0) + (open ? filteredFieldGroups.emptyFields.length : 0); - setPageSize( - Math.max(PAGINATION_SIZE, Math.min(pageSize * 1.5, displayedFieldLength)) - ); - }} - renderCallout={ - - } - /> - )} - -
-
+ currentIndexPatternId={currentIndexPatternId} + existenceFetchFailed={existenceFetchFailed} + />
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx index 4b549f537da302..dafe0dbe3d1929 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx @@ -116,7 +116,8 @@ export function FieldSelect({ })); } - const [availableFields, emptyFields] = _.partition(normalFields, containsData); + const [metaFields, nonMetaFields] = _.partition(normalFields, (field) => fieldMap[field].meta); + const [availableFields, emptyFields] = _.partition(nonMetaFields, containsData); const constructFieldsOptions = (fieldsArr: string[], label: string) => fieldsArr.length > 0 && { @@ -138,10 +139,18 @@ export function FieldSelect({ }) ); + const metaFieldsOptions = constructFieldsOptions( + metaFields, + i18n.translate('xpack.lens.indexPattern.metaFieldsLabel', { + defaultMessage: 'Meta fields', + }) + ); + return [ ...fieldNamesToOptions(specialFields), availableFieldsOptions, emptyFieldsOptions, + metaFieldsOptions, ].filter(Boolean); }, [ incompatibleSelectedOperationType, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index 1f6d7911b3a33c..1eeb64127310f9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -184,7 +184,8 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) { defaultMessage: 'Click for a field preview, or drag and drop to visualize.', }) : i18n.translate('xpack.lens.indexPattern.fieldStatsButtonEmptyLabel', { - defaultMessage: "This field doesn't have data. Drag and drop to visualize.", + defaultMessage: + 'This field doesn’t have any data but you can still drag and drop to visualize.', }) } type="iInCircle" @@ -307,7 +308,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { {i18n.translate('xpack.lens.indexPattern.fieldStatsNoData', { defaultMessage: - 'This field is empty because it doesn’t exist in the 500 sampled documents.', + 'This field is empty because it doesn’t exist in the 500 sampled documents. Adding this field to the configuration may result in a blank chart.', })} ); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_list.scss b/x-pack/plugins/lens/public/indexpattern_datasource/field_list.scss new file mode 100644 index 00000000000000..f28581b835b078 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_list.scss @@ -0,0 +1,20 @@ +/** + * 1. Don't cut off the shadow of the field items + */ + +.lnsIndexPatternFieldList { + @include euiOverflowShadow; + @include euiScrollBar; + margin-left: -$euiSize; /* 1 */ + position: relative; + flex-grow: 1; + overflow: auto; +} + +.lnsIndexPatternFieldList__accordionContainer { + padding-top: $euiSizeS; + position: absolute; + top: 0; + left: $euiSize; /* 1 */ + right: $euiSizeXS; /* 1 */ +} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_list.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_list.tsx new file mode 100644 index 00000000000000..4a9b3a0c63e3f4 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_list.tsx @@ -0,0 +1,193 @@ +/* + * 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 './field_list.scss'; +import { throttle } from 'lodash'; +import React, { useState, Fragment, useCallback, useMemo, useEffect } from 'react'; +import { EuiSpacer } from '@elastic/eui'; +import { FieldItem } from './field_item'; +import { NoFieldsCallout } from './no_fields_callout'; +import { IndexPatternField } from './types'; +import { FieldItemSharedProps, FieldsAccordion } from './fields_accordion'; +const PAGINATION_SIZE = 50; + +export interface FieldsGroup { + specialFields: IndexPatternField[]; + availableFields: IndexPatternField[]; + emptyFields: IndexPatternField[]; + metaFields: IndexPatternField[]; +} + +export type FieldGroups = Record< + string, + { + fields: IndexPatternField[]; + fieldCount: number; + showInAccordion: boolean; + isInitiallyOpen: boolean; + title: string; + isAffectedByGlobalFilter: boolean; + isAffectedByTimeFilter: boolean; + hideDetails?: boolean; + } +>; + +function getDisplayedFieldsLength( + fieldGroups: FieldGroups, + accordionState: Partial> +) { + return Object.entries(fieldGroups) + .filter(([key]) => accordionState[key]) + .reduce((allFieldCount, [, { fields }]) => allFieldCount + fields.length, 0); +} + +export function FieldList({ + exists, + fieldGroups, + existenceFetchFailed, + fieldProps, + hasSyncedExistingFields, + filter, + currentIndexPatternId, +}: { + exists: (field: IndexPatternField) => boolean; + fieldGroups: FieldGroups; + fieldProps: FieldItemSharedProps; + hasSyncedExistingFields: boolean; + existenceFetchFailed?: boolean; + filter: { + nameFilter: string; + typeFilter: string[]; + }; + currentIndexPatternId: string; +}) { + const [pageSize, setPageSize] = useState(PAGINATION_SIZE); + const [scrollContainer, setScrollContainer] = useState(undefined); + const [accordionState, setAccordionState] = useState>>(() => + Object.fromEntries( + Object.entries(fieldGroups) + .filter(([, { showInAccordion }]) => showInAccordion) + .map(([key, { isInitiallyOpen }]) => [key, isInitiallyOpen]) + ) + ); + + const isAffectedByFieldFilter = !!(filter.typeFilter.length || filter.nameFilter.length); + + useEffect(() => { + // Reset the scroll if we have made material changes to the field list + if (scrollContainer) { + scrollContainer.scrollTop = 0; + setPageSize(PAGINATION_SIZE); + } + }, [filter.nameFilter, filter.typeFilter, currentIndexPatternId, scrollContainer]); + + const lazyScroll = useCallback(() => { + if (scrollContainer) { + const nearBottom = + scrollContainer.scrollTop + scrollContainer.clientHeight > + scrollContainer.scrollHeight * 0.9; + if (nearBottom) { + setPageSize( + Math.max( + PAGINATION_SIZE, + Math.min( + pageSize + PAGINATION_SIZE * 0.5, + getDisplayedFieldsLength(fieldGroups, accordionState) + ) + ) + ); + } + } + }, [scrollContainer, pageSize, setPageSize, fieldGroups, accordionState]); + + const paginatedFields = useMemo(() => { + let remainingItems = pageSize; + return Object.fromEntries( + Object.entries(fieldGroups) + .filter(([, { showInAccordion }]) => showInAccordion) + .map(([key, fieldGroup]) => { + if (!accordionState[key] || remainingItems <= 0) { + return [key, []]; + } + const slicedFieldList = fieldGroup.fields.slice(0, remainingItems); + remainingItems = remainingItems - slicedFieldList.length; + return [key, slicedFieldList]; + }) + ); + }, [pageSize, fieldGroups, accordionState]); + + return ( +
{ + if (el && !el.dataset.dynamicScroll) { + el.dataset.dynamicScroll = 'true'; + setScrollContainer(el); + } + }} + onScroll={throttle(lazyScroll, 100)} + > +
+ {Object.entries(fieldGroups) + .filter(([, { showInAccordion }]) => !showInAccordion) + .flatMap(([, { fields }]) => + fields.map((field) => ( + + )) + )} + + {Object.entries(fieldGroups) + .filter(([, { showInAccordion }]) => showInAccordion) + .map(([key, fieldGroup]) => ( + + { + setAccordionState((s) => ({ + ...s, + [key]: open, + })); + const displayedFieldLength = getDisplayedFieldsLength(fieldGroups, { + ...accordionState, + [key]: open, + }); + setPageSize( + Math.max(PAGINATION_SIZE, Math.min(pageSize * 1.5, displayedFieldLength)) + ); + }} + showExistenceFetchError={existenceFetchFailed} + renderCallout={ + + } + /> + + + ))} +
+
+ ); +} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx index b0604efff7b891..7d1c80e5a7f6a9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx @@ -71,11 +71,19 @@ describe('Fields Accordion', () => { paginatedFields: indexPattern.fields, fieldProps, renderCallout:
Callout
, - exists: true, + exists: () => true, }; }); it('renders correct number of Field Items', () => { + const wrapper = mountWithIntl( + field.name === 'timestamp'} /> + ); + expect(wrapper.find(FieldItem).at(0).prop('exists')).toEqual(true); + expect(wrapper.find(FieldItem).at(1).prop('exists')).toEqual(false); + }); + + it('passed correct exists flag to each field', () => { const wrapper = mountWithIntl(); expect(wrapper.find(FieldItem).length).toEqual(2); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx index 30a92c21ff6610..e531eb72f94caa 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx @@ -45,7 +45,7 @@ export interface FieldsAccordionProps { paginatedFields: IndexPatternField[]; fieldProps: FieldItemSharedProps; renderCallout: JSX.Element; - exists: boolean; + exists: (field: IndexPatternField) => boolean; showExistenceFetchError?: boolean; hideDetails?: boolean; } @@ -71,7 +71,7 @@ export const InnerFieldsAccordion = function InnerFieldsAccordion({ {...fieldProps} key={field.name} field={field} - exists={exists} + exists={exists(field)} hideDetails={hideDetails} /> ), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts index 19213d4afc9bcb..ef6abbec9a34d1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts @@ -197,7 +197,7 @@ function mockClient() { function mockIndexPatternsService() { return ({ get: jest.fn(async (id: '1' | '2') => { - return sampleIndexPatternsFromService[id]; + return { ...sampleIndexPatternsFromService[id], metaFields: [] }; }), } as unknown) as Pick; } @@ -248,6 +248,7 @@ describe('loader', () => { get: jest.fn(async () => ({ id: 'foo', title: 'Foo index', + metaFields: [], typeMeta: { aggs: { date_histogram: { @@ -295,6 +296,55 @@ describe('loader', () => { date_histogram: { agg: 'date_histogram', fixed_interval: 'm' }, }); }); + + it('should map meta flag', async () => { + const cache = await loadIndexPatterns({ + cache: {}, + patterns: ['foo'], + indexPatternsService: ({ + get: jest.fn(async () => ({ + id: 'foo', + title: 'Foo index', + metaFields: ['timestamp'], + typeMeta: { + aggs: { + date_histogram: { + timestamp: { + agg: 'date_histogram', + fixed_interval: 'm', + }, + }, + sum: { + bytes: { + agg: 'sum', + }, + }, + }, + }, + fields: [ + { + name: 'timestamp', + displayName: 'timestampLabel', + type: 'date', + aggregatable: true, + searchable: true, + }, + { + name: 'bytes', + displayName: 'bytes', + type: 'number', + aggregatable: true, + searchable: true, + }, + ], + })), + } as unknown) as Pick, + }); + + expect(cache.foo.fields.find((f: IndexPatternField) => f.name === 'timestamp')!.meta).toEqual( + true + ); + }); }); describe('loadInitialState', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts index 0ab658b9613363..c4b1eb9e0c4c4a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts @@ -63,6 +63,7 @@ export async function loadIndexPatterns({ type: field.type, aggregatable: field.aggregatable, searchable: field.searchable, + meta: indexPattern.metaFields.includes(field.name), esTypes: field.esTypes, scripted: field.scripted, }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts index b691c5b5c4c403..a3c0e8aed74219 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts @@ -26,6 +26,7 @@ export interface IndexPattern { export type IndexPatternField = IFieldType & { displayName: string; aggregationRestrictions?: Partial; + meta?: boolean; }; export interface IndexPatternLayer { diff --git a/x-pack/plugins/lens/public/lens_attribute_service.ts b/x-pack/plugins/lens/public/lens_attribute_service.ts new file mode 100644 index 00000000000000..3c43fd98cceb46 --- /dev/null +++ b/x-pack/plugins/lens/public/lens_attribute_service.ts @@ -0,0 +1,52 @@ +/* + * 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 { CoreStart } from '../../../../src/core/public'; +import { LensPluginStartDependencies } from './plugin'; +import { AttributeService } from '../../../../src/plugins/dashboard/public'; +import { + LensSavedObjectAttributes, + LensByValueInput, + LensByReferenceInput, +} from './editor_frame_service/embeddable/embeddable'; +import { SavedObjectIndexStore, DOC_TYPE } from './persistence'; + +export type LensAttributeService = AttributeService< + LensSavedObjectAttributes, + LensByValueInput, + LensByReferenceInput +>; + +export function getLensAttributeService( + core: CoreStart, + startDependencies: LensPluginStartDependencies +): LensAttributeService { + const savedObjectStore = new SavedObjectIndexStore(core.savedObjects.client); + return startDependencies.dashboard.getAttributeService< + LensSavedObjectAttributes, + LensByValueInput, + LensByReferenceInput + >(DOC_TYPE, { + customSaveMethod: async ( + type: string, + attributes: LensSavedObjectAttributes, + savedObjectId?: string + ) => { + const savedDoc = await savedObjectStore.save({ + ...attributes, + savedObjectId, + type: DOC_TYPE, + }); + return { id: savedDoc.savedObjectId }; + }, + customUnwrapMethod: (savedObject) => { + return { + ...savedObject.attributes, + references: savedObject.references, + }; + }, + }); +} diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts index ba7c0ee6ae786e..6b6f81aeefed07 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts @@ -42,7 +42,7 @@ describe('LensStore', () => { }); expect(doc).toEqual({ - id: 'FOO', + savedObjectId: 'FOO', title: 'Hello', description: 'My doc', visualizationType: 'bar', @@ -82,7 +82,7 @@ describe('LensStore', () => { test('updates and returns a visualization document', async () => { const { client, store } = testStore(); const doc = await store.save({ - id: 'Gandalf', + savedObjectId: 'Gandalf', title: 'Even the very wise cannot see all ends.', visualizationType: 'line', references: [], @@ -95,7 +95,7 @@ describe('LensStore', () => { }); expect(doc).toEqual({ - id: 'Gandalf', + savedObjectId: 'Gandalf', title: 'Even the very wise cannot see all ends.', visualizationType: 'line', references: [], diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.ts index e4609213ec7929..c6b3fd2cc0f652 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.ts @@ -13,7 +13,7 @@ import { Query } from '../../../../../src/plugins/data/public'; import { PersistableFilter } from '../../common'; export interface Document { - id?: string; + savedObjectId?: string; type?: string; visualizationType: string | null; title: string; @@ -30,11 +30,11 @@ export interface Document { export const DOC_TYPE = 'lens'; export interface DocumentSaver { - save: (vis: Document) => Promise<{ id: string }>; + save: (vis: Document) => Promise<{ savedObjectId: string }>; } export interface DocumentLoader { - load: (id: string) => Promise; + load: (savedObjectId: string) => Promise; } export type SavedObjectStore = DocumentLoader & DocumentSaver; @@ -46,20 +46,20 @@ export class SavedObjectIndexStore implements SavedObjectStore { this.client = client; } - async save(vis: Document) { - const { id, type, references, ...rest } = vis; + save = async (vis: Document) => { + const { savedObjectId, type, references, ...rest } = vis; // TODO: SavedObjectAttributes should support this kind of object, // remove this workaround when SavedObjectAttributes is updated. const attributes = (rest as unknown) as SavedObjectAttributes; - const result = await (id - ? this.safeUpdate(id, attributes, references) + const result = await (savedObjectId + ? this.safeUpdate(savedObjectId, attributes, references) : this.client.create(DOC_TYPE, attributes, { references, })); - return { ...vis, id: result.id }; - } + return { ...vis, savedObjectId: result.id }; + }; // As Lens is using an object to store its attributes, using the update API // will merge the new attribute object with the old one, not overwriting deleted @@ -68,7 +68,7 @@ export class SavedObjectIndexStore implements SavedObjectStore { // This function fixes this by doing two updates - one to empty out the document setting // every key to null, and a second one to load the new content. private async safeUpdate( - id: string, + savedObjectId: string, attributes: SavedObjectAttributes, references: SavedObjectReference[] ) { @@ -78,14 +78,14 @@ export class SavedObjectIndexStore implements SavedObjectStore { }); return ( await this.client.bulkUpdate([ - { type: DOC_TYPE, id, attributes: resetAttributes, references }, - { type: DOC_TYPE, id, attributes, references }, + { type: DOC_TYPE, id: savedObjectId, attributes: resetAttributes, references }, + { type: DOC_TYPE, id: savedObjectId, attributes, references }, ]) ).savedObjects[1]; } - async load(id: string): Promise { - const { type, attributes, references, error } = await this.client.get(DOC_TYPE, id); + async load(savedObjectId: string): Promise { + const { type, attributes, references, error } = await this.client.get(DOC_TYPE, savedObjectId); if (error) { throw error; @@ -94,7 +94,7 @@ export class SavedObjectIndexStore implements SavedObjectStore { return { ...(attributes as SavedObjectAttributes), references, - id, + savedObjectId, type, } as Document; } diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index f9c63f54d67131..1655a571721f5b 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -7,10 +7,12 @@ import { AppMountParameters, CoreSetup, CoreStart } from 'kibana/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public'; import { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public'; +import { DashboardStart } from 'src/plugins/dashboard/public'; import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/public'; import { VisualizationsSetup } from 'src/plugins/visualizations/public'; import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; import { UrlForwardingSetup } from 'src/plugins/url_forwarding/public'; +import { GlobalSearchPluginSetup } from '../../global_search/public'; import { ChartsPluginSetup } from '../../../../src/plugins/charts/public'; import { EditorFrameService } from './editor_frame_service'; import { @@ -31,8 +33,10 @@ import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common'; import { EditorFrameStart } from './types'; import { getLensAliasConfig } from './vis_type_alias'; +import { getSearchProvider } from './search_provider'; import './index.scss'; +import { getLensAttributeService, LensAttributeService } from './lens_attribute_service'; export interface LensPluginSetupDependencies { urlForwarding: UrlForwardingSetup; @@ -41,6 +45,7 @@ export interface LensPluginSetupDependencies { embeddable?: EmbeddableSetup; visualizations: VisualizationsSetup; charts: ChartsPluginSetup; + globalSearch?: GlobalSearchPluginSetup; } export interface LensPluginStartDependencies { @@ -48,13 +53,14 @@ export interface LensPluginStartDependencies { expressions: ExpressionsStart; navigation: NavigationPublicPluginStart; uiActions: UiActionsStart; - embeddable: EmbeddableStart; + dashboard: DashboardStart; + embeddable?: EmbeddableStart; } - export class LensPlugin { private datatableVisualization: DatatableVisualization; private editorFrameService: EditorFrameService; private createEditorFrame: EditorFrameStart['createInstance'] | null = null; + private attributeService: LensAttributeService | null = null; private indexpatternDatasource: IndexPatternDatasource; private xyVisualization: XyVisualization; private metricVisualization: MetricVisualization; @@ -78,13 +84,18 @@ export class LensPlugin { embeddable, visualizations, charts, + globalSearch, }: LensPluginSetupDependencies ) { - const editorFrameSetupInterface = this.editorFrameService.setup(core, { - data, - embeddable, - expressions, - }); + const editorFrameSetupInterface = this.editorFrameService.setup( + core, + { + data, + embeddable, + expressions, + }, + () => this.attributeService! + ); const dependencies: IndexPatternDatasourceSetupPlugins & XyVisualizationPluginSetupPlugins & DatatableVisualizationPluginSetupPlugins & @@ -106,20 +117,44 @@ export class LensPlugin { visualizations.registerAlias(getLensAliasConfig()); + const getByValueFeatureFlag = async () => { + const [, deps] = await core.getStartServices(); + return deps.dashboard.dashboardFeatureFlagConfig; + }; + core.application.register({ id: 'lens', title: NOT_INTERNATIONALIZED_PRODUCT_NAME, navLinkStatus: AppNavLinkStatus.hidden, mount: async (params: AppMountParameters) => { const { mountApp } = await import('./app_plugin/mounter'); - return mountApp(core, params, this.createEditorFrame!); + return mountApp(core, params, { + createEditorFrame: this.createEditorFrame!, + attributeService: this.attributeService!, + getByValueFeatureFlag, + }); }, }); + if (globalSearch) { + globalSearch.registerResultProvider( + getSearchProvider( + core.getStartServices().then( + ([ + { + application: { capabilities }, + }, + ]) => capabilities + ) + ) + ); + } + urlForwarding.forwardApp('lens', 'lens'); } start(core: CoreStart, startDependencies: LensPluginStartDependencies) { + this.attributeService = getLensAttributeService(core, startDependencies); this.createEditorFrame = this.editorFrameService.start(core, startDependencies).createInstance; } diff --git a/x-pack/plugins/lens/public/search_provider.ts b/x-pack/plugins/lens/public/search_provider.ts new file mode 100644 index 00000000000000..c19e7970b45ae6 --- /dev/null +++ b/x-pack/plugins/lens/public/search_provider.ts @@ -0,0 +1,79 @@ +/* + * 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 levenshtein from 'js-levenshtein'; +import { ApplicationStart } from 'kibana/public'; +import { from } from 'rxjs'; +import { i18n } from '@kbn/i18n'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; +import { GlobalSearchResultProvider } from '../../global_search/public'; +import { getFullPath } from '../common'; + +/** + * Global search provider adding a Lens entry. + * This is necessary because Lens does not show up in the nav bar and is filtered out by the + * default app provider. + * + * It is inlining the same search term matching logic as the application search provider. + * + * TODO: This is a workaround and can be removed once there is a generic way to register sub features + * of apps. In this case, Lens should be considered a feature of Visualize. + */ +export const getSearchProvider: ( + uiCapabilities: Promise +) => GlobalSearchResultProvider = (uiCapabilities) => ({ + id: 'lens', + find: (term) => { + return from( + uiCapabilities.then(({ navLinks: { visualize: visualizeNavLink } }) => { + if (!visualizeNavLink) { + return []; + } + const title = i18n.translate('xpack.lens.searchTitle', { + defaultMessage: 'Lens: create visualizations', + description: 'Lens is a product name and should not be translated', + }); + const searchableTitle = title.toLowerCase(); + + term = term.toLowerCase(); + let score = 0; + + // shortcuts to avoid calculating the distance when there is an exact match somewhere. + if (searchableTitle === term) { + score = 100; + } else if (searchableTitle.startsWith(term)) { + score = 90; + } else if (searchableTitle.includes(term)) { + score = 75; + } else { + const length = Math.max(term.length, searchableTitle.length); + const distance = levenshtein(term, searchableTitle); + + // maximum lev distance is length, we compute the match ratio (lower distance is better) + const ratio = Math.floor((1 - distance / length) * 100); + if (ratio >= 60) { + score = ratio; + } + } + if (score === 0) return []; + return [ + { + id: 'lens', + title, + type: 'application', + icon: 'logoKibana', + meta: { + categoryId: DEFAULT_APP_CATEGORIES.kibana.id, + categoryLabel: DEFAULT_APP_CATEGORIES.kibana.label, + }, + score, + url: getFullPath(), + }, + ]; + }) + ); + }, +}); diff --git a/x-pack/plugins/lens/server/routes/existing_fields.test.ts b/x-pack/plugins/lens/server/routes/existing_fields.test.ts index 728b78c8e97bc4..9799dcf92ae411 100644 --- a/x-pack/plugins/lens/server/routes/existing_fields.test.ts +++ b/x-pack/plugins/lens/server/routes/existing_fields.test.ts @@ -15,6 +15,7 @@ describe('existingFields', () => { name, isScript: false, isAlias: false, + isMeta: false, path: name.split('.'), ...obj, }; @@ -101,6 +102,15 @@ describe('existingFields', () => { expect(result).toEqual(['baz']); }); + + it('supports meta fields', () => { + const result = existingFields( + [{ _mymeta: 'abc', ...indexPattern({}, { bar: 'scriptvalue' }) }], + [field({ name: '_mymeta', isMeta: true, path: ['_mymeta'] })] + ); + + expect(result).toEqual(['_mymeta']); + }); }); describe('buildFieldList', () => { @@ -116,6 +126,7 @@ describe('buildFieldList', () => { { name: 'bar' }, { name: '@bar' }, { name: 'baz' }, + { name: '_mymeta' }, ]), }, references: [], @@ -142,7 +153,7 @@ describe('buildFieldList', () => { ]; it('uses field descriptors to determine the path', () => { - const fields = buildFieldList(indexPattern, mappings, fieldDescriptors); + const fields = buildFieldList(indexPattern, mappings, fieldDescriptors, []); expect(fields.find((f) => f.name === 'baz')).toMatchObject({ isAlias: false, isScript: false, @@ -152,7 +163,7 @@ describe('buildFieldList', () => { }); it('uses aliases to determine the path', () => { - const fields = buildFieldList(indexPattern, mappings, fieldDescriptors); + const fields = buildFieldList(indexPattern, mappings, fieldDescriptors, []); expect(fields.find((f) => f.isAlias)).toMatchObject({ isAlias: true, isScript: false, @@ -162,7 +173,7 @@ describe('buildFieldList', () => { }); it('supports scripted fields', () => { - const fields = buildFieldList(indexPattern, mappings, fieldDescriptors); + const fields = buildFieldList(indexPattern, mappings, fieldDescriptors, []); expect(fields.find((f) => f.isScript)).toMatchObject({ isAlias: false, isScript: true, @@ -173,13 +184,24 @@ describe('buildFieldList', () => { }); }); + it('supports meta fields', () => { + const fields = buildFieldList(indexPattern, mappings, fieldDescriptors, ['_mymeta']); + expect(fields.find((f) => f.isMeta)).toMatchObject({ + isAlias: false, + isScript: false, + isMeta: true, + name: '_mymeta', + path: ['_mymeta'], + }); + }); + it('handles missing mappings', () => { - const fields = buildFieldList(indexPattern, {}, fieldDescriptors); + const fields = buildFieldList(indexPattern, {}, fieldDescriptors, []); expect(fields.every((f) => f.isAlias === false)).toEqual(true); }); it('handles empty fieldDescriptors by skipping multi-mappings', () => { - const fields = buildFieldList(indexPattern, mappings, []); + const fields = buildFieldList(indexPattern, mappings, [], []); expect(fields.find((f) => f.name === 'baz')).toMatchObject({ isAlias: false, isScript: false, diff --git a/x-pack/plugins/lens/server/routes/existing_fields.ts b/x-pack/plugins/lens/server/routes/existing_fields.ts index 7ab3cdceb21457..33fcafacfad733 100644 --- a/x-pack/plugins/lens/server/routes/existing_fields.ts +++ b/x-pack/plugins/lens/server/routes/existing_fields.ts @@ -12,6 +12,7 @@ import { BASE_API_URL } from '../../common'; import { IndexPatternsFetcher, IndexPatternAttributes, + UI_SETTINGS, } from '../../../../../src/plugins/data/server'; /** @@ -36,13 +37,12 @@ export interface Field { name: string; isScript: boolean; isAlias: boolean; + isMeta: boolean; path: string[]; lang?: string; script?: string; } -const metaFields = ['_source', '_type']; - export async function existingFieldsRoute(setup: CoreSetup) { const router = setup.http.createRouter(); @@ -104,14 +104,15 @@ async function fetchFieldExistence({ toDate?: string; timeFieldName?: string; }) { + const metaFields: string[] = await context.core.uiSettings.client.get(UI_SETTINGS.META_FIELDS); const { indexPattern, indexPatternTitle, mappings, fieldDescriptors, - } = await fetchIndexPatternDefinition(indexPatternId, context); + } = await fetchIndexPatternDefinition(indexPatternId, context, metaFields); - const fields = buildFieldList(indexPattern, mappings, fieldDescriptors); + const fields = buildFieldList(indexPattern, mappings, fieldDescriptors, metaFields); const docs = await fetchIndexPatternStats({ fromDate, toDate, @@ -128,7 +129,11 @@ async function fetchFieldExistence({ }; } -async function fetchIndexPatternDefinition(indexPatternId: string, context: RequestHandlerContext) { +async function fetchIndexPatternDefinition( + indexPatternId: string, + context: RequestHandlerContext, + metaFields: string[] +) { const savedObjectsClient = context.core.savedObjects.client; const requestClient = context.core.elasticsearch.legacy.client; const indexPattern = await savedObjectsClient.get( @@ -178,7 +183,8 @@ async function fetchIndexPatternDefinition(indexPatternId: string, context: Requ export function buildFieldList( indexPattern: SavedObject, mappings: MappingResult | {}, - fieldDescriptors: FieldDescriptor[] + fieldDescriptors: FieldDescriptor[], + metaFields: string[] ): Field[] { const aliasMap = Object.entries(Object.values(mappings)[0]?.mappings.properties ?? {}) .map(([name, v]) => ({ ...v, name })) @@ -204,6 +210,9 @@ export function buildFieldList( path: path.split('.'), lang: field.lang, script: field.script, + // id is a special case - it doesn't show up in the meta field list, + // but as it's not part of source, it has to be handled separately. + isMeta: metaFields.includes(field.name) || field.name === '_id', }; } ); @@ -312,7 +321,7 @@ function exists(obj: unknown, path: string[], i = 0): boolean { * Exported only for unit tests. */ export function existingFields( - docs: Array<{ _source: unknown; fields: unknown }>, + docs: Array<{ _source: unknown; fields: unknown; [key: string]: unknown }>, fields: Field[] ): string[] { const missingFields = new Set(fields); @@ -323,7 +332,14 @@ export function existingFields( } missingFields.forEach((field) => { - if (exists(field.isScript ? doc.fields : doc._source, field.path)) { + let fieldStore = doc._source; + if (field.isScript) { + fieldStore = doc.fields; + } + if (field.isMeta) { + fieldStore = doc; + } + if (exists(fieldStore, field.path)) { missingFields.delete(field); } }); diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index d72d04d2a18435..be891b6e596088 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -37,6 +37,7 @@ export const FONTS_API_PATH = `${GIS_API_PATH}/fonts`; export const API_ROOT_PATH = `/${GIS_API_PATH}`; export const MVT_GETTILE_API_PATH = 'mvt/getTile'; +export const MVT_GETGRIDTILE_API_PATH = 'mvt/getGridTile'; export const MVT_SOURCE_LAYER_NAME = 'source_layer'; export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__'; export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__'; @@ -165,8 +166,13 @@ export enum GRID_RESOLUTION { COARSE = 'COARSE', FINE = 'FINE', MOST_FINE = 'MOST_FINE', + SUPER_FINE = 'SUPER_FINE', } +export const SUPER_FINE_ZOOM_DELTA = 7; // (2 ^ SUPER_FINE_ZOOM_DELTA) ^ 2 = number of cells in a given tile +export const GEOTILE_GRID_AGG_NAME = 'gridSplit'; +export const GEOCENTROID_AGG_NAME = 'gridCentroid'; + export const TOP_TERM_PERCENTAGE_SUFFIX = '__percentage'; export const COUNT_PROP_LABEL = i18n.translate('xpack.maps.aggs.defaultCountLabel', { @@ -230,8 +236,6 @@ export enum SCALING_TYPES { MVT = 'MVT', } -export const RGBA_0000 = 'rgba(0,0,0,0)'; - export enum MVT_FIELD_TYPE { STRING = 'String', NUMBER = 'Number', diff --git a/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts new file mode 100644 index 00000000000000..b1c1b181d81300 --- /dev/null +++ b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts @@ -0,0 +1,11 @@ +/* + * 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 { Feature } from 'geojson'; +import { RENDER_AS } from '../constants'; + +export function convertCompositeRespToGeoJson(esResponse: any, renderAs: RENDER_AS): Feature[]; +export function convertRegularRespToGeoJson(esResponse: any, renderAs: RENDER_AS): Feature[]; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.js similarity index 79% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js rename to x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.js index 35dbebdfd3c8a4..a8f32bb4e7f5da 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.js @@ -5,12 +5,12 @@ */ import _ from 'lodash'; -import { RENDER_AS } from '../../../../common/constants'; -import { getTileBoundingBox } from './geo_tile_utils'; -import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; -import { clamp } from '../../../../common/elasticsearch_geo_utils'; +import { RENDER_AS, GEOTILE_GRID_AGG_NAME, GEOCENTROID_AGG_NAME } from '../constants'; +import { getTileBoundingBox } from '../geo_tile_utils'; +import { extractPropertiesFromBucket } from './es_agg_utils'; +import { clamp } from './elasticsearch_geo_utils'; -const GRID_BUCKET_KEYS_TO_IGNORE = ['key', 'gridCentroid']; +const GRID_BUCKET_KEYS_TO_IGNORE = ['key', GEOCENTROID_AGG_NAME]; export function convertCompositeRespToGeoJson(esResponse, renderAs) { return convertToGeoJson( @@ -20,7 +20,7 @@ export function convertCompositeRespToGeoJson(esResponse, renderAs) { return _.get(esResponse, 'aggregations.compositeSplit.buckets', []); }, (gridBucket) => { - return gridBucket.key.gridSplit; + return gridBucket.key[GEOTILE_GRID_AGG_NAME]; } ); } @@ -30,7 +30,7 @@ export function convertRegularRespToGeoJson(esResponse, renderAs) { esResponse, renderAs, (esResponse) => { - return _.get(esResponse, 'aggregations.gridSplit.buckets', []); + return _.get(esResponse, `aggregations.${GEOTILE_GRID_AGG_NAME}.buckets`, []); }, (gridBucket) => { return gridBucket.key; @@ -49,7 +49,7 @@ function convertToGeoJson(esResponse, renderAs, pluckGridBuckets, pluckGridKey) type: 'Feature', geometry: rowToGeometry({ gridKey, - gridCentroid: gridBucket.gridCentroid, + [GEOCENTROID_AGG_NAME]: gridBucket[GEOCENTROID_AGG_NAME], renderAs, }), id: gridKey, diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.test.ts b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.test.ts similarity index 97% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.test.ts rename to x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.test.ts index 523cc869150108..ee40a1f2fc7513 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.test.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.test.ts @@ -4,11 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../kibana_services', () => {}); - // @ts-ignore import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; -import { RENDER_AS } from '../../../../common/constants'; +import { RENDER_AS } from '../constants'; describe('convertCompositeRespToGeoJson', () => { const esResponse = { diff --git a/x-pack/plugins/maps/common/elasticsearch_geo_utils.d.ts b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts similarity index 89% rename from x-pack/plugins/maps/common/elasticsearch_geo_utils.d.ts rename to x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts index e57efca94d95e7..cff8ba119e1de2 100644 --- a/x-pack/plugins/maps/common/elasticsearch_geo_utils.d.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts @@ -5,8 +5,8 @@ */ import { FeatureCollection, GeoJsonProperties } from 'geojson'; -import { MapExtent } from './descriptor_types'; -import { ES_GEO_FIELD_TYPE } from './constants'; +import { MapExtent } from '../descriptor_types'; +import { ES_GEO_FIELD_TYPE } from '../constants'; export function scaleBounds(bounds: MapExtent, scaleFactor: number): MapExtent; diff --git a/x-pack/plugins/maps/common/elasticsearch_geo_utils.js b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js similarity index 98% rename from x-pack/plugins/maps/common/elasticsearch_geo_utils.js rename to x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js index f2bf83ae18bb0d..be214e3b01e67b 100644 --- a/x-pack/plugins/maps/common/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js @@ -15,9 +15,9 @@ import { POLYGON_COORDINATES_EXTERIOR_INDEX, LON_INDEX, LAT_INDEX, -} from '../common/constants'; -import { getEsSpatialRelationLabel } from './i18n_getters'; -import { FILTERS } from '../../../../src/plugins/data/common'; +} from '../constants'; +import { getEsSpatialRelationLabel } from '../i18n_getters'; +import { FILTERS } from '../../../../../src/plugins/data/common'; import turfCircle from '@turf/circle'; const SPATIAL_FILTER_TYPE = FILTERS.SPATIAL_FILTER; diff --git a/x-pack/plugins/maps/common/elasticsearch_geo_utils.test.js b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js similarity index 100% rename from x-pack/plugins/maps/common/elasticsearch_geo_utils.test.js rename to x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js diff --git a/x-pack/plugins/maps/public/classes/util/es_agg_utils.test.ts b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.test.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/util/es_agg_utils.test.ts rename to x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.test.ts diff --git a/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts similarity index 92% rename from x-pack/plugins/maps/public/classes/util/es_agg_utils.ts rename to x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts index 329a2a6fc64fb1..7828c3cc6410b5 100644 --- a/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts @@ -5,8 +5,8 @@ */ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; -import { IndexPattern, IFieldType } from '../../../../../../src/plugins/data/public'; -import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; +import { IndexPattern, IFieldType } from '../../../../../src/plugins/data/common'; +import { TOP_TERM_PERCENTAGE_SUFFIX } from '../constants'; export function getField(indexPattern: IndexPattern, fieldName: string) { const field = indexPattern.fields.getByName(fieldName); diff --git a/x-pack/plugins/maps/common/elasticsearch_util/index.ts b/x-pack/plugins/maps/common/elasticsearch_util/index.ts new file mode 100644 index 00000000000000..ffb4a542374fa2 --- /dev/null +++ b/x-pack/plugins/maps/common/elasticsearch_util/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './es_agg_utils'; +export * from './convert_to_geojson'; +export * from './elasticsearch_geo_utils'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.test.js b/x-pack/plugins/maps/common/geo_tile_utils.test.js similarity index 96% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.test.js rename to x-pack/plugins/maps/common/geo_tile_utils.test.js index 88a6ce048a1788..ae2623e1687663 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.test.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.test.js @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../kibana_services', () => {}); - import { parseTileKey, getTileBoundingBox, expandToTileBoundaries } from './geo_tile_utils'; it('Should parse tile key', () => { diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js b/x-pack/plugins/maps/common/geo_tile_utils.ts similarity index 65% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js rename to x-pack/plugins/maps/common/geo_tile_utils.ts index 89b24522e42755..c6e35224458c52 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.ts @@ -5,18 +5,32 @@ */ import _ from 'lodash'; -import { DECIMAL_DEGREES_PRECISION } from '../../../../common/constants'; -import { clampToLatBounds } from '../../../../common/elasticsearch_geo_utils'; +import { DECIMAL_DEGREES_PRECISION } from './constants'; +import { clampToLatBounds } from './elasticsearch_util'; +import { MapExtent } from './descriptor_types'; const ZOOM_TILE_KEY_INDEX = 0; const X_TILE_KEY_INDEX = 1; const Y_TILE_KEY_INDEX = 2; -function getTileCount(zoom) { +function getTileCount(zoom: number): number { return Math.pow(2, zoom); } -export function parseTileKey(tileKey) { +export interface ESBounds { + top_left: { + lon: number; + lat: number; + }; + bottom_right: { + lon: number; + lat: number; + }; +} + +export function parseTileKey( + tileKey: string +): { x: number; y: number; zoom: number; tileCount: number } { const tileKeyParts = tileKey.split('/'); if (tileKeyParts.length !== 3) { @@ -42,7 +56,7 @@ export function parseTileKey(tileKey) { return { x, y, zoom, tileCount }; } -function sinh(x) { +function sinh(x: number): number { return (Math.exp(x) - Math.exp(-x)) / 2; } @@ -55,24 +69,52 @@ function sinh(x) { // We add one extra decimal level of precision because, at high zoom // levels rounding exactly can cause the boxes to render as uneven sizes // (some will be slightly larger and some slightly smaller) -function precisionRounding(v, minPrecision, binSize) { +function precisionRounding(v: number, minPrecision: number, binSize: number): number { let precision = Math.ceil(Math.abs(Math.log10(binSize))) + 1; precision = Math.max(precision, minPrecision); return _.round(v, precision); } -function tileToLatitude(y, tileCount) { +export function tile2long(x: number, z: number): number { + const tileCount = getTileCount(z); + return tileToLongitude(x, tileCount); +} + +export function tile2lat(y: number, z: number): number { + const tileCount = getTileCount(z); + return tileToLatitude(y, tileCount); +} + +export function tileToESBbox(x: number, y: number, z: number): ESBounds { + const wLon = tile2long(x, z); + const sLat = tile2lat(y + 1, z); + const eLon = tile2long(x + 1, z); + const nLat = tile2lat(y, z); + + return { + top_left: { + lon: wLon, + lat: nLat, + }, + bottom_right: { + lon: eLon, + lat: sLat, + }, + }; +} + +export function tileToLatitude(y: number, tileCount: number) { const radians = Math.atan(sinh(Math.PI - (2 * Math.PI * y) / tileCount)); const lat = (180 / Math.PI) * radians; return precisionRounding(lat, DECIMAL_DEGREES_PRECISION, 180 / tileCount); } -function tileToLongitude(x, tileCount) { +export function tileToLongitude(x: number, tileCount: number) { const lon = (x / tileCount) * 360 - 180; return precisionRounding(lon, DECIMAL_DEGREES_PRECISION, 360 / tileCount); } -export function getTileBoundingBox(tileKey) { +export function getTileBoundingBox(tileKey: string) { const { x, y, tileCount } = parseTileKey(tileKey); return { @@ -83,22 +125,22 @@ export function getTileBoundingBox(tileKey) { }; } -function sec(value) { +function sec(value: number): number { return 1 / Math.cos(value); } -function latitudeToTile(lat, tileCount) { +function latitudeToTile(lat: number, tileCount: number) { const radians = (clampToLatBounds(lat) * Math.PI) / 180; const y = ((1 - Math.log(Math.tan(radians) + sec(radians)) / Math.PI) / 2) * tileCount; return Math.floor(y); } -function longitudeToTile(lon, tileCount) { +function longitudeToTile(lon: number, tileCount: number) { const x = ((lon + 180) / 360) * tileCount; return Math.floor(x); } -export function expandToTileBoundaries(extent, zoom) { +export function expandToTileBoundaries(extent: MapExtent, zoom: number): MapExtent { const tileCount = getTileCount(zoom); const upperLeftX = longitudeToTile(extent.minLon, tileCount); diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 2876f3d668a69e..14d81969005068 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -40,7 +40,7 @@ import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer'; import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; -import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_geo_utils'; +import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util'; import { IVectorStyle } from '../classes/styles/vector/vector_style'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts index b00594cb7fb23f..09491e5c3a7b3e 100644 --- a/x-pack/plugins/maps/public/actions/map_actions.ts +++ b/x-pack/plugins/maps/public/actions/map_actions.ts @@ -54,7 +54,7 @@ import { MapRefreshConfig, } from '../../common/descriptor_types'; import { INITIAL_LOCATION } from '../../common/constants'; -import { scaleBounds } from '../../common/elasticsearch_geo_utils'; +import { scaleBounds } from '../../common/elasticsearch_util'; export function setMapInitError(errorMessage: string) { return { diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 7b184819b839b4..8cff98205186fc 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -12,7 +12,7 @@ import { IVectorSource } from '../sources/vector_source'; import { ESDocField } from './es_doc_field'; import { AGG_TYPE, FIELD_ORIGIN } from '../../../common/constants'; import { isMetricCountable } from '../util/is_metric_countable'; -import { getField, addFieldToDSL } from '../util/es_agg_utils'; +import { getField, addFieldToDSL } from '../../../common/elasticsearch_util'; import { TopTermPercentageField } from './top_term_percentage_field'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { ESAggTooltipProperty } from '../tooltips/es_agg_tooltip_property'; @@ -30,6 +30,7 @@ export class ESAggField implements IESAggField { private readonly _label?: string; private readonly _aggType: AGG_TYPE; private readonly _esDocField?: IField | undefined; + private readonly _canReadFromGeoJson: boolean; constructor({ label, @@ -37,18 +38,21 @@ export class ESAggField implements IESAggField { aggType, esDocField, origin, + canReadFromGeoJson = true, }: { label?: string; source: IESAggSource; aggType: AGG_TYPE; esDocField?: IField; origin: FIELD_ORIGIN; + canReadFromGeoJson?: boolean; }) { this._source = source; this._origin = origin; this._label = label; this._aggType = aggType; this._esDocField = esDocField; + this._canReadFromGeoJson = canReadFromGeoJson; } getSource(): IVectorSource { @@ -132,18 +136,19 @@ export class ESAggField implements IESAggField { } supportsAutoDomain(): boolean { - return true; + return this._canReadFromGeoJson ? true : this.supportsFieldMeta(); } canReadFromGeoJson(): boolean { - return true; + return this._canReadFromGeoJson; } } export function esAggFieldsFactory( aggDescriptor: AggDescriptor, source: IESAggSource, - origin: FIELD_ORIGIN + origin: FIELD_ORIGIN, + canReadFromGeoJson: boolean = true ): IESAggField[] { const aggField = new ESAggField({ label: aggDescriptor.label, @@ -153,12 +158,13 @@ export function esAggFieldsFactory( aggType: aggDescriptor.type, source, origin, + canReadFromGeoJson, }); const aggFields: IESAggField[] = [aggField]; if (aggDescriptor.field && aggDescriptor.type === AGG_TYPE.TERMS) { - aggFields.push(new TopTermPercentageField(aggField)); + aggFields.push(new TopTermPercentageField(aggField, canReadFromGeoJson)); } return aggFields; diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 2c190d54f02651..658c2bba878479 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -21,12 +21,12 @@ export interface IField { getOrdinalFieldMetaRequest(): Promise; getCategoricalFieldMetaRequest(size: number): Promise; - // Determines whether Maps-app can automatically determine the domain of the field-values + // Whether Maps-app can automatically determine the domain of the field-values // if this is not the case (e.g. for .mvt tiled data), // then styling properties that require the domain to be known cannot use this property. supportsAutoDomain(): boolean; - // Determinse wheter Maps-app can automatically deterime the domain of the field-values + // Whether Maps-app can automatically determine the domain of the field-values // _without_ having to retrieve the data as GeoJson // e.g. for ES-sources, this would use the extended_stats API supportsFieldMeta(): boolean; diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index fc931b13619ef3..50db04d08b2aab 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -6,16 +6,17 @@ import { IESAggField } from './es_agg_field'; import { IVectorSource } from '../sources/vector_source'; -// @ts-ignore import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; + private readonly _canReadFromGeoJson: boolean; - constructor(topTermAggField: IESAggField) { + constructor(topTermAggField: IESAggField, canReadFromGeoJson: boolean = true) { this._topTermAggField = topTermAggField; + this._canReadFromGeoJson = canReadFromGeoJson; } getSource(): IVectorSource { @@ -61,7 +62,7 @@ export class TopTermPercentageField implements IESAggField { } supportsAutoDomain(): boolean { - return true; + return this._canReadFromGeoJson; } supportsFieldMeta(): boolean { @@ -81,6 +82,6 @@ export class TopTermPercentageField implements IESAggField { } canReadFromGeoJson(): boolean { - return true; + return this._canReadFromGeoJson; } } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 8026f48fe6093b..cd720063c67031 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -423,7 +423,7 @@ export class AbstractLayer implements ILayer { renderSourceSettingsEditor({ onChange }: SourceEditorArgs) { const source = this.getSourceForEditing(); - return source.renderSourceSettingsEditor({ onChange }); + return source.renderSourceSettingsEditor({ onChange, currentLayerType: this._descriptor.type }); } getPrevRequestToken(dataId: string): symbol | undefined { diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts index a9c886617d3af8..be947d79f4e395 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts @@ -31,14 +31,25 @@ export interface IESAggSource extends IESSource { export class AbstractESAggSource extends AbstractESSource { private readonly _metricFields: IESAggField[]; + private readonly _canReadFromGeoJson: boolean; - constructor(descriptor: AbstractESAggSourceDescriptor, inspectorAdapters: Adapters) { + constructor( + descriptor: AbstractESAggSourceDescriptor, + inspectorAdapters: Adapters, + canReadFromGeoJson = true + ) { super(descriptor, inspectorAdapters); this._metricFields = []; + this._canReadFromGeoJson = canReadFromGeoJson; if (descriptor.metrics) { descriptor.metrics.forEach((aggDescriptor: AggDescriptor) => { this._metricFields.push( - ...esAggFieldsFactory(aggDescriptor, this, this.getOriginForField()) + ...esAggFieldsFactory( + aggDescriptor, + this, + this.getOriginForField(), + this._canReadFromGeoJson + ) ); }); } @@ -72,7 +83,12 @@ export class AbstractESAggSource extends AbstractESSource { const metrics = this._metricFields.filter((esAggField) => esAggField.isValid()); // Handle case where metrics is empty because older saved object state is empty array or there are no valid aggs. return metrics.length === 0 - ? esAggFieldsFactory({ type: AGG_TYPE.COUNT }, this, this.getOriginForField()) + ? esAggFieldsFactory( + { type: AGG_TYPE.COUNT }, + this, + this.getOriginForField(), + this._canReadFromGeoJson + ) : metrics; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap new file mode 100644 index 00000000000000..ca9775594a9d73 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`resolution editor should add super-fine option 1`] = ` + + + +`; + +exports[`resolution editor should omit super-fine option 1`] = ` + + + +`; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap new file mode 100644 index 00000000000000..dfce6b36396a75 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap @@ -0,0 +1,121 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`source editor geo_grid_source default vector layer config should allow super-fine option 1`] = ` + + + +
+ +
+
+ + +
+ + + +
+ +
+
+ + + +
+ +
+`; + +exports[`source editor geo_grid_source should put limitations based on heatmap-rendering selection should not allow super-fine option for heatmaps and should not allow multiple metrics 1`] = ` + + + +
+ +
+
+ + +
+ + + +
+ +
+
+ + + +
+ +
+`; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 2ce4353fca13c9..ada76b8e4e674e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -5,11 +5,17 @@ */ import { AbstractESAggSource } from '../es_agg_source'; -import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; +import { + ESGeoGridSourceDescriptor, + MapFilters, + MapQuery, + VectorSourceSyncMeta, +} from '../../../../common/descriptor_types'; import { GRID_RESOLUTION } from '../../../../common/constants'; import { IField } from '../../fields/field'; +import { ITiledSingleLayerVectorSource } from '../vector_source'; -export class ESGeoGridSource extends AbstractESAggSource { +export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingleLayerVectorSource { static createDescriptor({ indexPatternId, geoField, @@ -19,8 +25,27 @@ export class ESGeoGridSource extends AbstractESAggSource { constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); + readonly _descriptor: ESGeoGridSourceDescriptor; + getFieldNames(): string[]; getGridResolution(): GRID_RESOLUTION; getGeoGridPrecision(zoom: number): number; createField({ fieldName }: { fieldName: string }): IField; + + getLayerName(): string; + + getUrlTemplateWithMeta( + searchFilters: MapFilters & { + applyGlobalQuery: boolean; + fieldNames: string[]; + geogridPrecision?: number; + sourceQuery: MapQuery; + sourceMeta: VectorSourceSyncMeta; + } + ): Promise<{ + layerName: string; + urlTemplate: string; + minSourceZoom: number; + maxSourceZoom: number; + }>; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index aa167cb577672a..89258f04612fd1 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -7,7 +7,11 @@ import React from 'react'; import uuid from 'uuid/v4'; -import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; +import { + convertCompositeRespToGeoJson, + convertRegularRespToGeoJson, + makeESBbox, +} from '../../../../common/elasticsearch_util'; import { UpdateSourceEditor } from './update_source_editor'; import { SOURCE_TYPES, @@ -15,13 +19,20 @@ import { RENDER_AS, GRID_RESOLUTION, VECTOR_SHAPE_TYPE, + MVT_SOURCE_LAYER_NAME, + GIS_API_PATH, + MVT_GETGRIDTILE_API_PATH, + GEOTILE_GRID_AGG_NAME, + GEOCENTROID_AGG_NAME, } from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { DataRequestAbortError } from '../../util/data_request'; import { registerSource } from '../source_registry'; -import { makeESBbox } from '../../../../common/elasticsearch_geo_utils'; + +import rison from 'rison-node'; +import { getHttp } from '../../../kibana_services'; export const MAX_GEOTILE_LEVEL = 29; @@ -48,9 +59,14 @@ export class ESGeoGridSource extends AbstractESAggSource { }; } - renderSourceSettingsEditor({ onChange }) { + constructor(descriptor, inspectorAdapters) { + super(descriptor, inspectorAdapters, descriptor.resolution !== GRID_RESOLUTION.SUPER_FINE); + } + + renderSourceSettingsEditor({ onChange, currentLayerType }) { return ( { @@ -96,59 +99,67 @@ describe('ESGeoGridSource', () => { }; }; - describe('getGeoJsonWithMeta', () => { - let mockSearchSource: unknown; - beforeEach(async () => { - mockSearchSource = new MockSearchSource(); - const mockSearchService = { - searchSource: { - async create() { - return mockSearchSource as SearchSource; - }, - createEmpty() { - return mockSearchSource as SearchSource; - }, + let mockSearchSource: unknown; + beforeEach(async () => { + mockSearchSource = new MockSearchSource(); + const mockSearchService = { + searchSource: { + async create() { + return mockSearchSource as SearchSource; }, - }; + createEmpty() { + return mockSearchSource as SearchSource; + }, + }, + }; - // @ts-expect-error - getIndexPatternService.mockReturnValue(mockIndexPatternService); - // @ts-expect-error - getSearchService.mockReturnValue(mockSearchService); + // @ts-expect-error + getIndexPatternService.mockReturnValue(mockIndexPatternService); + // @ts-expect-error + getSearchService.mockReturnValue(mockSearchService); + // @ts-expect-error + getHttp.mockReturnValue({ + basePath: { + prepend(path: string) { + return `rootdir${path};`; + }, + }, }); + }); - const extent: MapExtent = { - minLon: -160, - minLat: -80, - maxLon: 160, - maxLat: 80, - }; + const extent: MapExtent = { + minLon: -160, + minLat: -80, + maxLon: 160, + maxLat: 80, + }; - const mapFilters: VectorSourceRequestMeta = { - geogridPrecision: 4, - filters: [], - timeFilters: { - from: 'now', - to: '15m', - mode: 'relative', - }, - extent, - applyGlobalQuery: true, - fieldNames: [], - buffer: extent, - sourceQuery: { - query: '', - language: 'KQL', - queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', - }, - sourceMeta: null, - zoom: 0, - }; + const vectorSourceRequestMeta: VectorSourceRequestMeta = { + geogridPrecision: 4, + filters: [], + timeFilters: { + from: 'now', + to: '15m', + mode: 'relative', + }, + extent, + applyGlobalQuery: true, + fieldNames: [], + buffer: extent, + sourceQuery: { + query: '', + language: 'KQL', + queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', + }, + sourceMeta: null, + zoom: 0, + }; + describe('getGeoJsonWithMeta', () => { it('Should configure the SearchSource correctly', async () => { const { data, meta } = await geogridSource.getGeoJsonWithMeta( 'foobarLayer', - mapFilters, + vectorSourceRequestMeta, () => {} ); @@ -215,5 +226,48 @@ describe('ESGeoGridSource', () => { it('should use heuristic to derive precision', () => { expect(geogridSource.getGeoGridPrecision(10)).toBe(12); }); + + it('Should not return valid precision for super-fine resolution', () => { + const superFineSource = new ESGeoGridSource( + { + id: 'foobar', + indexPatternId: 'fooIp', + geoField: geoFieldName, + metrics: [], + resolution: GRID_RESOLUTION.SUPER_FINE, + type: SOURCE_TYPES.ES_GEO_GRID, + requestType: RENDER_AS.HEATMAP, + }, + {} + ); + expect(superFineSource.getGeoGridPrecision(10)).toBe(NaN); + }); + }); + + describe('ITiledSingleLayerVectorSource', () => { + it('getLayerName', () => { + expect(geogridSource.getLayerName()).toBe('source_layer'); + }); + + it('getMinZoom', () => { + expect(geogridSource.getMinZoom()).toBe(0); + }); + + it('getMaxZoom', () => { + expect(geogridSource.getMaxZoom()).toBe(24); + }); + + it('getUrlTemplateWithMeta', async () => { + const urlTemplateWithMeta = await geogridSource.getUrlTemplateWithMeta( + vectorSourceRequestMeta + ); + + expect(urlTemplateWithMeta.layerName).toBe('source_layer'); + expect(urlTemplateWithMeta.minSourceZoom).toBe(0); + expect(urlTemplateWithMeta.maxSourceZoom).toBe(24); + expect(urlTemplateWithMeta.urlTemplate).toBe( + "rootdir/api/maps/mvt/getGridTile;?x={x}&y={y}&z={z}&geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!((geo_bounding_box:(bar:(bottom_right:!(180,-82.67628),top_left:!(-180,82.67628)))))),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point" + ); + }); }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js index 28c24f58a0efcf..71133cb25280c7 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js @@ -9,7 +9,7 @@ import { GRID_RESOLUTION } from '../../../../common/constants'; import { EuiSelect, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -const OPTIONS = [ +const BASE_OPTIONS = [ { value: GRID_RESOLUTION.COARSE, text: i18n.translate('xpack.maps.source.esGrid.coarseDropdownOption', { @@ -30,7 +30,18 @@ const OPTIONS = [ }, ]; -export function ResolutionEditor({ resolution, onChange }) { +export function ResolutionEditor({ resolution, onChange, includeSuperFine }) { + const options = [...BASE_OPTIONS]; + + if (includeSuperFine) { + options.push({ + value: GRID_RESOLUTION.SUPER_FINE, + text: i18n.translate('xpack.maps.source.esGrid.superFineDropDownOption', { + defaultMessage: 'super fine (beta)', + }), + }); + } + return ( onChange(e.target.value)} compressed diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx new file mode 100644 index 00000000000000..369203dbe16c0f --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +// @ts-expect-error +import { ResolutionEditor } from './resolution_editor'; +import { GRID_RESOLUTION } from '../../../../common/constants'; + +const defaultProps = { + resolution: GRID_RESOLUTION.COARSE, + onChange: () => {}, + includeSuperFine: false, +}; + +describe('resolution editor', () => { + test('should omit super-fine option', () => { + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + test('should add super-fine option', () => { + const component = shallow(); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js index ac7d809c40f61b..7e885c291b952e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js @@ -6,7 +6,7 @@ import React, { Fragment, Component } from 'react'; -import { RENDER_AS } from '../../../../common/constants'; +import { GRID_RESOLUTION, LAYER_TYPE } from '../../../../common/constants'; import { MetricsEditor } from '../../../components/metrics_editor'; import { getIndexPatternService } from '../../../kibana_services'; import { ResolutionEditor } from './resolution_editor'; @@ -62,8 +62,25 @@ export class UpdateSourceEditor extends Component { this.props.onChange({ propName: 'metrics', value: metrics }); }; - _onResolutionChange = (e) => { - this.props.onChange({ propName: 'resolution', value: e }); + _onResolutionChange = (resolution) => { + let newLayerType; + if ( + this.props.currentLayerType === LAYER_TYPE.VECTOR || + this.props.currentLayerType === LAYER_TYPE.TILED_VECTOR + ) { + newLayerType = + resolution === GRID_RESOLUTION.SUPER_FINE ? LAYER_TYPE.TILED_VECTOR : LAYER_TYPE.VECTOR; + } else if (this.props.currentLayerType === LAYER_TYPE.HEATMAP) { + if (resolution === GRID_RESOLUTION.SUPER_FINE) { + throw new Error('Heatmap does not support SUPER_FINE resolution'); + } else { + newLayerType = LAYER_TYPE.HEATMAP; + } + } else { + throw new Error('Unexpected layer-type'); + } + + this.props.onChange({ propName: 'resolution', value: resolution, newLayerType }); }; _onRequestTypeSelect = (requestType) => { @@ -72,13 +89,13 @@ export class UpdateSourceEditor extends Component { _renderMetricsPanel() { const metricsFilter = - this.props.renderAs === RENDER_AS.HEATMAP + this.props.currentLayerType === LAYER_TYPE.HEATMAP ? (metric) => { //these are countable metrics, where blending heatmap color blobs make sense return isMetricCountable(metric.value); } : null; - const allowMultipleMetrics = this.props.renderAs !== RENDER_AS.HEATMAP; + const allowMultipleMetrics = this.props.currentLayerType !== LAYER_TYPE.HEATMAP; return ( @@ -115,6 +132,7 @@ export class UpdateSourceEditor extends Component { diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx new file mode 100644 index 00000000000000..ceb79230bc8320 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +// @ts-expect-error +import { UpdateSourceEditor } from './update_source_editor'; +import { GRID_RESOLUTION, LAYER_TYPE, RENDER_AS } from '../../../../common/constants'; + +const defaultProps = { + currentLayerType: LAYER_TYPE.VECTOR, + indexPatternId: 'foobar', + onChange: () => {}, + metrics: [], + renderAs: RENDER_AS.POINT, + resolution: GRID_RESOLUTION.COARSE, +}; + +describe('source editor geo_grid_source', () => { + describe('default vector layer config', () => { + test('should allow super-fine option', async () => { + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + }); + + describe('should put limitations based on heatmap-rendering selection', () => { + test('should not allow super-fine option for heatmaps and should not allow multiple metrics', async () => { + const component = shallow( + + ); + expect(component).toMatchSnapshot(); + }); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js index 96a7f50cdf523a..24ac6d31bc6456 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; +import { extractPropertiesFromBucket } from '../../../../common/elasticsearch_util'; const LAT_INDEX = 0; const LON_INDEX = 1; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js index 9ec54335d4e785..0360208ef83707 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js @@ -16,7 +16,7 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { convertToLines } from './convert_to_lines'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { registerSource } from '../source_registry'; -import { turfBboxToBounds } from '../../../../common/elasticsearch_geo_utils'; +import { turfBboxToBounds } from '../../../../common/elasticsearch_util'; import { DataRequestAbortError } from '../../util/data_request'; const MAX_GEOTILE_LEVEL = 29; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js index df83bd1cf5e608..edcafae54d54ca 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js @@ -10,7 +10,7 @@ import rison from 'rison-node'; import { AbstractESSource } from '../es_source'; import { getSearchService, getHttp } from '../../../kibana_services'; -import { hitsToGeoJson } from '../../../../common/elasticsearch_geo_utils'; +import { hitsToGeoJson, getField, addFieldToDSL } from '../../../../common/elasticsearch_util'; import { UpdateSourceEditor } from './update_source_editor'; import { SOURCE_TYPES, @@ -31,7 +31,7 @@ import uuid from 'uuid/v4'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { ESDocField } from '../../fields/es_doc_field'; -import { getField, addFieldToDSL } from '../../util/es_agg_utils'; + import { registerSource } from '../source_registry'; export const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', { diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js index d51ca46fd98fff..ab56ceeab4e771 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js @@ -11,14 +11,14 @@ import { getTimeFilter, getSearchService, } from '../../../kibana_services'; -import { createExtentFilter } from '../../../../common/elasticsearch_geo_utils'; +import { createExtentFilter } from '../../../../common/elasticsearch_util'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; import { copyPersistentState } from '../../../reducers/util'; import { DataRequestAbortError } from '../../util/data_request'; -import { expandToTileBoundaries } from '../es_geo_grid_source/geo_tile_utils'; +import { expandToTileBoundaries } from '../../../../common/geo_tile_utils'; import { search } from '../../../../../../../src/plugins/data/public'; export class AbstractESSource extends AbstractVectorSource { diff --git a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js index b4ad256c1598af..359d22d2c44ce7 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js @@ -16,7 +16,11 @@ import { import { getJoinAggKey } from '../../../../common/get_agg_key'; import { ESDocField } from '../../fields/es_doc_field'; import { AbstractESAggSource } from '../es_agg_source'; -import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../../util/es_agg_utils'; +import { + getField, + addFieldToDSL, + extractPropertiesFromBucket, +} from '../../../../common/elasticsearch_util'; const TERMS_AGG_NAME = 'join'; diff --git a/x-pack/plugins/maps/public/classes/sources/source.ts b/x-pack/plugins/maps/public/classes/sources/source.ts index 7e7a7bd8f049dd..946381817b8fc4 100644 --- a/x-pack/plugins/maps/public/classes/sources/source.ts +++ b/x-pack/plugins/maps/public/classes/sources/source.ts @@ -18,6 +18,7 @@ import { OnSourceChangeArgs } from '../../connected_components/layer_panel/view' export type SourceEditorArgs = { onChange: (...args: OnSourceChangeArgs[]) => void; + currentLayerType?: string; }; export type ImmutableSourceProperty = { @@ -50,7 +51,7 @@ export interface ISource { getImmutableProperties(): Promise; getAttributions(): Promise; isESSource(): boolean; - renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null; + renderSourceSettingsEditor(sourceEditorArgs: SourceEditorArgs): ReactElement | null; supportsFitToBounds(): Promise; showJoinEditor(): boolean; getJoinsDisabledReason(): string | null; @@ -126,7 +127,7 @@ export class AbstractSource implements ISource { return []; } - renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null { + renderSourceSettingsEditor(sourceEditorArgs: SourceEditorArgs): ReactElement | null { return null; } diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx index a3002251785269..c75698805225f1 100644 --- a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx @@ -86,6 +86,7 @@ export class HeatmapStyle implements IStyle { } else if (resolution === GRID_RESOLUTION.MOST_FINE) { radius = 32; } else { + // SUPER_FINE or any other is not supported. const errorMessage = i18n.translate('xpack.maps.style.heatmap.resolutionStyleErrorMessage', { defaultMessage: `Resolution param not recognized: {resolution}`, values: { resolution }, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts index d190a62e6f300a..49d6ccdeb9316d 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { MB_LOOKUP_FUNCTION, VECTOR_SHAPE_TYPE } from '../../../../common/constants'; +import { MB_LOOKUP_FUNCTION, VECTOR_SHAPE_TYPE, VECTOR_STYLES } from '../../../../common/constants'; import { Category } from '../../../../common/descriptor_types'; export function getOtherCategoryLabel() { @@ -14,8 +14,8 @@ export function getOtherCategoryLabel() { }); } -export function getComputedFieldName(styleName: string, fieldName: string) { - return `${getComputedFieldNamePrefix(fieldName)}__${styleName}`; +export function getComputedFieldName(styleName: VECTOR_STYLES, fieldName: string) { + return `${getComputedFieldNamePrefix(fieldName)}__${styleName as string}`; } export function getComputedFieldNamePrefix(fieldName: string) { diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js index 98267965fd30fb..33a0f1c5bf0884 100644 --- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js +++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import { i18n } from '@kbn/i18n'; import { URL_MAX_LENGTH } from '../../../../../../../src/core/public'; -import { createSpatialFilterWithGeometry } from '../../../../common/elasticsearch_geo_utils'; +import { createSpatialFilterWithGeometry } from '../../../../common/elasticsearch_util'; import { GEO_JSON_TYPE } from '../../../../common/constants'; import { GeometryFilterForm } from '../../../components/geometry_filter_form'; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js index 49675ac6a39243..0356a8267c18af 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js @@ -15,7 +15,7 @@ import { createSpatialFilterWithGeometry, getBoundingBoxGeometry, roundCoordinates, -} from '../../../../../common/elasticsearch_geo_utils'; +} from '../../../../../common/elasticsearch_util'; import { DrawTooltip } from './draw_tooltip'; const DRAW_RECTANGLE = 'draw_rectangle'; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/plugins/maps/public/connected_components/map/mb/view.js index eede1edf40cc4f..ddc48cfc9c329b 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/view.js @@ -23,7 +23,7 @@ import sprites1 from '@elastic/maki/dist/sprite@1.png'; import sprites2 from '@elastic/maki/dist/sprite@2.png'; import { DrawControl } from './draw_control'; import { TooltipControl } from './tooltip_control'; -import { clampToLatBounds, clampToLonBounds } from '../../../../common/elasticsearch_geo_utils'; +import { clampToLatBounds, clampToLonBounds } from '../../../../common/elasticsearch_util'; import { getInitialView } from './get_initial_view'; import { getPreserveDrawingBuffer } from '../../../kibana_services'; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx index 47f41f2b76f3ef..8a0eb8db4d7aa0 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx @@ -67,17 +67,17 @@ export function getTopNavConfig({ savedMap.description = newDescription; savedMap.copyOnSave = newCopyOnSave; - let id; + let savedObjectId; try { savedMap.syncWithStore(); - id = await savedMap.save({ + savedObjectId = await savedMap.save({ confirmOverwrite: false, isTitleDuplicateConfirmed, onTitleDuplicate, }); // id not returned when save fails because of duplicate title check. // return and let user confirm duplicate title. - if (!id) { + if (!savedObjectId) { return {}; } } catch (err) { @@ -105,7 +105,7 @@ export function getTopNavConfig({ getCoreChrome().docTitle.change(savedMap.title); setBreadcrumbs(); - goToSpecifiedPath(`/map/${id}${window.location.hash}`); + goToSpecifiedPath(`/map/${savedObjectId}${window.location.hash}`); const newlyCreated = newCopyOnSave || isNewMap; if (newlyCreated && !returnToOrigin) { @@ -113,14 +113,14 @@ export function getTopNavConfig({ } else if (!!originatingApp && returnToOrigin) { if (newlyCreated && stateTransfer) { stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { - state: { id, type: MAP_SAVED_OBJECT_TYPE }, + state: { input: { savedObjectId }, type: MAP_SAVED_OBJECT_TYPE }, }); } else { getNavigateToApp()(originatingApp); } } - return { id }; + return { id: savedObjectId }; } if (hasSaveAndReturnConfig) { diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 03e0f753812c9f..db4371e9cd590f 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -31,7 +31,7 @@ import { SPATIAL_FILTERS_LAYER_ID, } from '../../common/constants'; // @ts-ignore -import { extractFeaturesFromFilters } from '../../common/elasticsearch_geo_utils'; +import { extractFeaturesFromFilters } from '../../common/elasticsearch_util'; import { MapStoreState } from '../reducers/store'; import { DataRequestDescriptor, diff --git a/x-pack/plugins/maps/server/mvt/__tests__/json/0_0_0_gridagg.json b/x-pack/plugins/maps/server/mvt/__tests__/json/0_0_0_gridagg.json new file mode 100644 index 00000000000000..0945dc57fa5122 --- /dev/null +++ b/x-pack/plugins/maps/server/mvt/__tests__/json/0_0_0_gridagg.json @@ -0,0 +1 @@ +{"took":2,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":10000,"relation":"gte"},"max_score":null,"hits":[]},"aggregations":{"gridSplit":{"buckets":[{"key":"7/37/48","doc_count":42637,"avg_of_TOTAL_AV":{"value":5398920.390458991},"gridCentroid":{"location":{"lat":40.77936432658204,"lon":-73.96795676049909},"count":42637}}]}}} diff --git a/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0.pbf b/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_docs.pbf similarity index 100% rename from x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0.pbf rename to x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_docs.pbf diff --git a/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_grid_asgrid.pbf b/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_grid_asgrid.pbf new file mode 100644 index 00000000000000..f2289865b80229 Binary files /dev/null and b/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_grid_asgrid.pbf differ diff --git a/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_grid_aspoint.pbf b/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_grid_aspoint.pbf new file mode 100644 index 00000000000000..54b0791ccd1361 Binary files /dev/null and b/x-pack/plugins/maps/server/mvt/__tests__/pbf/0_0_0_grid_aspoint.pbf differ diff --git a/x-pack/plugins/maps/server/mvt/__tests__/tile_searches.ts b/x-pack/plugins/maps/server/mvt/__tests__/tile_es_responses.ts similarity index 57% rename from x-pack/plugins/maps/server/mvt/__tests__/tile_searches.ts rename to x-pack/plugins/maps/server/mvt/__tests__/tile_es_responses.ts index 317d6434cf81ef..9fbaba21e71d58 100644 --- a/x-pack/plugins/maps/server/mvt/__tests__/tile_searches.ts +++ b/x-pack/plugins/maps/server/mvt/__tests__/tile_es_responses.ts @@ -7,10 +7,6 @@ import * as path from 'path'; import * as fs from 'fs'; -const search000path = path.resolve(__dirname, './json/0_0_0_search.json'); -const search000raw = fs.readFileSync(search000path); -const search000json = JSON.parse((search000raw as unknown) as string); - export const TILE_SEARCHES = { '0.0.0': { countResponse: { @@ -22,7 +18,18 @@ export const TILE_SEARCHES = { failed: 0, }, }, - searchResponse: search000json, + searchResponse: loadJson('./json/0_0_0_search.json'), + }, +}; + +export const TILE_GRIDAGGS = { + '0.0.0': { + gridAggResponse: loadJson('./json/0_0_0_gridagg.json'), }, - '1.1.0': {}, }; + +function loadJson(filePath: string) { + const absolutePath = path.resolve(__dirname, filePath); + const rawContents = fs.readFileSync(absolutePath); + return JSON.parse((rawContents as unknown) as string); +} diff --git a/x-pack/plugins/maps/server/mvt/get_tile.test.ts b/x-pack/plugins/maps/server/mvt/get_tile.test.ts index b9c928d594539c..76c1741ab2ad09 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.test.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.test.ts @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getTile } from './get_tile'; -import { TILE_SEARCHES } from './__tests__/tile_searches'; +import { getGridTile, getTile } from './get_tile'; +import { TILE_GRIDAGGS, TILE_SEARCHES } from './__tests__/tile_es_responses'; import { Logger } from 'src/core/server'; import * as path from 'path'; import * as fs from 'fs'; +import { ES_GEO_FIELD_TYPE, RENDER_AS } from '../../common/constants'; describe('getTile', () => { const mockCallElasticsearch = jest.fn(); @@ -51,13 +52,84 @@ describe('getTile', () => { callElasticsearch: mockCallElasticsearch, }); - if (tile === null) { - throw new Error('Tile should be created'); - } + compareTiles('./__tests__/pbf/0_0_0_docs.pbf', tile); + }); +}); + +describe('getGridTile', () => { + const mockCallElasticsearch = jest.fn(); + + const geometryFieldName = 'geometry'; + + // For mock-purposes only. The ES-call response is mocked in 0_0_0_gridagg.json file + const requestBody = { + _source: { excludes: [] }, + aggs: { + gridSplit: { + aggs: { + // eslint-disable-next-line @typescript-eslint/naming-convention + avg_of_TOTAL_AV: { avg: { field: 'TOTAL_AV' } }, + gridCentroid: { geo_centroid: { field: geometryFieldName } }, + }, + geotile_grid: { + bounds: null, + field: geometryFieldName, + precision: null, + shard_size: 65535, + size: 65535, + }, + }, + }, + docvalue_fields: [], + query: { + bool: { + filter: [], + }, + }, + script_fields: {}, + size: 0, + stored_fields: ['*'], + }; - const expectedPath = path.resolve(__dirname, './__tests__/pbf/0_0_0.pbf'); - const expectedBin = fs.readFileSync(expectedPath, 'binary'); - const expectedTile = Buffer.from(expectedBin, 'binary'); - expect(expectedTile.equals(tile)).toBe(true); + beforeEach(() => { + mockCallElasticsearch.mockReset(); + mockCallElasticsearch.mockImplementation((type) => { + return TILE_GRIDAGGS['0.0.0'].gridAggResponse; + }); + }); + + const defaultParams = { + x: 0, + y: 0, + z: 0, + index: 'manhattan', + requestBody, + geometryFieldName, + logger: ({ + info: () => {}, + } as unknown) as Logger, + callElasticsearch: mockCallElasticsearch, + requestType: RENDER_AS.POINT, + geoFieldType: ES_GEO_FIELD_TYPE.GEO_POINT, + }; + + test('0.0.0 tile (clusters)', async () => { + const tile = await getGridTile(defaultParams); + compareTiles('./__tests__/pbf/0_0_0_grid_aspoint.pbf', tile); + }); + + test('0.0.0 tile (grids)', async () => { + const tile = await getGridTile({ ...defaultParams, requestType: RENDER_AS.GRID }); + compareTiles('./__tests__/pbf/0_0_0_grid_asgrid.pbf', tile); }); }); + +function compareTiles(expectedRelativePath: string, actualTile: Buffer | null) { + if (actualTile === null) { + throw new Error('Tile should be created'); + } + const expectedPath = path.resolve(__dirname, expectedRelativePath); + const expectedBin = fs.readFileSync(expectedPath, 'binary'); + const expectedTile = Buffer.from(expectedBin, 'binary'); + expect(expectedTile.equals(actualTile)).toBe(true); +} diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 9621f7f174a306..dd88be7f80c2ea 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -13,22 +13,89 @@ import { Feature, FeatureCollection, Polygon } from 'geojson'; import { ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, + GEOTILE_GRID_AGG_NAME, KBN_TOO_MANY_FEATURES_PROPERTY, + MAX_ZOOM, MVT_SOURCE_LAYER_NAME, + RENDER_AS, + SUPER_FINE_ZOOM_DELTA, } from '../../common/constants'; -import { hitsToGeoJson } from '../../common/elasticsearch_geo_utils'; +import { hitsToGeoJson } from '../../common/elasticsearch_util'; import { flattenHit } from './util'; +import { convertRegularRespToGeoJson } from '../../common/elasticsearch_util'; +import { ESBounds, tile2lat, tile2long, tileToESBbox } from '../../common/geo_tile_utils'; -interface ESBounds { - top_left: { - lon: number; - lat: number; - }; - bottom_right: { - lon: number; - lat: number; - }; +export async function getGridTile({ + logger, + callElasticsearch, + index, + geometryFieldName, + x, + y, + z, + requestBody = {}, + requestType = RENDER_AS.POINT, + geoFieldType = ES_GEO_FIELD_TYPE.GEO_POINT, +}: { + x: number; + y: number; + z: number; + geometryFieldName: string; + index: string; + callElasticsearch: (type: string, ...args: any[]) => Promise; + logger: Logger; + requestBody: any; + requestType: RENDER_AS; + geoFieldType: ES_GEO_FIELD_TYPE; +}): Promise { + const esBbox: ESBounds = tileToESBbox(x, y, z); + try { + let bboxFilter; + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { + bboxFilter = { + geo_bounding_box: { + [geometryFieldName]: esBbox, + }, + }; + } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { + const geojsonPolygon = tileToGeoJsonPolygon(x, y, z); + bboxFilter = { + geo_shape: { + [geometryFieldName]: { + shape: geojsonPolygon, + relation: 'INTERSECTS', + }, + }, + }; + } else { + throw new Error(`${geoFieldType} is not valid geo field-type`); + } + requestBody.query.bool.filter.push(bboxFilter); + + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = Math.min( + z + SUPER_FINE_ZOOM_DELTA, + MAX_ZOOM + ); + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; + + const esGeotileGridQuery = { + index, + body: requestBody, + }; + + const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); + const features: Feature[] = convertRegularRespToGeoJson(gridAggResult, requestType); + const featureCollection: FeatureCollection = { + features, + type: 'FeatureCollection', + }; + + return createMvtTile(featureCollection, z, x, y); + } catch (e) { + logger.warn(`Cannot generate grid-tile for ${z}/${x}/${y}: ${e.message}`); + return null; + } } export async function getTile({ @@ -149,26 +216,7 @@ export async function getTile({ type: 'FeatureCollection', }; - const tileIndex = geojsonvt(featureCollection, { - maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 - tolerance: 3, // simplification tolerance (higher means simpler) - extent: 4096, // tile extent (both width and height) - buffer: 64, // tile buffer on each side - debug: 0, // logging level (0 to disable, 1 or 2) - lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features - promoteId: null, // name of a feature property to promote to feature.id. Cannot be used with `generateId` - generateId: false, // whether to generate feature ids. Cannot be used with `promoteId` - indexMaxZoom: 5, // max zoom in the initial tile index - indexMaxPoints: 100000, // max number of points per tile in the index - }); - const tile = tileIndex.getTile(z, x, y); - - if (tile) { - const pbf = vtpbf.fromGeojsonVt({ [MVT_SOURCE_LAYER_NAME]: tile }, { version: 2 }); - return Buffer.from(pbf); - } else { - return null; - } + return createMvtTile(featureCollection, z, x, y); } catch (e) { logger.warn(`Cannot generate tile for ${z}/${x}/${y}: ${e.message}`); return null; @@ -195,15 +243,6 @@ function tileToGeoJsonPolygon(x: number, y: number, z: number): Polygon { }; } -function tile2long(x: number, z: number): number { - return (x / Math.pow(2, z)) * 360 - 180; -} - -function tile2lat(y: number, z: number): number { - const n = Math.PI - (2 * Math.PI * y) / Math.pow(2, z); - return (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); -} - function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { let minLon = esBounds.top_left.lon; const maxLon = esBounds.bottom_right.lon; @@ -224,3 +263,31 @@ function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { ], }; } + +function createMvtTile( + featureCollection: FeatureCollection, + z: number, + x: number, + y: number +): Buffer | null { + const tileIndex = geojsonvt(featureCollection, { + maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 + tolerance: 3, // simplification tolerance (higher means simpler) + extent: 4096, // tile extent (both width and height) + buffer: 64, // tile buffer on each side + debug: 0, // logging level (0 to disable, 1 or 2) + lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features + promoteId: null, // name of a feature property to promote to feature.id. Cannot be used with `generateId` + generateId: false, // whether to generate feature ids. Cannot be used with `promoteId` + indexMaxZoom: 5, // max zoom in the initial tile index + indexMaxPoints: 100000, // max number of points per tile in the index + }); + const tile = tileIndex.getTile(z, x, y); + + if (tile) { + const pbf = vtpbf.fromGeojsonVt({ [MVT_SOURCE_LAYER_NAME]: tile }, { version: 2 }); + return Buffer.from(pbf); + } else { + return null; + } +} diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 32c14a355ba2a1..266a240b530172 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -6,10 +6,21 @@ import rison from 'rison-node'; import { schema } from '@kbn/config-schema'; -import { Logger } from 'src/core/server'; +import { + KibanaRequest, + KibanaResponseFactory, + Logger, + RequestHandlerContext, +} from 'src/core/server'; import { IRouter } from 'src/core/server'; -import { MVT_GETTILE_API_PATH, API_ROOT_PATH } from '../../common/constants'; -import { getTile } from './get_tile'; +import { + MVT_GETTILE_API_PATH, + API_ROOT_PATH, + MVT_GETGRIDTILE_API_PATH, + ES_GEO_FIELD_TYPE, + RENDER_AS, +} from '../../common/constants'; +import { getGridTile, getTile } from './get_tile'; const CACHE_TIMEOUT = 0; // Todo. determine good value. Unsure about full-implications (e.g. wrt. time-based data). @@ -28,46 +39,93 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }), }, }, - async (context, request, response) => { + async ( + context: RequestHandlerContext, + request: KibanaRequest, unknown>, + response: KibanaResponseFactory + ) => { const { query } = request; + const requestBodyDSL = rison.decode(query.requestBody as string); - const callElasticsearch = async (type: string, ...args: any[]): Promise => { - return await context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); - }; + const tile = await getTile({ + logger, + callElasticsearch: makeCallElasticsearch(context), + geometryFieldName: query.geometryFieldName as string, + x: query.x as number, + y: query.y as number, + z: query.z as number, + index: query.index as string, + requestBody: requestBodyDSL as any, + }); - const requestBodyDSL = rison.decode(query.requestBody); + return sendResponse(response, tile); + } + ); - const tile = await getTile({ + router.get( + { + path: `${API_ROOT_PATH}/${MVT_GETGRIDTILE_API_PATH}`, + validate: { + query: schema.object({ + x: schema.number(), + y: schema.number(), + z: schema.number(), + geometryFieldName: schema.string(), + requestBody: schema.string(), + index: schema.string(), + requestType: schema.string(), + geoFieldType: schema.string(), + }), + }, + }, + async ( + context: RequestHandlerContext, + request: KibanaRequest, unknown>, + response: KibanaResponseFactory + ) => { + const { query } = request; + const requestBodyDSL = rison.decode(query.requestBody as string); + + const tile = await getGridTile({ logger, - callElasticsearch, - geometryFieldName: query.geometryFieldName, - x: query.x, - y: query.y, - z: query.z, - index: query.index, - requestBody: requestBodyDSL, + callElasticsearch: makeCallElasticsearch(context), + geometryFieldName: query.geometryFieldName as string, + x: query.x as number, + y: query.y as number, + z: query.z as number, + index: query.index as string, + requestBody: requestBodyDSL as any, + requestType: query.requestType as RENDER_AS, + geoFieldType: query.geoFieldType as ES_GEO_FIELD_TYPE, }); - if (tile) { - return response.ok({ - body: tile, - headers: { - 'content-disposition': 'inline', - 'content-length': `${tile.length}`, - 'Content-Type': 'application/x-protobuf', - 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - }, - }); - } else { - return response.ok({ - headers: { - 'content-disposition': 'inline', - 'content-length': '0', - 'Content-Type': 'application/x-protobuf', - 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - }, - }); - } + return sendResponse(response, tile); } ); } + +function sendResponse(response: KibanaResponseFactory, tile: any) { + const headers = { + 'content-disposition': 'inline', + 'content-length': tile ? `${tile.length}` : `0`, + 'Content-Type': 'application/x-protobuf', + 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, + }; + + if (tile) { + return response.ok({ + body: tile, + headers, + }); + } else { + return response.ok({ + headers, + }); + } +} + +function makeCallElasticsearch(context: RequestHandlerContext) { + return async (type: string, ...args: any[]): Promise => { + return context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); + }; +} diff --git a/x-pack/plugins/monitoring/public/angular/app_modules.ts b/x-pack/plugins/monitoring/public/angular/app_modules.ts index 499610045d7717..4ef905fd35fc4a 100644 --- a/x-pack/plugins/monitoring/public/angular/app_modules.ts +++ b/x-pack/plugins/monitoring/public/angular/app_modules.ts @@ -41,10 +41,6 @@ import { licenseProvider } from '../services/license'; // @ts-ignore import { titleProvider } from '../services/title'; // @ts-ignore -import { monitoringBeatsBeatProvider } from '../directives/beats/beat'; -// @ts-ignore -import { monitoringBeatsOverviewProvider } from '../directives/beats/overview'; -// @ts-ignore import { monitoringMlListingProvider } from '../directives/elasticsearch/ml_job_listing'; // @ts-ignore import { monitoringMainProvider } from '../directives/main'; @@ -153,8 +149,6 @@ function createMonitoringAppServices() { function createMonitoringAppDirectives() { angular .module('monitoring/directives', []) - .directive('monitoringBeatsBeat', monitoringBeatsBeatProvider) - .directive('monitoringBeatsOverview', monitoringBeatsOverviewProvider) .directive('monitoringMlListing', monitoringMlListingProvider) .directive('monitoringMain', monitoringMainProvider); } diff --git a/x-pack/plugins/monitoring/public/components/apm/instance/instance.js b/x-pack/plugins/monitoring/public/components/apm/instance/instance.js index 396d2258edd0c8..eec24e741ac416 100644 --- a/x-pack/plugins/monitoring/public/components/apm/instance/instance.js +++ b/x-pack/plugins/monitoring/public/components/apm/instance/instance.js @@ -42,9 +42,7 @@ export function ApmServerInstance({ summary, metrics, ...props }) { const charts = seriesToShow.map((data, index) => ( - - - + )); @@ -55,15 +53,15 @@ export function ApmServerInstance({ summary, metrics, ...props }) {

+ + + + - - - - {charts} diff --git a/x-pack/plugins/monitoring/public/components/apm/instances/instances.js b/x-pack/plugins/monitoring/public/components/apm/instances/instances.js index 6dcfa6dd043aaf..e05ba1878caed7 100644 --- a/x-pack/plugins/monitoring/public/components/apm/instances/instances.js +++ b/x-pack/plugins/monitoring/public/components/apm/instances/instances.js @@ -156,11 +156,11 @@ export function ApmServerInstances({ apms, setupMode }) { /> + + + + - - - - {setupModeCallout} ( - - - + )); @@ -51,15 +49,15 @@ export function ApmOverview({ stats, metrics, ...props }) {

+ + + + - - - - {charts} diff --git a/x-pack/plugins/monitoring/public/components/beats/beat/beat.js b/x-pack/plugins/monitoring/public/components/beats/beat/beat.js index 3fe211c0f2edc4..f489271659bfe1 100644 --- a/x-pack/plugins/monitoring/public/components/beats/beat/beat.js +++ b/x-pack/plugins/monitoring/public/components/beats/beat/beat.js @@ -135,6 +135,9 @@ export function Beat({ summary, metrics, ...props }) { + + + diff --git a/x-pack/plugins/monitoring/public/components/beats/listing/listing.js b/x-pack/plugins/monitoring/public/components/beats/listing/listing.js index be8595e8e6bbe5..60a35e00a4c636 100644 --- a/x-pack/plugins/monitoring/public/components/beats/listing/listing.js +++ b/x-pack/plugins/monitoring/public/components/beats/listing/listing.js @@ -13,6 +13,7 @@ import { EuiSpacer, EuiLink, EuiScreenReaderOnly, + EuiPanel, } from '@elastic/eui'; import { Stats } from '../../beats'; import { formatMetric } from '../../../lib/format_number'; @@ -153,9 +154,11 @@ export class Listing extends PureComponent { /> - + - + + + {setupModeCallOut} - + + + + - - -

- -

-
- - -
+ +

+ +

+
+ +
- - -

- -

-
- - -
+ +

+ +

+
+ +
- - -

- -

-
- - -
+ +

+ +

+
+ +
- +
+ + @@ -212,18 +213,25 @@ exports[`Overview that overview page shows a message if there is no beats data 1 /> - + + + + - + + + diff --git a/x-pack/plugins/monitoring/public/components/beats/overview/overview.js b/x-pack/plugins/monitoring/public/components/beats/overview/overview.js index 83f92ea1b481cd..897f017f44f418 100644 --- a/x-pack/plugins/monitoring/public/components/beats/overview/overview.js +++ b/x-pack/plugins/monitoring/public/components/beats/overview/overview.js @@ -30,46 +30,40 @@ function renderLatestActive(latestActive, latestTypes, latestVersions) { return ( - - -

- -

-
- - -
+ +

+ +

+
+ +
- - -

- -

-
- - -
+ +

+ +

+
+ +
- - -

- -

-
- - -
+ +

+ +

+
+ +
); @@ -118,10 +112,13 @@ export function BeatsOverview({ /> - + - {renderLatestActive(latestActive, latestTypes, latestVersions)} - + + + {renderLatestActive(latestActive, latestTypes, latestVersions)} + + {charts}
diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js index ccbf0b0ec711dd..4bf07710393ea7 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js @@ -55,7 +55,7 @@ export function ApmPanel(props) { {...props} url="apm" title={i18n.translate('xpack.monitoring.cluster.overview.apmPanel.apmTitle', { - defaultMessage: 'APM', + defaultMessage: 'APM server', })} > @@ -70,21 +70,21 @@ export function ApmPanel(props) { aria-label={i18n.translate( 'xpack.monitoring.cluster.overview.apmPanel.overviewLinkAriaLabel', { - defaultMessage: 'APM Overview', + defaultMessage: 'APM server overview', } )} data-test-subj="apmOverview" > - + {formatMetric(props.totalEvents, '0.[0]a')} - + {apmsTotal} }} /> @@ -144,7 +144,7 @@ export function ApmPanel(props) { - + - + {formatMetric(props.totalEvents, '0.[0]a')} - + {props.logs.types.map((log, index) => ( - + - + @@ -276,7 +277,7 @@ export function ElasticsearchPanel(props) { - + - + - + - + {showMlJobs()} - + - + - + - + - + {formatNumber(get(indices, 'docs.count'), 'int_commas')} - + - + - + - + diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/kibana_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/kibana_panel.js index 6fa533302db48d..7df0a3ca7138e6 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/kibana_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/kibana_panel.js @@ -111,7 +111,7 @@ export function KibanaPanel(props) { data-test-subj="kibana_overview" data-overview-status={props.status} > - + {props.requests_total} - + - + {formatNumber(props.concurrent_connections, 'int_commas')} - + - + {formatNumber(props.events_in_total, '0.[0]a')} - + - + {props.max_uptime ? formatNumber(props.max_uptime, 'time_since') : 0} - + - + {queueTypes[LOGSTASH.QUEUE_TYPES.MEMORY] || 0} - + } checked={showSystemIndices} diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/__snapshots__/cells.test.js.snap b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/__snapshots__/cells.test.js.snap index c7081dc439085c..b0b5ceb46d16cb 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/__snapshots__/cells.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/__snapshots__/cells.test.js.snap @@ -10,30 +10,46 @@ exports[`Node Listing Metric Cell should format N/A as the metric for an offline exports[`Node Listing Metric Cell should format a non-percentage metric 1`] = `
+
- - 206.3 GB  - - -
- 206.5 GB max -
- 206.3 GB min +
+
+
+
+
+
+
+
+
+ 206.3 GB +
+
@@ -41,30 +57,46 @@ exports[`Node Listing Metric Cell should format a non-percentage metric 1`] = ` exports[`Node Listing Metric Cell should format a percentage metric 1`] = `
+
- - 0%  - - -
- 2% max -
- 0% min +
+
+
+
+
+
+
+
+
+ 0% +
+
diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/cells.test.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/cells.test.js index 0c4b4b2b3c3f41..f0b131b65433cf 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/cells.test.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/cells.test.js @@ -27,6 +27,7 @@ describe('Node Listing Metric Cell', () => { }, summary: { minVal: 0, maxVal: 2, lastVal: 0, slope: -1 }, }, + 'data-test-subj': 'testCell', }; expect(renderWithIntl()).toMatchSnapshot(); }); @@ -54,6 +55,7 @@ describe('Node Listing Metric Cell', () => { slope: -1, }, }, + 'data-test-subj': 'testCell2', }; expect(renderWithIntl()).toMatchSnapshot(); }); diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/cells.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/cells.js index 4c3b642213d998..9956dd4da7d8a4 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/cells.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/cells.js @@ -4,19 +4,42 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useState } from 'react'; import { get } from 'lodash'; import { formatMetric } from '../../../lib/format_number'; -import { EuiText, EuiTitle, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { + EuiText, + EuiPopover, + EuiIcon, + EuiDescriptionList, + EuiSpacer, + EuiKeyboardAccessible, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +const TRENDING_DOWN = i18n.translate('xpack.monitoring.elasticsearch.node.cells.trendingDownText', { + defaultMessage: 'down', +}); +const TRENDING_UP = i18n.translate('xpack.monitoring.elasticsearch.node.cells.trendingUpText', { + defaultMessage: 'up', +}); + function OfflineCell() { return
N/A
; } -const getSlopeArrow = (slope) => { +const getDirection = (slope) => { + if (slope || slope === 0) { + return slope > 0 ? TRENDING_UP : TRENDING_DOWN; + } + return null; +}; + +const getIcon = (slope) => { if (slope || slope === 0) { - return slope > 0 ? 'up' : 'down'; + return slope > 0 ? 'arrowUp' : 'arrowDown'; } return null; }; @@ -28,40 +51,82 @@ const metricVal = (metric, format, isPercent, units) => { return formatMetric(metric, format, units); }; -const noWrapStyle = { overflowX: 'hidden', whiteSpace: 'nowrap' }; - function MetricCell({ isOnline, metric = {}, isPercent, ...props }) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const onButtonClick = () => setIsPopoverOpen((isPopoverOpen) => !isPopoverOpen); + const closePopover = () => setIsPopoverOpen(false); + if (isOnline) { const { lastVal, maxVal, minVal, slope } = get(metric, 'summary', {}); const format = get(metric, 'metric.format'); const units = get(metric, 'metric.units'); + const tooltipItems = [ + { + title: i18n.translate('xpack.monitoring.elasticsearch.node.cells.tooltip.trending', { + defaultMessage: 'Trending', + }), + description: getDirection(slope), + }, + { + title: i18n.translate('xpack.monitoring.elasticsearch.node.cells.tooltip.max', { + defaultMessage: 'Max value', + }), + description: metricVal(maxVal, format, isPercent, units), + }, + { + title: i18n.translate('xpack.monitoring.elasticsearch.node.cells.tooltip.min', { + defaultMessage: 'Min value', + }), + description: metricVal(minVal, format, isPercent, units), + }, + ]; + + const button = ( + + + + ); + return ( - + + - - - {metricVal(lastVal, format, isPercent)} -   - - - - - {i18n.translate('xpack.monitoring.elasticsearch.nodes.cells.maxText', { - defaultMessage: '{metric} max', - values: { - metric: metricVal(maxVal, format, isPercent, units), - }, - })} - - - {i18n.translate('xpack.monitoring.elasticsearch.nodes.cells.minText', { - defaultMessage: '{metric} min', - values: { - metric: metricVal(minVal, format, isPercent, units), - }, - })} - + + + +
+ + + + {i18n.translate('xpack.monitoring.elasticsearch.node.cells.tooltip.preface', { + defaultMessage: 'Applies to current time period', + })} + +
+
+
+ + {metricVal(lastVal, format, isPercent)} + +
); diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js index 43512f8e528f6a..f088f7c0d348af 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js @@ -73,7 +73,6 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler name: i18n.translate('xpack.monitoring.elasticsearch.nodes.nameColumnTitle', { defaultMessage: 'Name', }), - width: '20%', field: 'name', sortable: true, render: (value, node) => { @@ -131,7 +130,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler defaultMessage: 'Alerts', }), field: 'alerts', - width: '175px', + // width: '175px', sortable: true, render: (_field, node) => { return ( @@ -148,6 +147,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler name: i18n.translate('xpack.monitoring.elasticsearch.nodes.statusColumnTitle', { defaultMessage: 'Status', }), + dataType: 'boolean', field: 'isOnline', sortable: true, render: (value) => { @@ -181,22 +181,18 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler name: i18n.translate('xpack.monitoring.elasticsearch.nodes.shardsColumnTitle', { defaultMessage: 'Shards', }), + dataType: 'number', field: 'shardCount', sortable: true, render: (value, node) => { - return node.isOnline ? ( -
- {value} -
- ) : ( - - ); + return node.isOnline ? {value} : ; }, }); if (showCgroupMetricsElasticsearch) { cols.push({ name: cpuUsageColumnTitle, + dataType: 'number', field: 'node_cgroup_quota', sortable: getSortHandler('node_cgroup_quota'), render: (value, node) => ( @@ -213,6 +209,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler name: i18n.translate('xpack.monitoring.elasticsearch.nodes.cpuThrottlingColumnTitle', { defaultMessage: 'CPU Throttling', }), + dataType: 'number', field: 'node_cgroup_throttled', sortable: getSortHandler('node_cgroup_throttled'), render: (value, node) => ( @@ -227,6 +224,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler } else { cols.push({ name: cpuUsageColumnTitle, + dataType: 'number', field: 'node_cpu_utilization', sortable: getSortHandler('node_cpu_utilization'), render: (value, node) => { @@ -245,6 +243,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler name: i18n.translate('xpack.monitoring.elasticsearch.nodes.loadAverageColumnTitle', { defaultMessage: 'Load Average', }), + dataType: 'number', field: 'node_load_average', sortable: getSortHandler('node_load_average'), render: (value, node) => ( @@ -265,6 +264,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler javaVirtualMachine: 'JVM', }, }), + dataType: 'number', field: 'node_jvm_mem_percent', sortable: getSortHandler('node_jvm_mem_percent'), render: (value, node) => ( @@ -281,6 +281,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler name: i18n.translate('xpack.monitoring.elasticsearch.nodes.diskFreeSpaceColumnTitle', { defaultMessage: 'Disk Free Space', }), + dataType: 'number', field: 'node_free_space', sortable: getSortHandler('node_free_space'), render: (value, node) => ( diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/table_head.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/table_head.js index fd5f28ea02039e..3c875667fe04cf 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/table_head.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/table_head.js @@ -5,6 +5,7 @@ */ import React from 'react'; +import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSwitch } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -37,7 +38,12 @@ class IndexLabel extends React.Component { $el && $el[0] && unmountComponentAtNode($el[0])); - - scope.$watch('data', (data = {}) => { - render( - , - $el[0] - ); - }); - }, - }; -} diff --git a/x-pack/plugins/monitoring/public/directives/beats/overview/index.js b/x-pack/plugins/monitoring/public/directives/beats/overview/index.js deleted file mode 100644 index 4faf69e13d02c4..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/beats/overview/index.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { BeatsOverview } from '../../../components/beats/overview'; - -export function monitoringBeatsOverviewProvider() { - return { - restrict: 'E', - scope: { - data: '=', - onBrush: '<', - zoomInfo: '<', - }, - link(scope, $el) { - scope.$on('$destroy', () => $el && $el[0] && unmountComponentAtNode($el[0])); - - scope.$watch('data', (data = {}) => { - render( - , - $el[0] - ); - }); - }, - }; -} diff --git a/x-pack/plugins/monitoring/public/directives/main/index.html b/x-pack/plugins/monitoring/public/directives/main/index.html index fabd207d72b1fc..fb24d9e678d565 100644 --- a/x-pack/plugins/monitoring/public/directives/main/index.html +++ b/x-pack/plugins/monitoring/public/directives/main/index.html @@ -1,19 +1,32 @@
-
- - +
+
+
+
+
+
+

{{pageTitle || monitoringMain.instance}}

+
+
+
+
+
+ + +
+
`; diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx index 62880e7510cd2b..0cb721bb5382f2 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx @@ -15,6 +15,8 @@ import { Title } from './title'; import { DraggableArguments, BadgeOptions, TitleProp } from './types'; import { useFormatUrl } from '../link_to'; import { SecurityPageName } from '../../../app/types'; +import { Sourcerer } from '../sourcerer'; +import { SourcererScopeName } from '../../store/sourcerer/model'; interface HeaderProps { border?: boolean; @@ -72,6 +74,7 @@ export interface HeaderPageProps extends HeaderProps { badgeOptions?: BadgeOptions; children?: React.ReactNode; draggableArguments?: DraggableArguments; + hideSourcerer?: boolean; subtitle?: SubtitleProps['items']; subtitle2?: SubtitleProps['items']; title: TitleProp; @@ -84,6 +87,7 @@ const HeaderPageComponent: React.FC = ({ border, children, draggableArguments, + hideSourcerer = false, isLoading, subtitle, subtitle2, @@ -138,6 +142,7 @@ const HeaderPageComponent: React.FC = ({ )} + {!hideSourcerer && } ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/last_event_time/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/last_event_time/index.test.tsx index 9473ba67a1c4fa..c2800b0705b43e 100644 --- a/x-pack/plugins/security_solution/public/common/components/last_event_time/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/last_event_time/index.test.tsx @@ -37,7 +37,7 @@ describe('Last Event Time Stat', () => { ]); const wrapper = mount( - + ); expect(wrapper.html()).toBe( @@ -54,7 +54,7 @@ describe('Last Event Time Stat', () => { ]); const wrapper = mount( - + ); expect(wrapper.html()).toBe('Last event: 12 minutes ago'); @@ -69,7 +69,7 @@ describe('Last Event Time Stat', () => { ]); const wrapper = mount( - + ); @@ -85,7 +85,7 @@ describe('Last Event Time Stat', () => { ]); const wrapper = mount( - + ); expect(wrapper.html()).toContain(getEmptyValue()); diff --git a/x-pack/plugins/security_solution/public/common/components/last_event_time/index.tsx b/x-pack/plugins/security_solution/public/common/components/last_event_time/index.tsx index e9e8e7a03017cb..d508040f84239b 100644 --- a/x-pack/plugins/security_solution/public/common/components/last_event_time/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/last_event_time/index.tsx @@ -8,58 +8,65 @@ import { EuiIcon, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { memo } from 'react'; +import { DocValueFields } from '../../../../common/search_strategy'; import { LastEventIndexKey } from '../../../graphql/types'; import { useTimelineLastEventTime } from '../../containers/events/last_event_time'; import { getEmptyTagValue } from '../empty_value'; import { FormattedRelativePreferenceDate } from '../formatted_date'; export interface LastEventTimeProps { + docValueFields: DocValueFields[]; hostName?: string; indexKey: LastEventIndexKey; ip?: string; + indexNames: string[]; } -export const LastEventTime = memo(({ hostName, indexKey, ip }) => { - const [loading, { lastSeen, errorMessage }] = useTimelineLastEventTime({ - indexKey, - details: { - hostName, - ip, - }, - }); +export const LastEventTime = memo( + ({ docValueFields, hostName, indexKey, ip, indexNames }) => { + const [loading, { lastSeen, errorMessage }] = useTimelineLastEventTime({ + docValueFields, + indexKey, + indexNames, + details: { + hostName, + ip, + }, + }); + + if (errorMessage != null) { + return ( + + + + ); + } - if (errorMessage != null) { return ( - - - + <> + {loading && } + {!loading && lastSeen != null && new Date(lastSeen).toString() === 'Invalid Date' + ? lastSeen + : !loading && + lastSeen != null && ( + , + }} + /> + )} + {!loading && lastSeen == null && getEmptyTagValue()} + ); } - - return ( - <> - {loading && } - {!loading && lastSeen != null && new Date(lastSeen).toString() === 'Invalid Date' - ? lastSeen - : !loading && - lastSeen != null && ( - , - }} - /> - )} - {!loading && lastSeen == null && getEmptyTagValue()} - - ); -}); +); LastEventTime.displayName = 'LastEventTime'; diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx index 7286c6b7436929..99dc8a802b33df 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx @@ -47,6 +47,7 @@ describe('Matrix Histogram Component', () => { errorMessage: 'error', histogramType: MatrixHistogramType.alerts, id: 'mockId', + indexNames: [], isInspected: false, isPtrIncluded: false, setQuery: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx index 485ca4c93133ac..e7d7e60a3c4088 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx @@ -37,7 +37,6 @@ export type MatrixHistogramComponentProps = MatrixHistogramProps & hideHistogramIfEmpty?: boolean; histogramType: MatrixHistogramType; id: string; - indexToAdd?: string[] | null; legendPosition?: Position; mapping?: MatrixHistogramMappingTypes; showSpacer?: boolean; @@ -72,7 +71,7 @@ export const MatrixHistogramComponent: React.FC = histogramType, hideHistogramIfEmpty = false, id, - indexToAdd, + indexNames, legendPosition, mapping, panelHeight = DEFAULT_PANEL_HEIGHT, @@ -136,7 +135,7 @@ export const MatrixHistogramComponent: React.FC = errorMessage, filterQuery, histogramType, - indexToAdd, + indexNames, startDate, stackByField: selectedStackByOption.value, }); diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts index fc1df4d8ca85f5..9a892110bde43d 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts @@ -59,6 +59,7 @@ interface MatrixHistogramBasicProps { export interface MatrixHistogramQueryProps { endDate: string; errorMessage: string; + indexNames: string[]; filterQuery?: ESQuery | string | undefined; setAbsoluteRangeDatePicker?: ActionCreator<{ id: InputsModelId; @@ -68,7 +69,6 @@ export interface MatrixHistogramQueryProps { setAbsoluteRangeDatePickerTarget?: InputsModelId; stackByField: string; startDate: string; - indexToAdd?: string[] | null; histogramType: MatrixHistogramType; } diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts index 89aa77106933e5..da5099f61e9b2d 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts @@ -105,6 +105,7 @@ const getMockObject = ( }, }, }, + sourcerer: {}, }); const getUrlForAppMock = (appId: string, options?: { path?: string; absolute?: boolean }) => @@ -130,7 +131,7 @@ describe('Navigation Breadcrumbs', () => { }, { href: - "securitySolution:hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:hosts?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", text: 'Hosts', }, { @@ -150,7 +151,7 @@ describe('Navigation Breadcrumbs', () => { { text: 'Network', href: - "securitySolution:network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:network?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: 'Flows', @@ -169,7 +170,7 @@ describe('Navigation Breadcrumbs', () => { { text: 'Timelines', href: - "securitySolution:timelines?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:timelines?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, ]); }); @@ -184,12 +185,12 @@ describe('Navigation Breadcrumbs', () => { { text: 'Hosts', href: - "securitySolution:hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:hosts?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: 'siem-kibana', href: - "securitySolution:hosts/siem-kibana?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:hosts/siem-kibana?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: 'Authentications', href: '' }, ]); @@ -205,11 +206,11 @@ describe('Navigation Breadcrumbs', () => { { text: 'Network', href: - "securitySolution:network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:network?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: ipv4, - href: `securitySolution:network/ip/${ipv4}/source?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, + href: `securitySolution:network/ip/${ipv4}/source?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, }, { text: 'Flows', href: '' }, ]); @@ -225,11 +226,11 @@ describe('Navigation Breadcrumbs', () => { { text: 'Network', href: - "securitySolution:network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:network?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: ipv6, - href: `securitySolution:network/ip/${ipv6Encoded}/source?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, + href: `securitySolution:network/ip/${ipv6Encoded}/source?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, }, { text: 'Flows', href: '' }, ]); @@ -245,7 +246,7 @@ describe('Navigation Breadcrumbs', () => { { text: 'Detections', href: - "securitySolution:detections?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:detections?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, ]); }); @@ -259,7 +260,7 @@ describe('Navigation Breadcrumbs', () => { { text: 'Cases', href: - "securitySolution:case?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:case?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, ]); }); @@ -280,11 +281,11 @@ describe('Navigation Breadcrumbs', () => { { text: 'Cases', href: - "securitySolution:case?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:case?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: sampleCase.name, - href: `securitySolution:case/${sampleCase.id}?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, + href: `securitySolution:case/${sampleCase.id}?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, }, ]); }); @@ -311,12 +312,12 @@ describe('Navigation Breadcrumbs', () => { { text: 'Hosts', href: - "securitySolution:hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:hosts?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: 'siem-kibana', href: - "securitySolution:hosts/siem-kibana?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "securitySolution:hosts/siem-kibana?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", }, { text: 'Authentications', href: '' }, ]); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts b/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts index 8f5a3ac63fa1ad..ed71f55fd0161c 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts @@ -19,12 +19,19 @@ import { import { Query, Filter } from '../../../../../../../src/plugins/data/public'; import { SearchNavTab } from './types'; +import { SourcererScopePatterns } from '../../store/sourcerer/model'; export const getSearch = (tab: SearchNavTab, urlState: UrlState): string => { if (tab && tab.urlKey != null && URL_STATE_KEYS[tab.urlKey] != null) { return URL_STATE_KEYS[tab.urlKey].reduce( (myLocation: Location, urlKey: KeyUrlState) => { - let urlStateToReplace: UrlInputsModel | Query | Filter[] | TimelineUrl | string = ''; + let urlStateToReplace: + | Filter[] + | Query + | SourcererScopePatterns + | TimelineUrl + | UrlInputsModel + | string = ''; if (urlKey === CONSTANTS.appQuery && urlState.query != null) { if (urlState.query.query === '') { @@ -40,6 +47,8 @@ export const getSearch = (tab: SearchNavTab, urlState: UrlState): string => { } } else if (urlKey === CONSTANTS.timerange) { urlStateToReplace = urlState[CONSTANTS.timerange]; + } else if (urlKey === CONSTANTS.sourcerer) { + urlStateToReplace = urlState[CONSTANTS.sourcerer]; } else if (urlKey === CONSTANTS.timeline && urlState[CONSTANTS.timeline] != null) { const timeline = urlState[CONSTANTS.timeline]; if (timeline.id === '') { diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx index 16cb19f5a0c146..102ed7851e57d2 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx @@ -78,6 +78,7 @@ describe('SIEM Navigation', () => { }, [CONSTANTS.appQuery]: { query: '', language: 'kuery' }, [CONSTANTS.filters]: [], + [CONSTANTS.sourcerer]: {}, [CONSTANTS.timeline]: { id: '', isOpen: false, @@ -145,6 +146,7 @@ describe('SIEM Navigation', () => { pageName: 'hosts', pathName: '/', search: '', + sourcerer: {}, state: undefined, tabName: 'authentications', query: { query: '', language: 'kuery' }, @@ -252,6 +254,7 @@ describe('SIEM Navigation', () => { query: { language: 'kuery', query: '' }, savedQuery: undefined, search: '', + sourcerer: {}, state: undefined, tabName: 'authentications', timeline: { id: '', isOpen: false, graphEventId: '' }, diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index 5ee35e7da0f3ee..b149488ff38a75 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -40,19 +40,20 @@ export const SiemNavigationComponent: React.FC< if (pathName || pageName) { setBreadcrumbs( { - query: urlState.query, detailName, filters: urlState.filters, + flowTarget, navTabs, pageName, pathName, + query: urlState.query, savedQuery: urlState.savedQuery, search, + sourcerer: urlState.sourcerer, + state, tabName, - flowTarget, - timerange: urlState.timerange, timeline: urlState.timeline, - state, + timerange: urlState.timerange, }, chrome, getUrlForApp @@ -69,6 +70,7 @@ export const SiemNavigationComponent: React.FC< navTabs={navTabs} pageName={pageName} pathName={pathName} + sourcerer={urlState.sourcerer} savedQuery={urlState.savedQuery} tabName={tabName} timeline={urlState.timeline} diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx index b25cf3779801b7..5c69edbabdc665 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx @@ -68,6 +68,7 @@ describe('Tab Navigation', () => { }, [CONSTANTS.appQuery]: { query: 'host.name:"siem-es"', language: 'kuery' }, [CONSTANTS.filters]: [], + [CONSTANTS.sourcerer]: {}, [CONSTANTS.timeline]: { id: '', isOpen: false, @@ -126,6 +127,7 @@ describe('Tab Navigation', () => { }, [CONSTANTS.appQuery]: { query: 'host.name:"siem-es"', language: 'kuery' }, [CONSTANTS.filters]: [], + [CONSTANTS.sourcerer]: {}, [CONSTANTS.timeline]: { id: '', isOpen: false, diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx index 217ad0e58570f5..3eb66b5591b85e 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx @@ -94,10 +94,17 @@ export const TabNavigationComponent = (props: TabNavigationProps) => { () => Object.values(navTabs).map((tab) => { const isSelected = selectedTabId === tab.id; - const { query, filters, savedQuery, timerange, timeline } = props; - const search = getSearch(tab, { query, filters, savedQuery, timerange, timeline }); + const { filters, query, savedQuery, sourcerer, timeline, timerange } = props; + const search = getSearch(tab, { + filters, + query, + savedQuery, + sourcerer, + timeline, + timerange, + }); const hrefWithSearch = - tab.href + getSearch(tab, { query, filters, savedQuery, timerange, timeline }); + tab.href + getSearch(tab, { filters, query, savedQuery, sourcerer, timeline, timerange }); return ( { - const original = jest.requireActual('../../containers/sourcerer'); +const mockDispatch = jest.fn(); +jest.mock('react-redux', () => { + const original = jest.requireActual('react-redux'); return { ...original, - useManageSource: () => mockManageSource, + useDispatch: () => mockDispatch, }; }); const mockOptions = [ - { label: 'auditbeat-*', key: 'auditbeat-*-0', value: 'auditbeat-*', checked: 'on' }, - { label: 'endgame-*', key: 'endgame-*-1', value: 'endgame-*', checked: 'on' }, - { label: 'filebeat-*', key: 'filebeat-*-2', value: 'filebeat-*', checked: 'on' }, - { label: 'logs-*', key: 'logs-*-3', value: 'logs-*', checked: 'on' }, - { label: 'packetbeat-*', key: 'packetbeat-*-4', value: 'packetbeat-*', checked: undefined }, - { label: 'winlogbeat-*', key: 'winlogbeat-*-5', value: 'winlogbeat-*', checked: 'on' }, - { - label: 'apm-*-transaction*', - key: 'apm-*-transaction*-0', - value: 'apm-*-transaction*', - disabled: true, - checked: undefined, - }, - { - label: 'blobbeat-*', - key: 'blobbeat-*-1', - value: 'blobbeat-*', - disabled: true, - checked: undefined, - }, + { label: 'apm-*-transaction*', value: 'apm-*-transaction*' }, + { label: 'auditbeat-*', value: 'auditbeat-*' }, + { label: 'endgame-*', value: 'endgame-*' }, + { label: 'filebeat-*', value: 'filebeat-*' }, + { label: 'logs-*', value: 'logs-*' }, + { label: 'packetbeat-*', value: 'packetbeat-*' }, + { label: 'winlogbeat-*', value: 'winlogbeat-*' }, ]; +const defaultProps = { + scope: sourcererModel.SourcererScopeName.default, +}; describe('Sourcerer component', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + const state: State = mockGlobalState; + const { storage } = createSecuritySolutionStorageMock(); + let store = createStore( + state, + SUB_PLUGINS_REDUCER, + apolloClientObservable, + kibanaObservable, + storage + ); + + beforeEach(() => { + store = createStore( + state, + SUB_PLUGINS_REDUCER, + apolloClientObservable, + kibanaObservable, + storage + ); + }); + // Using props callback instead of simulating clicks, // because EuiSelectable uses a virtualized list, which isn't easily testable via test subjects - it('Mounts with correct options selected and disabled', () => { - const wrapper = mount(); + it('Mounts with all options selected', () => { + const wrapper = mount( + + + + ); wrapper.find(`[data-test-subj="sourcerer-trigger"]`).first().simulate('click'); - expect( - wrapper.find(`[data-test-subj="indexPattern-switcher"]`).first().prop('options') + wrapper.find(`[data-test-subj="indexPattern-switcher"]`).first().prop('selectedOptions') ).toEqual(mockOptions); }); - it('onChange calls updateSourceGroupIndicies', () => { - const wrapper = mount(); - wrapper.find(`[data-test-subj="sourcerer-trigger"]`).first().simulate('click'); - - const switcherOnChange = wrapper - .find(`[data-test-subj="indexPattern-switcher"]`) - .first() - .prop('onChange'); - // @ts-ignore - switcherOnChange([mockOptions[0], mockOptions[1]]); - expect(updateSourceGroupIndicies).toHaveBeenCalledWith(SecurityPageName.default, [ - mockOptions[0].value, - mockOptions[1].value, - ]); - }); - it('Disabled options have icon tooltip', () => { - const wrapper = mount(); - wrapper.find(`[data-test-subj="sourcerer-trigger"]`).first().simulate('click'); - // @ts-ignore - const Rendered = wrapper - .find(`[data-test-subj="indexPattern-switcher"]`) - .first() - .prop('renderOption')( - { - label: 'blobbeat-*', - key: 'blobbeat-*-1', - value: 'blobbeat-*', - disabled: true, - checked: undefined, + it('Mounts with some options selected', () => { + const state2 = { + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.default]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default], + loading: false, + selectedPatterns: [DEFAULT_INDEX_PATTERN[0]], + }, + }, }, - '' + }; + + store = createStore( + state2, + SUB_PLUGINS_REDUCER, + apolloClientObservable, + kibanaObservable, + storage + ); + const wrapper = mount( + + + ); - expect(Rendered.props.children[1].props.content).toEqual(i18n.DISABLED_INDEX_PATTERNS); + wrapper.find(`[data-test-subj="sourcerer-trigger"]`).first().simulate('click'); + expect( + wrapper.find(`[data-test-subj="indexPattern-switcher"]`).first().prop('selectedOptions') + ).toEqual([mockOptions[0]]); }); - - it('Button links to index path', () => { - const wrapper = mount(); + it('onChange calls updateSourcererScopeIndices', async () => { + const wrapper = mount( + + + + ); + expect(true).toBeTruthy(); wrapper.find(`[data-test-subj="sourcerer-trigger"]`).first().simulate('click'); - expect(wrapper.find(`[data-test-subj="add-index"]`).first().prop('href')).toEqual( - ADD_INDEX_PATH + await act(async () => { + ((wrapper.find(EuiComboBox).props() as unknown) as { + onChange: (a: EuiComboBoxOptionOption[]) => void; + }).onChange([mockOptions[0], mockOptions[1]]); + await waitFor(() => { + wrapper.update(); + }); + }); + wrapper.find(`[data-test-subj="add-index"]`).first().simulate('click'); + + expect(mockDispatch).toHaveBeenCalledWith( + sourcererActions.setSelectedIndexPatterns({ + id: SourcererScopeName.default, + selectedPatterns: [mockOptions[0].value, mockOptions[1].value], + }) ); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx index 6275ce19c36087..7a74f5bf2247f5 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx @@ -4,50 +4,122 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, useMemo, useState } from 'react'; import { EuiButton, EuiButtonEmpty, - EuiHighlight, - EuiIconTip, + EuiComboBox, + EuiComboBoxOptionOption, + EuiIcon, + EuiFlexGroup, + EuiFlexItem, EuiPopover, - EuiPopoverFooter, EuiPopoverTitle, - EuiSelectable, + EuiSpacer, + EuiText, + EuiToolTip, } from '@elastic/eui'; -import { EuiSelectableOption } from '@elastic/eui/src/components/selectable/selectable_option'; -import { useManageSource } from '../../containers/sourcerer'; +import deepEqual from 'fast-deep-equal'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import styled from 'styled-components'; + import * as i18n from './translations'; import { SOURCERER_FEATURE_FLAG_ON } from '../../containers/sourcerer/constants'; -import { ADD_INDEX_PATH } from '../../../../common/constants'; - -export const MaybeSourcerer = React.memo(() => { - const { - activeSourceGroupId, - availableIndexPatterns, - getManageSourceGroupById, - isIndexPatternsLoading, - updateSourceGroupIndicies, - } = useManageSource(); - const { defaultPatterns, indexPatterns: selectedOptions, loading: loadingIndices } = useMemo( - () => getManageSourceGroupById(activeSourceGroupId), - [getManageSourceGroupById, activeSourceGroupId] +import { sourcererActions, sourcererModel } from '../../store/sourcerer'; +import { State } from '../../store'; +import { getSourcererScopeSelector, SourcererScopeSelector } from './selectors'; + +const PopoverContent = styled.div` + width: 600px; +`; + +const ResetButton = styled(EuiButtonEmpty)` + width: fit-content; +`; +interface SourcererComponentProps { + scope: sourcererModel.SourcererScopeName; +} + +export const SourcererComponent = React.memo(({ scope: scopeId }) => { + const dispatch = useDispatch(); + const sourcererScopeSelector = useMemo(getSourcererScopeSelector, []); + const { configIndexPatterns, kibanaIndexPatterns, sourcererScope } = useSelector< + State, + SourcererScopeSelector + >((state) => sourcererScopeSelector(state, scopeId), deepEqual); + const { selectedPatterns, loading } = sourcererScope; + const [isPopoverOpen, setPopoverIsOpen] = useState(false); + const [selectedOptions, setSelectedOptions] = useState>>( + selectedPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })) ); - const loading = useMemo(() => loadingIndices || isIndexPatternsLoading, [ - isIndexPatternsLoading, - loadingIndices, - ]); + const setPopoverIsOpenCb = useCallback(() => setPopoverIsOpen((prevState) => !prevState), []); const onChangeIndexPattern = useCallback( - (newIndexPatterns: string[]) => { - updateSourceGroupIndicies(activeSourceGroupId, newIndexPatterns); + (newSelectedPatterns: string[]) => { + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: scopeId, + selectedPatterns: newSelectedPatterns, + }) + ); }, - [activeSourceGroupId, updateSourceGroupIndicies] + [dispatch, scopeId] + ); + + const renderOption = useCallback( + (option) => { + const { value } = option; + if (kibanaIndexPatterns.some((kip) => kip.title === value)) { + return ( + <> + {value} + + ); + } + return <>{value}; + }, + [kibanaIndexPatterns] + ); + + const onChangeCombo = useCallback((newSelectedOptions) => { + setSelectedOptions(newSelectedOptions); + }, []); + + const resetDataSources = useCallback(() => { + setSelectedOptions( + configIndexPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })) + ); + }, [configIndexPatterns]); + + const handleSaveIndices = useCallback(() => { + onChangeIndexPattern(selectedOptions.map((so) => so.label)); + setPopoverIsOpen(false); + }, [onChangeIndexPattern, selectedOptions]); + + const handleClosePopOver = useCallback(() => { + setPopoverIsOpen(false); + }, []); + + const indexesPatternOptions = useMemo( + () => + [...configIndexPatterns, ...kibanaIndexPatterns.map((kip) => kip.title)].reduce< + Array> + >((acc, index) => { + if (index != null && !acc.some((o) => o.label.includes(index))) { + return [...acc, { label: index, value: index }]; + } + return acc; + }, []), + [configIndexPatterns, kibanaIndexPatterns] ); - const [isPopoverOpen, setPopoverIsOpen] = useState(false); - const setPopoverIsOpenCb = useCallback(() => setPopoverIsOpen((prevState) => !prevState), []); const trigger = useMemo( () => ( { data-test-subj="sourcerer-trigger" flush="left" iconSide="right" - iconType="indexSettings" + iconType="arrowDown" + isLoading={loading} onClick={setPopoverIsOpenCb} size="l" title={i18n.SOURCERER} @@ -63,99 +136,91 @@ export const MaybeSourcerer = React.memo(() => { {i18n.SOURCERER} ), - [setPopoverIsOpenCb] - ); - const options: EuiSelectableOption[] = useMemo( - () => - availableIndexPatterns.map((title, id) => ({ - label: title, - key: `${title}-${id}`, - value: title, - checked: selectedOptions.includes(title) ? 'on' : undefined, - })), - [availableIndexPatterns, selectedOptions] + [setPopoverIsOpenCb, loading] ); - const unSelectableOptions: EuiSelectableOption[] = useMemo( - () => - defaultPatterns - .filter((title) => !availableIndexPatterns.includes(title)) - .map((title, id) => ({ - label: title, - key: `${title}-${id}`, - value: title, - disabled: true, - checked: undefined, - })), - [availableIndexPatterns, defaultPatterns] - ); - const renderOption = useCallback( - (option, searchValue) => ( - <> - {option.label} - {option.disabled ? ( - - ) : null} - + + const comboBox = useMemo( + () => ( + ), - [] + [indexesPatternOptions, onChangeCombo, renderOption, selectedOptions] ); - const onChange = useCallback( - (choices: EuiSelectableOption[]) => { - const choice = choices.reduce( - (acc, { checked, label }) => (checked === 'on' ? [...acc, label] : acc), - [] - ); - onChangeIndexPattern(choice); - }, - [onChangeIndexPattern] + + useEffect(() => { + const newSelecteOptions = selectedPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })); + setSelectedOptions((prevSelectedOptions) => { + if (!deepEqual(newSelecteOptions, prevSelectedOptions)) { + return newSelecteOptions; + } + return prevSelectedOptions; + }); + }, [selectedPatterns]); + + const tooltipContent = useMemo( + () => (isPopoverOpen ? null : sourcererScope.selectedPatterns.sort().join(', ')), + [isPopoverOpen, sourcererScope.selectedPatterns] ); - const allOptions = useMemo(() => [...options, ...unSelectableOptions], [ - options, - unSelectableOptions, - ]); + return ( - setPopoverIsOpen(false)} - display="block" - panelPaddingSize="s" - ownFocus - > -
- - <> - {i18n.CHANGE_INDEX_PATTERNS} - - - - - {(list, search) => ( - <> - {search} - {list} - - )} - - - - {i18n.ADD_INDEX_PATTERNS} - - -
-
+ + + + + <>{i18n.SELECT_INDEX_PATTERNS} + + + {i18n.INDEX_PATTERNS_SELECTION_LABEL} + + {comboBox} + + + + + {i18n.INDEX_PATTERNS_RESET} + + + + + {i18n.SAVE_INDEX_PATTERNS} + + + + + + ); }); -MaybeSourcerer.displayName = 'Sourcerer'; +SourcererComponent.displayName = 'Sourcerer'; -export const Sourcerer = SOURCERER_FEATURE_FLAG_ON ? MaybeSourcerer : () => null; +export const Sourcerer = SOURCERER_FEATURE_FLAG_ON ? SourcererComponent : () => null; diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/selectors.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/selectors.tsx new file mode 100644 index 00000000000000..6bbe24e9218801 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/selectors.tsx @@ -0,0 +1,35 @@ +/* + * 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 { State } from '../../store'; +import { sourcererSelectors } from '../../store/sourcerer'; +import { KibanaIndexPatterns, ManageScope, SourcererScopeName } from '../../store/sourcerer/model'; + +export interface SourcererScopeSelector { + configIndexPatterns: string[]; + kibanaIndexPatterns: KibanaIndexPatterns; + sourcererScope: ManageScope; +} + +export const getSourcererScopeSelector = () => { + const getKibanaIndexPatternsSelector = sourcererSelectors.kibanaIndexPatternsSelector(); + const getScopesSelector = sourcererSelectors.scopesSelector(); + const getConfigIndexPatternsSelector = sourcererSelectors.configIndexPatternsSelector(); + + const mapStateToProps = (state: State, scopeId: SourcererScopeName): SourcererScopeSelector => { + const kibanaIndexPatterns = getKibanaIndexPatternsSelector(state); + const scope = getScopesSelector(state)[scopeId]; + const configIndexPatterns = getConfigIndexPatternsSelector(state); + + return { + kibanaIndexPatterns, + configIndexPatterns, + sourcererScope: scope, + }; + }; + + return mapStateToProps; +}; diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/translations.ts b/x-pack/plugins/security_solution/public/common/components/sourcerer/translations.ts index 71b1734dad6a65..473eb43d5c4fed 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/translations.ts @@ -6,23 +6,26 @@ import { i18n } from '@kbn/i18n'; -export const SOURCERER = i18n.translate('xpack.securitySolution.indexPatterns.sourcerer', { - defaultMessage: 'Sourcerer', +export const SOURCERER = i18n.translate('xpack.securitySolution.indexPatterns.dataSourcesLabel', { + defaultMessage: 'Data sources', }); -export const CHANGE_INDEX_PATTERNS = i18n.translate('xpack.securitySolution.indexPatterns.help', { - defaultMessage: 'Change index patterns', +export const ALL_DEFAULT = i18n.translate('xpack.securitySolution.indexPatterns.allDefault', { + defaultMessage: 'All default', }); -export const ADD_INDEX_PATTERNS = i18n.translate('xpack.securitySolution.indexPatterns.add', { - defaultMessage: 'Configure Kibana index patterns', +export const SELECT_INDEX_PATTERNS = i18n.translate('xpack.securitySolution.indexPatterns.help', { + defaultMessage: 'Data sources selection', }); -export const CONFIGURE_INDEX_PATTERNS = i18n.translate( - 'xpack.securitySolution.indexPatterns.configure', +export const SAVE_INDEX_PATTERNS = i18n.translate('xpack.securitySolution.indexPatterns.save', { + defaultMessage: 'Save', +}); + +export const INDEX_PATTERNS_SELECTION_LABEL = i18n.translate( + 'xpack.securitySolution.indexPatterns.selectionLabel', { - defaultMessage: - 'Configure additional Kibana index patterns to see them become available in the Security Solution', + defaultMessage: 'Choose the source of the data on this page', } ); @@ -33,3 +36,17 @@ export const DISABLED_INDEX_PATTERNS = i18n.translate( 'Disabled index patterns are recommended on this page, but first need to be configured in your Kibana index pattern settings', } ); + +export const INDEX_PATTERNS_RESET = i18n.translate( + 'xpack.securitySolution.indexPatterns.resetButton', + { + defaultMessage: 'Reset', + } +); + +export const PICK_INDEX_PATTERNS = i18n.translate( + 'xpack.securitySolution.indexPatterns.pickIndexPatternsCombo', + { + defaultMessage: 'Pick index patterns', + } +); diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/helpers.ts b/x-pack/plugins/security_solution/public/common/components/top_n/helpers.ts index b654eaf17b47be..79cbd87cda2011 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/components/top_n/helpers.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EventType } from '../../../timelines/store/timeline/model'; +import { TimelineEventsType } from '../../../../common/types/timeline'; import * as i18n from './translations'; export interface TopNOption { inputDisplay: string; - value: EventType; + value: TimelineEventsType; 'data-test-subj': string; } @@ -52,8 +52,8 @@ export const defaultOptions = [...rawEvents, ...alertEvents]; * is always in sync with the `EventType` chosen by the user in * the active timeline. */ -export const getOptions = (activeTimelineEventType?: EventType): TopNOption[] => { - switch (activeTimelineEventType) { +export const getOptions = (activeTimelineEventsType?: TimelineEventsType): TopNOption[] => { + switch (activeTimelineEventsType) { case 'all': return allEvents; case 'raw': diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx index 31318122eb5644..594bffbd4ff63e 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx @@ -168,6 +168,17 @@ const store = createStore( storage ); +let testProps = { + browserFields: mockBrowserFields, + field, + indexNames: [], + indexPattern: mockIndexPattern, + timelineId: TimelineId.hostsPageExternalAlerts, + toggleTopN: jest.fn(), + onFilterAdded: jest.fn(), + value, +}; + describe('StatefulTopN', () => { // Suppress warnings about "react-beautiful-dnd" /* eslint-disable no-console */ @@ -189,16 +200,7 @@ describe('StatefulTopN', () => { wrapper = mount( - + ); @@ -277,19 +279,14 @@ describe('StatefulTopN', () => { filterManager, }, }; + testProps = { + ...testProps, + timelineId: TimelineId.active, + }; wrapper = mount( - + ); @@ -345,37 +342,33 @@ describe('StatefulTopN', () => { expect(props.to).toEqual('2020-04-15T03:46:09.047Z'); }); }); + describe('rendering in a NON-active timeline context', () => { + test(`defaults to the 'Alert events' option when rendering in a NON-active timeline context (e.g. the Alerts table on the Detections page) when 'documentType' from 'useTimelineTypeContext()' is 'alerts'`, () => { + const filterManager = new FilterManager(mockUiSettingsForFilterManager); - test(`defaults to the 'Alert events' option when rendering in a NON-active timeline context (e.g. the Alerts table on the Detections page) when 'documentType' from 'useTimelineTypeContext()' is 'alerts'`, () => { - const filterManager = new FilterManager(mockUiSettingsForFilterManager); + const manageTimelineForTesting = { + [TimelineId.active]: { + ...getTimelineDefaults(TimelineId.active), + filterManager, + documentType: 'alerts', + }, + }; - const manageTimelineForTesting = { - [TimelineId.active]: { - ...getTimelineDefaults(TimelineId.active), - filterManager, - documentType: 'alerts', - }, - }; - - const wrapper = mount( - - - - - - ); - - const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props; - - expect(props.defaultView).toEqual('alert'); + testProps = { + ...testProps, + timelineId: TimelineId.detectionsPage, + }; + const wrapper = mount( + + + + + + ); + + const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props; + + expect(props.defaultView).toEqual('alert'); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx index d71242329bcda9..9c81cb57335a58 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx @@ -74,7 +74,7 @@ interface OwnProps { browserFields: BrowserFields; field: string; indexPattern: IIndexPattern; - indexToAdd: string[] | null; + indexNames: string[]; timelineId?: string; toggleTopN: () => void; onFilterAdded?: () => void; @@ -93,7 +93,7 @@ const StatefulTopNComponent: React.FC = ({ dataProviders, field, indexPattern, - indexToAdd, + indexNames, globalFilters = EMPTY_FILTERS, globalQuery = EMPTY_QUERY, kqlMode, @@ -109,7 +109,6 @@ const StatefulTopNComponent: React.FC = ({ const options = getOptions( timelineId === TimelineId.active ? activeTimelineEventType : undefined ); - return ( = ({ filters={timelineId === TimelineId.active ? EMPTY_FILTERS : globalFilters} from={timelineId === TimelineId.active ? activeTimelineFrom : from} indexPattern={indexPattern} - indexToAdd={indexToAdd} + indexNames={indexNames} options={options} query={timelineId === TimelineId.active ? EMPTY_QUERY : globalQuery} setAbsoluteRangeDatePicker={setAbsoluteRangeDatePicker} diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx index 667d1816e8f079..829f918ddfe1b0 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx @@ -13,6 +13,8 @@ import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { allEvents, defaultOptions } from './helpers'; import { TopN } from './top_n'; +import { TimelineEventsType } from '../../../../common/types/timeline'; +import { InputsModelId } from '../../store/inputs/constants'; jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -103,29 +105,34 @@ describe('TopN', () => { const query = { query: '', language: 'kuery' }; + const toggleTopN = jest.fn(); + const eventTypes: { [id: string]: TimelineEventsType } = { + raw: 'raw', + alert: 'alert', + all: 'all', + }; + let testProps = { + defaultView: eventTypes.raw, + field, + filters: [], + from: '2020-04-14T00:31:47.695Z', + indexNames: [], + indexPattern: mockIndexPattern, + options: defaultOptions, + query, + setAbsoluteRangeDatePicker, + setAbsoluteRangeDatePickerTarget: 'global' as InputsModelId, + setQuery: jest.fn(), + to: '2020-04-15T00:31:47.695Z', + toggleTopN, + value, + }; describe('common functionality', () => { - let toggleTopN: () => void; let wrapper: ReactWrapper; - beforeEach(() => { - toggleTopN = jest.fn(); wrapper = mount( - + ); }); @@ -143,28 +150,12 @@ describe('TopN', () => { }); describe('events view', () => { - let toggleTopN: () => void; let wrapper: ReactWrapper; beforeEach(() => { - toggleTopN = jest.fn(); wrapper = mount( - + ); }); @@ -181,37 +172,25 @@ describe('TopN', () => { }); describe('alerts view', () => { - let toggleTopN: () => void; let wrapper: ReactWrapper; beforeEach(() => { - toggleTopN = jest.fn(); + testProps = { + ...testProps, + defaultView: eventTypes.alert, + }; wrapper = mount( - + ); }); - test(`it renders SignalsByCategory when defaultView is 'signal'`, () => { + test(`it renders SignalsByCategory when defaultView is 'alert'`, () => { expect(wrapper.find('[data-test-subj="alerts-histogram-panel"]').exists()).toBe(true); }); - test(`it does NOT render EventsByDataset when defaultView is 'signal'`, () => { + test(`it does NOT render EventsByDataset when defaultView is 'alert'`, () => { expect( wrapper.find('[data-test-subj="eventsByDatasetOverview-uuid.v4()Panel"]').exists() ).toBe(false); @@ -222,24 +201,14 @@ describe('TopN', () => { let wrapper: ReactWrapper; beforeEach(() => { + testProps = { + ...testProps, + defaultView: eventTypes.all, + options: allEvents, + }; wrapper = mount( - + ); }); diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx index 064241a7216f46..4f0a71dcc3ebba 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -14,7 +14,7 @@ import { EventsByDataset } from '../../../overview/components/events_by_dataset' import { SignalsByCategory } from '../../../overview/components/signals_by_category'; import { Filter, IIndexPattern, Query } from '../../../../../../../src/plugins/data/public'; import { InputsModelId } from '../../store/inputs/constants'; -import { EventType } from '../../../timelines/store/timeline/model'; +import { TimelineEventsType } from '../../../../common/types/timeline'; import { TopNOption } from './helpers'; import * as i18n from './translations'; @@ -45,11 +45,11 @@ const TopNContent = styled.div` export interface Props extends Pick { combinedQueries?: string; - defaultView: EventType; + defaultView: TimelineEventsType; field: string; filters: Filter[]; indexPattern: IIndexPattern; - indexToAdd?: string[] | null; + indexNames: string[]; options: TopNOption[]; query: Query; setAbsoluteRangeDatePicker: ActionCreator<{ @@ -75,7 +75,7 @@ const TopNComponent: React.FC = ({ field, from, indexPattern, - indexToAdd, + indexNames, options, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, @@ -85,8 +85,10 @@ const TopNComponent: React.FC = ({ to, toggleTopN, }) => { - const [view, setView] = useState(defaultView); - const onViewSelected = useCallback((value: string) => setView(value as EventType), [setView]); + const [view, setView] = useState(defaultView); + const onViewSelected = useCallback((value: string) => setView(value as TimelineEventsType), [ + setView, + ]); useEffect(() => { setView(defaultView); @@ -123,7 +125,7 @@ const TopNComponent: React.FC = ({ from={from} headerChildren={headerChildren} indexPattern={indexPattern} - indexToAdd={indexToAdd} + indexNames={indexNames} onlyField={field} query={query} setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget} diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/constants.ts b/x-pack/plugins/security_solution/public/common/components/url_state/constants.ts index 5a4aec93dd9aaa..e5c09d229808b7 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/constants.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/constants.ts @@ -17,6 +17,7 @@ export enum CONSTANTS { networkPage = 'network.page', overviewPage = 'overview.page', savedQuery = 'savedQuery', + sourcerer = 'sourcerer', timeline = 'timeline', timelinePage = 'timeline.page', timerange = 'timerange', diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts b/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts index 6052913b4183b1..a915b1c9d09a7d 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts @@ -22,6 +22,8 @@ import { formatDate } from '../super_date_picker'; import { NavTab } from '../navigation/types'; import { CONSTANTS, UrlStateType } from './constants'; import { ReplaceStateInLocation, UpdateUrlStateString } from './types'; +import { sourcererSelectors } from '../../store/sourcerer'; +import { SourcererScopeName, SourcererScopePatterns } from '../../store/sourcerer/model'; export const decodeRisonUrlState = (value: string | undefined): T | null => { try { @@ -118,6 +120,7 @@ export const makeMapStateToProps = () => { const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); const getGlobalSavedQuerySelector = inputsSelectors.globalSavedQuerySelector(); const getTimeline = timelineSelectors.getTimelineByIdSelector(); + const getSourcererScopes = sourcererSelectors.scopesSelector(); const mapStateToProps = (state: State) => { const inputState = getInputsSelector(state); const { linkTo: globalLinkTo, timerange: globalTimerange } = inputState.global; @@ -147,10 +150,16 @@ export const makeMapStateToProps = () => { [CONSTANTS.savedQuery]: savedQuery.id, }; } + const sourcerer = getSourcererScopes(state); + const activeScopes: SourcererScopeName[] = Object.keys(sourcerer) as SourcererScopeName[]; + const selectedPatterns: SourcererScopePatterns = activeScopes + .filter((scope) => scope === SourcererScopeName.default) + .reduce((acc, scope) => ({ ...acc, [scope]: sourcerer[scope]?.selectedPatterns }), {}); return { urlState: { ...searchAttr, + [CONSTANTS.sourcerer]: selectedPatterns, [CONSTANTS.timerange]: { global: { [CONSTANTS.timerange]: globalTimerange, @@ -217,6 +226,17 @@ export const updateUrlStateString = ({ urlStateKey: urlKey, }); } + } else if (urlKey === CONSTANTS.sourcerer) { + const sourcererState = decodeRisonUrlState(newUrlStateString); + if (sourcererState != null && Object.keys(sourcererState).length > 0) { + return replaceStateInLocation({ + history, + pathName, + search, + urlStateToReplace: sourcererState, + urlStateKey: urlKey, + }); + } } else if (urlKey === CONSTANTS.filters) { const queryState = decodeRisonUrlState(newUrlStateString); if (isEmpty(queryState)) { diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx index 72df9d613abacb..fc970c066e8a5c 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx @@ -161,7 +161,7 @@ describe('UrlStateContainer', () => { ).toEqual({ hash: '', pathname: examplePath, - search: `?query=(language:kuery,query:'host.name:%22siem-es%22')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, + search: `?query=(language:kuery,query:'host.name:%22siem-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))`, state: '', }); } diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx index 723f2d235864fe..9e845ec538aa0f 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx @@ -83,7 +83,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => hash: '', pathname: '/network', search: - "?query=(language:kuery,query:'host.name:%22siem-es%22')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "?query=(language:kuery,query:'host.name:%22siem-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", state: '', }); }); @@ -114,7 +114,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => hash: '', pathname: '/network', search: - "?query=(language:kuery,query:'host.name:%22siem-es%22')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "?query=(language:kuery,query:'host.name:%22siem-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", state: '', }); }); @@ -147,7 +147,40 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => hash: '', pathname: '/network', search: - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))&timeline=(id:hello_timeline_id,isOpen:!t)", + "?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))&timeline=(id:hello_timeline_id,isOpen:!t)", + state: '', + }); + }); + + test('sourcerer redux state updates the url', () => { + mockProps = getMockPropsObj({ + page: CONSTANTS.networkPage, + examplePath: '/network', + namespaceLower: 'network', + pageName: SecurityPageName.network, + detailName: undefined, + }).noSearch.undefinedQuery; + + const wrapper = mount( + useUrlStateHooks(args)} /> + ); + const newUrlState = { + ...mockProps.urlState, + sourcerer: ['cool', 'patterns'], + }; + + wrapper.setProps({ + hookProps: { ...mockProps, urlState: newUrlState, isInitializing: false }, + }); + wrapper.update(); + + expect( + mockHistory.replace.mock.calls[mockHistory.replace.mock.calls.length - 1][0] + ).toStrictEqual({ + hash: '', + pathname: '/network', + search: + "?sourcerer=!(cool,patterns)&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", state: '', }); }); @@ -176,7 +209,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => hash: '', pathname: examplePath, search: - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + "?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", state: '', }); } @@ -204,7 +237,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => expect( mockHistory.replace.mock.calls[mockHistory.replace.mock.calls.length - 1][0].search ).toEqual( - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" + "?sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" ); wrapper.setProps({ hookProps: updatedProps }); @@ -213,7 +246,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => expect( mockHistory.replace.mock.calls[mockHistory.replace.mock.calls.length - 1][0].search ).toEqual( - "?query=(language:kuery,query:'host.name:%22siem-es%22')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" + "?query=(language:kuery,query:'host.name:%22siem-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" ); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx index 6eccf52ec72da2..1e77ae77666301 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx @@ -8,7 +8,7 @@ import { get, isEmpty } from 'lodash/fp'; import { Dispatch } from 'redux'; import { Query, Filter } from '../../../../../../../src/plugins/data/public'; -import { inputsActions } from '../../store/actions'; +import { inputsActions, sourcererActions } from '../../store/actions'; import { InputsModelId, TimeRangeKinds } from '../../store/inputs/constants'; import { UrlInputsModel, @@ -22,6 +22,8 @@ import { decodeRisonUrlState } from './helpers'; import { normalizeTimeRange } from './normalize_time_range'; import { DispatchSetInitialStateFromUrl, SetInitialStateFromUrl } from './types'; import { queryTimelineById } from '../../../timelines/components/open_timeline/helpers'; +import { SourcererScopeName, SourcererScopePatterns } from '../../store/sourcerer/model'; +import { SecurityPageName } from '../../../../common/constants'; export const dispatchSetInitialStateFromUrl = ( dispatch: Dispatch @@ -40,6 +42,22 @@ export const dispatchSetInitialStateFromUrl = ( if (urlKey === CONSTANTS.timerange) { updateTimerange(newUrlStateString, dispatch); } + if (urlKey === CONSTANTS.sourcerer) { + const sourcererState = decodeRisonUrlState(newUrlStateString); + if (sourcererState != null) { + const activeScopes: SourcererScopeName[] = Object.keys(sourcererState).filter( + (key) => !(key === SourcererScopeName.default && pageName === SecurityPageName.detections) + ) as SourcererScopeName[]; + activeScopes.forEach((scope) => + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: scope, + selectedPatterns: sourcererState[scope] ?? [], + }) + ) + ); + } + } if (urlKey === CONSTANTS.appQuery && indexPattern != null) { const appQuery = decodeRisonUrlState(newUrlStateString); diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts b/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts index 8d471e843320c2..6f04226fa3a198 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts @@ -117,6 +117,7 @@ export const defaultProps: UrlStateContainerPropTypes = { id: '', isOpen: false, }, + [CONSTANTS.sourcerer]: {}, }, setInitialStateFromUrl: dispatchSetInitialStateFromUrl(mockDispatch), updateTimeline: (jest.fn() as unknown) as DispatchUpdateTimeline, diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/types.ts b/x-pack/plugins/security_solution/public/common/components/url_state/types.ts index f383e181323854..301771a4db6b90 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/types.ts @@ -22,11 +22,13 @@ import { DispatchUpdateTimeline } from '../../../timelines/components/open_timel import { NavTab } from '../navigation/types'; import { CONSTANTS, UrlStateType } from './constants'; +import { SourcererScopePatterns } from '../../store/sourcerer/model'; export const ALL_URL_STATE_KEYS: KeyUrlState[] = [ CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ]; @@ -36,6 +38,7 @@ export const URL_STATE_KEYS: Record = { CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ], @@ -43,6 +46,7 @@ export const URL_STATE_KEYS: Record = { CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ], @@ -51,6 +55,7 @@ export const URL_STATE_KEYS: Record = { CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ], @@ -58,6 +63,7 @@ export const URL_STATE_KEYS: Record = { CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ], @@ -65,6 +71,7 @@ export const URL_STATE_KEYS: Record = { CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ], @@ -72,6 +79,7 @@ export const URL_STATE_KEYS: Record = { CONSTANTS.appQuery, CONSTANTS.filters, CONSTANTS.savedQuery, + CONSTANTS.sourcerer, CONSTANTS.timerange, CONSTANTS.timeline, ], @@ -93,6 +101,7 @@ export interface UrlState { [CONSTANTS.appQuery]?: Query; [CONSTANTS.filters]?: Filter[]; [CONSTANTS.savedQuery]?: string; + [CONSTANTS.sourcerer]: SourcererScopePatterns; [CONSTANTS.timerange]: UrlInputsModel; [CONSTANTS.timeline]: TimelineUrl; } diff --git a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx index f6ebbb990f2234..489ccb23c9b2c4 100644 --- a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx @@ -29,6 +29,7 @@ const AnomaliesQueryTabBodyComponent: React.FC = ({ AnomaliesTableComponent, flowTarget, ip, + indexNames, }) => { const { jobs } = useInstalledSecurityJobs(); const [anomalyScore] = useUiSetting$(DEFAULT_ANOMALY_SCORE); @@ -57,6 +58,7 @@ const AnomaliesQueryTabBodyComponent: React.FC = ({ endDate={endDate} filterQuery={mergedFilterQuery} id={ID} + indexNames={indexNames} setQuery={setQuery} startDate={startDate} {...histogramConfigs} diff --git a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts index d716df70246f78..3ce4b8b6d4494a 100644 --- a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts +++ b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts @@ -24,6 +24,7 @@ export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & { deleteQuery?: ({ id }: { id: string }) => void; endDate: GlobalTimeArgs['to']; flowTarget?: FlowTarget; + indexNames: string[]; narrowDateRange: NarrowDateRange; setQuery: GlobalTimeArgs['setQuery']; startDate: GlobalTimeArgs['from']; diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts index 3d79c83dc42cb9..dc2d6605bc292d 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { useKibana } from '../../../../common/lib/kibana'; import { @@ -23,10 +22,10 @@ import { isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; -import { useWithSource } from '../../source'; import * as i18n from './translations'; +import { DocValueFields } from '../../../../../common/search_strategy'; -// const ID = 'timelineEventsLastEventTimeQuery'; +const ID = 'timelineEventsLastEventTimeQuery'; export interface UseTimelineLastEventTimeArgs { lastSeen: string | null; @@ -35,26 +34,29 @@ export interface UseTimelineLastEventTimeArgs { } interface UseTimelineLastEventTimeProps { + docValueFields: DocValueFields[]; indexKey: LastEventIndexKey; + indexNames: string[]; details: LastTimeDetails; } export const useTimelineLastEventTime = ({ + docValueFields, indexKey, + indexNames, details, }: UseTimelineLastEventTimeProps): [boolean, UseTimelineLastEventTimeArgs] => { - const { data, notifications, uiSettings } = useKibana().services; - const { docValueFields } = useWithSource('default'); + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [TimelineLastEventTimeRequest, setTimelineLastEventTimeRequest] = useState< TimelineEventsLastEventTimeRequestOptions >({ - defaultIndex, - factoryQueryType: TimelineEventsQueries.lastEventTime, + defaultIndex: indexNames, docValueFields, + factoryQueryType: TimelineEventsQueries.lastEventTime, + id: ID, indexKey, details, }); @@ -133,7 +135,8 @@ export const useTimelineLastEventTime = ({ setTimelineLastEventTimeRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, + docValueFields, indexKey, details, }; @@ -142,7 +145,7 @@ export const useTimelineLastEventTime = ({ } return prevRequest; }); - }, [defaultIndex, details, indexKey]); + }, [indexNames, details, docValueFields, indexKey]); useEffect(() => { timelineLastEventTimeSearch(TimelineLastEventTimeRequest); diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts index 8e0c133f95b4d3..ca8bcc637717b4 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts @@ -5,14 +5,13 @@ */ import deepEqual from 'fast-deep-equal'; -import { isEmpty, noop } from 'lodash/fp'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { noop } from 'lodash/fp'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel } from '../../../common/store'; import { createFilter } from '../../../common/containers/helpers'; -import { useKibana, useUiSetting$ } from '../../../common/lib/kibana'; +import { useKibana } from '../../../common/lib/kibana'; import { MatrixHistogramQuery, MatrixHistogramRequestOptions, @@ -40,25 +39,18 @@ export const useMatrixHistogram = ({ errorMessage, filterQuery, histogramType, - indexToAdd, + indexNames, stackByField, startDate, }: MatrixHistogramQueryProps): [boolean, UseMatrixHistogramArgs] => { const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const [configIndex] = useUiSetting$(DEFAULT_INDEX_KEY); - const defaultIndex = useMemo(() => { - if (indexToAdd != null && !isEmpty(indexToAdd)) { - return [...configIndex, ...indexToAdd]; - } - return configIndex; - }, [configIndex, indexToAdd]); const [loading, setLoading] = useState(false); const [matrixHistogramRequest, setMatrixHistogramRequest] = useState< MatrixHistogramRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: MatrixHistogramQuery, filterQuery: createFilter(filterQuery), histogramType, @@ -140,7 +132,7 @@ export const useMatrixHistogram = ({ setMatrixHistogramRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -153,7 +145,7 @@ export const useMatrixHistogram = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, startDate]); + }, [indexNames, endDate, filterQuery, startDate]); useEffect(() => { hostsSearch(matrixHistogramRequest); diff --git a/x-pack/plugins/security_solution/public/common/containers/query_template.tsx b/x-pack/plugins/security_solution/public/common/containers/query_template.tsx index eaa43c255a944a..80791d91481a8a 100644 --- a/x-pack/plugins/security_solution/public/common/containers/query_template.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/query_template.tsx @@ -14,6 +14,7 @@ import { DocValueFields } from './source'; export { DocValueFields }; export interface QueryTemplateProps { + indexNames: string[]; docValueFields?: DocValueFields[]; id?: string; endDate?: string; diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.gql_query.ts b/x-pack/plugins/security_solution/public/common/containers/source/index.gql_query.ts deleted file mode 100644 index 630515c5cbed48..00000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.gql_query.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const sourceQuery = gql` - query SourceQuery($sourceId: ID = "default", $defaultIndex: [String!]!) { - source(id: $sourceId) { - id - status { - indicesExist(defaultIndex: $defaultIndex) - indexFields(defaultIndex: $defaultIndex) { - category - description - example - indexes - name - searchable - type - aggregatable - format - esTypes - subType - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx deleted file mode 100644 index 8ba7f7da7b8e37..00000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx +++ /dev/null @@ -1,109 +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 { act, renderHook } from '@testing-library/react-hooks'; - -import { useWithSource, indicesExistOrDataTemporarilyUnavailable } from '.'; -import { NO_ALERT_INDEX } from '../../../../common/constants'; -import { mockBrowserFields, mockIndexFields, mocksSource } from './mock'; - -jest.mock('../../lib/kibana'); -jest.mock('../../utils/apollo_context', () => ({ - useApolloClient: jest.fn().mockReturnValue({ - query: jest.fn().mockImplementation(() => Promise.resolve(mocksSource[0].result)), - }), -})); - -describe('Index Fields & Browser Fields', () => { - test('At initialization the value of indicesExists should be true', async () => { - const { result, waitForNextUpdate } = renderHook(() => useWithSource()); - const initialResult = result.current; - - await waitForNextUpdate(); - - return expect(initialResult).toEqual({ - browserFields: {}, - docValueFields: [], - errorMessage: null, - indexPattern: { - fields: [], - title: - 'apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', - }, - indicesExist: true, - loading: true, - }); - }); - - test('returns memoized value', async () => { - const { result, waitForNextUpdate, rerender } = renderHook(() => useWithSource()); - await waitForNextUpdate(); - - const result1 = result.current; - act(() => rerender()); - const result2 = result.current; - - return expect(result1).toBe(result2); - }); - - test('Index Fields', async () => { - const { result, waitForNextUpdate } = renderHook(() => useWithSource()); - - await waitForNextUpdate(); - - return expect(result).toEqual({ - current: { - indicesExist: true, - browserFields: mockBrowserFields, - docValueFields: [ - { - field: '@timestamp', - format: 'date_time', - }, - { - field: 'event.end', - format: 'date_time', - }, - ], - indexPattern: { - fields: mockIndexFields, - title: - 'apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', - }, - loading: false, - errorMessage: null, - }, - error: undefined, - }); - }); - - test('Make sure we are not querying for NO_ALERT_INDEX and it is not includes in the index pattern', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useWithSource('default', [NO_ALERT_INDEX]) - ); - - await waitForNextUpdate(); - return expect(result.current.indexPattern.title).toEqual( - 'apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*' - ); - }); - - describe('indicesExistOrDataTemporarilyUnavailable', () => { - test('it returns true when undefined', () => { - let undefVar; - const result = indicesExistOrDataTemporarilyUnavailable(undefVar); - expect(result).toBeTruthy(); - }); - test('it returns true when true', () => { - const result = indicesExistOrDataTemporarilyUnavailable(true); - expect(result).toBeTruthy(); - }); - test('it returns false when false', () => { - const result = indicesExistOrDataTemporarilyUnavailable(false); - expect(result).toBeFalsy(); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx index ffbecf9e3d4334..4b1db8a2871bd8 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx @@ -4,42 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isUndefined } from 'lodash'; import { set } from '@elastic/safer-lodash-set/fp'; -import { get, keyBy, pick, isEmpty } from 'lodash/fp'; -import { useEffect, useMemo, useState } from 'react'; +import { keyBy, pick, isEmpty, isEqual, isUndefined } from 'lodash/fp'; import memoizeOne from 'memoize-one'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; -import { DEFAULT_INDEX_KEY, NO_ALERT_INDEX } from '../../../../common/constants'; -import { useUiSetting$ } from '../../lib/kibana'; +import { useKibana } from '../../lib/kibana'; +import { + IndexField, + IndexFieldsStrategyResponse, + IndexFieldsStrategyRequest, + BrowserField, + BrowserFields, +} from '../../../../common/search_strategy/index_fields'; +import { AbortError } from '../../../../../../../src/plugins/data/common'; +import * as i18n from './translations'; +import { SourcererScopeName } from '../../store/sourcerer/model'; +import { sourcererActions, sourcererSelectors } from '../../store/sourcerer'; -import { IndexField, SourceQuery } from '../../../graphql/types'; +import { State } from '../../store'; +import { DocValueFields } from '../../../../common/search_strategy/common'; -import { sourceQuery } from './index.gql_query'; -import { useApolloClient } from '../../utils/apollo_context'; - -export { sourceQuery }; - -export interface BrowserField { - aggregatable: boolean; - category: string; - description: string | null; - example: string | number | null; - fields: Readonly>>; - format: string; - indexes: string[]; - name: string; - searchable: boolean; - type: string; -} - -export interface DocValueFields { - field: string; - format: string; -} - -export type BrowserFields = Readonly>>; +export { BrowserField, BrowserFields, DocValueFields }; export const getAllBrowserFields = (browserFields: BrowserFields): Array> => Object.values(browserFields).reduce>>( @@ -85,14 +73,12 @@ export const getDocValueFields = memoizeOne( (_title: string, fields: IndexField[]): DocValueFields[] => fields && fields.length > 0 ? fields.reduce((accumulator: DocValueFields[], field: IndexField) => { - if (field.type === 'date' && accumulator.length < 100) { - const format: string = - field.format != null && !isEmpty(field.format) ? field.format : 'date_time'; + if (field.readFromDocValues && accumulator.length < 100) { return [ ...accumulator, { field: field.name, - format, + format: field.format, }, ]; } @@ -107,115 +93,196 @@ export const indicesExistOrDataTemporarilyUnavailable = ( indicesExist: boolean | null | undefined ) => indicesExist || isUndefined(indicesExist); -const EMPTY_BROWSER_FIELDS = {}; -const EMPTY_DOCVALUE_FIELD: DocValueFields[] = []; +const DEFAULT_BROWSER_FIELDS = {}; +const DEFAULT_INDEX_PATTERNS = { fields: [], title: '' }; +const DEFAULT_DOC_VALUE_FIELDS: DocValueFields[] = []; -interface UseWithSourceState { +interface FetchIndexReturn { browserFields: BrowserFields; docValueFields: DocValueFields[]; - errorMessage: string | null; - indexPattern: IIndexPattern; - indicesExist: boolean | undefined | null; - loading: boolean; + indexes: string[]; + indexExists: boolean; + indexPatterns: IIndexPattern; } -export const useWithSource = ( - sourceId = 'default', - indexToAdd?: string[] | null, - onlyCheckIndexToAdd?: boolean, - // Fun fact: When using this hook multiple times within a component (e.g. add_exception_modal & edit_exception_modal), - // the apolloClient will perform queryDeduplication and prevent the first query from executing. A deep compare is not - // performed on `indices`, so another field must be passed to circumvent this. - // For details, see https://github.com/apollographql/react-apollo/issues/2202 - queryDeduplication = 'default' -) => { - const [configIndex] = useUiSetting$(DEFAULT_INDEX_KEY); - const defaultIndex = useMemo(() => { - const filterIndexAdd = (indexToAdd ?? []).filter((item) => item !== NO_ALERT_INDEX); - if (!isEmpty(filterIndexAdd)) { - return onlyCheckIndexToAdd ? filterIndexAdd : [...configIndex, ...filterIndexAdd]; - } - return configIndex; - }, [configIndex, indexToAdd, onlyCheckIndexToAdd]); - - const [state, setState] = useState({ - browserFields: EMPTY_BROWSER_FIELDS, - docValueFields: EMPTY_DOCVALUE_FIELD, - errorMessage: null, - indexPattern: getIndexFields(defaultIndex.join(), []), - indicesExist: indicesExistOrDataTemporarilyUnavailable(undefined), - loading: true, +export const useFetchIndex = ( + indexNames: string[], + onlyCheckIfIndicesExist: boolean = false +): [boolean, FetchIndexReturn] => { + const { data, notifications } = useKibana().services; + const abortCtrl = useRef(new AbortController()); + const previousIndexesName = useRef([]); + const [isLoading, setLoading] = useState(true); + + const [state, setState] = useState({ + browserFields: DEFAULT_BROWSER_FIELDS, + docValueFields: DEFAULT_DOC_VALUE_FIELDS, + indexes: indexNames, + indexExists: true, + indexPatterns: DEFAULT_INDEX_PATTERNS, }); - const apolloClient = useApolloClient(); + const indexFieldsSearch = useCallback( + (iNames) => { + let didCancel = false; + const asyncSearch = async () => { + abortCtrl.current = new AbortController(); + setLoading(true); + const searchSubscription$ = data.search + .search( + { indices: iNames, onlyCheckIfIndicesExist }, + { + abortSignal: abortCtrl.current.signal, + strategy: 'securitySolutionIndexFields', + } + ) + .subscribe({ + next: (response) => { + if (!response.isPartial && !response.isRunning) { + if (!didCancel) { + const stringifyIndices = response.indicesExist.sort().join(); + previousIndexesName.current = response.indicesExist; + setLoading(false); + setState({ + browserFields: getBrowserFields(stringifyIndices, response.indexFields), + docValueFields: getDocValueFields(stringifyIndices, response.indexFields), + indexes: response.indicesExist, + indexExists: response.indicesExist.length > 0, + indexPatterns: getIndexFields(stringifyIndices, response.indexFields), + }); + } + searchSubscription$.unsubscribe(); + } else if (!didCancel && response.isPartial && !response.isRunning) { + setLoading(false); + notifications.toasts.addWarning(i18n.ERROR_BEAT_FIELDS); + searchSubscription$.unsubscribe(); + } + }, + error: (msg) => { + if (!didCancel) { + setLoading(false); + } - useEffect(() => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - - async function fetchSource() { - if (!apolloClient) return; - - setState((prevState) => ({ ...prevState, loading: true })); - - try { - const result = await apolloClient.query< - SourceQuery.Query, - SourceQuery.Variables & { queryDeduplication: string } - >({ - query: sourceQuery, - fetchPolicy: 'cache-first', - variables: { - sourceId, - defaultIndex, - queryDeduplication, - }, - context: { - fetchOptions: { - signal: abortCtrl.signal, + if (!(msg instanceof AbortError)) { + notifications.toasts.addDanger({ + text: msg.message, + title: i18n.FAIL_BEAT_FIELDS, + }); + } }, - }, - }); - - if (isSubscribed) { - setState({ - loading: false, - indicesExist: indicesExistOrDataTemporarilyUnavailable( - get('data.source.status.indicesExist', result) - ), - browserFields: getBrowserFields( - defaultIndex.join(), - get('data.source.status.indexFields', result) - ), - docValueFields: getDocValueFields( - defaultIndex.join(), - get('data.source.status.indexFields', result) - ), - indexPattern: getIndexFields( - defaultIndex.join(), - get('data.source.status.indexFields', result) - ), - errorMessage: null, }); - } - } catch (error) { - if (isSubscribed) { - setState((prevState) => ({ - ...prevState, - loading: false, - errorMessage: error.message, - })); - } - } + }; + abortCtrl.current.abort(); + asyncSearch(); + return () => { + didCancel = true; + abortCtrl.current.abort(); + }; + }, + [data.search, notifications.toasts, onlyCheckIfIndicesExist] + ); + + useEffect(() => { + if (!isEmpty(indexNames) && !isEqual(previousIndexesName.current, indexNames)) { + indexFieldsSearch(indexNames); } + }, [indexNames, indexFieldsSearch, previousIndexesName]); + + return [isLoading, state]; +}; + +export const useIndexFields = (sourcererScopeName: SourcererScopeName) => { + const { data, notifications } = useKibana().services; + const abortCtrl = useRef(new AbortController()); + const dispatch = useDispatch(); + const previousIndexesName = useRef([]); + + const indexNamesSelectedSelector = useMemo( + () => sourcererSelectors.getIndexNamesSelectedSelector(), + [] + ); + const indexNames = useSelector( + (state) => indexNamesSelectedSelector(state, sourcererScopeName), + shallowEqual + ); - fetchSource(); + const setLoading = useCallback( + (loading: boolean) => { + dispatch(sourcererActions.setSourcererScopeLoading({ id: sourcererScopeName, loading })); + }, + [dispatch, sourcererScopeName] + ); + + const indexFieldsSearch = useCallback( + (indicesName) => { + let didCancel = false; + const asyncSearch = async () => { + abortCtrl.current = new AbortController(); + setLoading(true); + const searchSubscription$ = data.search + .search( + { indices: indicesName, onlyCheckIfIndicesExist: false }, + { + abortSignal: abortCtrl.current.signal, + strategy: 'securitySolutionIndexFields', + } + ) + .subscribe({ + next: (response) => { + if (!response.isPartial && !response.isRunning) { + if (!didCancel) { + const stringifyIndices = response.indicesExist.sort().join(); + previousIndexesName.current = response.indicesExist; + dispatch( + sourcererActions.setSource({ + id: sourcererScopeName, + payload: { + browserFields: getBrowserFields(stringifyIndices, response.indexFields), + docValueFields: getDocValueFields(stringifyIndices, response.indexFields), + errorMessage: null, + id: sourcererScopeName, + indexPattern: getIndexFields(stringifyIndices, response.indexFields), + indicesExist: response.indicesExist.length > 0, + loading: false, + }, + }) + ); + } + searchSubscription$.unsubscribe(); + } else if (!didCancel && response.isPartial && !response.isRunning) { + // TODO: Make response error status clearer + setLoading(false); + notifications.toasts.addWarning(i18n.ERROR_BEAT_FIELDS); + searchSubscription$.unsubscribe(); + } + }, + error: (msg) => { + if (!didCancel) { + setLoading(false); + } - return () => { - isSubscribed = false; - return abortCtrl.abort(); - }; - }, [apolloClient, sourceId, defaultIndex, queryDeduplication]); + if (!(msg instanceof AbortError)) { + notifications.toasts.addDanger({ + text: msg.message, + title: i18n.FAIL_BEAT_FIELDS, + }); + } + }, + }); + }; + abortCtrl.current.abort(); + asyncSearch(); + return () => { + didCancel = true; + abortCtrl.current.abort(); + }; + }, + [data.search, dispatch, notifications.toasts, setLoading, sourcererScopeName] + ); - return state; + useEffect(() => { + if (!isEmpty(indexNames) && !isEqual(previousIndexesName.current, indexNames)) { + indexFieldsSearch(indexNames); + } + }, [indexNames, indexFieldsSearch, previousIndexesName]); }; diff --git a/x-pack/plugins/security_solution/public/common/containers/source/mock.ts b/x-pack/plugins/security_solution/public/common/containers/source/mock.ts index bba6a15d739709..7fcd11f71f081f 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/mock.ts +++ b/x-pack/plugins/security_solution/public/common/containers/source/mock.ts @@ -5,347 +5,296 @@ */ import { DEFAULT_INDEX_PATTERN } from '../../../../common/constants'; +import { DocValueFields } from '../../../../common/search_strategy'; +import { BrowserFields } from '../../../../common/search_strategy/index_fields'; -import { BrowserFields, DocValueFields } from '.'; -import { sourceQuery } from './index.gql_query'; - -export const mocksSource = [ - { - request: { - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: DEFAULT_INDEX_PATTERN, - }, +export const mocksSource = { + indexFields: [ + { + category: 'base', + description: + 'Date/time when the event originated. For log events this is the date/time when the event was generated, and not when it was read. Required field for all events.', + example: '2016-05-23T08:05:34.853Z', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: '@timestamp', + searchable: true, + type: 'date', + aggregatable: true, }, - result: { - data: { - source: { - id: 'default', - configuration: {}, - status: { - indicesExist: true, - winlogbeatIndices: [ - 'winlogbeat-7.0.0-2019.02.17', - 'winlogbeat-7.0.0-2019.02.18', - 'winlogbeat-7.0.0-2019.02.19', - 'winlogbeat-7.0.0-2019.02.20', - 'winlogbeat-7.0.0-2019.02.21', - 'winlogbeat-7.0.0-2019.02.21-000001', - 'winlogbeat-7.0.0-2019.02.22', - 'winlogbeat-8.0.0-2019.02.19-000001', - ], - auditbeatIndices: [ - 'auditbeat-7.0.0-2019.02.17', - 'auditbeat-7.0.0-2019.02.18', - 'auditbeat-7.0.0-2019.02.19', - 'auditbeat-7.0.0-2019.02.20', - 'auditbeat-7.0.0-2019.02.21', - 'auditbeat-7.0.0-2019.02.21-000001', - 'auditbeat-7.0.0-2019.02.22', - 'auditbeat-8.0.0-2019.02.19-000001', - ], - filebeatIndices: [ - 'filebeat-7.0.0-iot-2019.06', - 'filebeat-7.0.0-iot-2019.07', - 'filebeat-7.0.0-iot-2019.08', - 'filebeat-7.0.0-iot-2019.09', - 'filebeat-7.0.0-iot-2019.10', - 'filebeat-8.0.0-2019.02.19-000001', - ], - indexFields: [ - { - category: 'base', - description: - 'Date/time when the event originated. For log events this is the date/time when the event was generated, and not when it was read. Required field for all events.', - example: '2016-05-23T08:05:34.853Z', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: '@timestamp', - searchable: true, - type: 'date', - aggregatable: true, - }, - { - category: 'agent', - description: - 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.ephemeral_id', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'agent', - description: null, - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.hostname', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'agent', - description: - 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', - example: '8a4f500d', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.id', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'agent', - description: - 'Name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', - example: 'foo', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.name', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'auditd', - description: null, - example: null, - format: '', - indexes: ['auditbeat'], - name: 'auditd.data.a0', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'auditd', - description: null, - example: null, - format: '', - indexes: ['auditbeat'], - name: 'auditd.data.a1', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'auditd', - description: null, - example: null, - format: '', - indexes: ['auditbeat'], - name: 'auditd.data.a2', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'client', - description: - 'Some event client addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.address', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'client', - description: 'Bytes sent from the client to the server.', - example: '184', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.bytes', - searchable: true, - type: 'number', - aggregatable: true, - }, - { - category: 'client', - description: 'Client domain.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.domain', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'client', - description: 'Country ISO code.', - example: 'CA', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.geo.country_iso_code', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'cloud', - description: - 'The cloud account or organization id used to identify different entities in a multi-tenant environment. Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: '666777888999', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'cloud.account.id', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'cloud', - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'cloud.availability_zone', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'container', - description: 'Unique container id.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'container.id', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'container', - description: 'Name of the image the container was built on.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'container.image.name', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'container', - description: 'Container image tag.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'container.image.tag', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'destination', - description: - 'Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.address', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - category: 'destination', - description: 'Bytes sent from the destination to the source.', - example: '184', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.bytes', - searchable: true, - type: 'number', - aggregatable: true, - }, - { - category: 'destination', - description: 'Destination domain.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.domain', - searchable: true, - type: 'string', - aggregatable: true, - }, - { - aggregatable: true, - category: 'destination', - description: - 'IP address of the destination. Can be one or multiple IPv4 or IPv6 addresses.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.ip', - searchable: true, - type: 'ip', - }, - { - aggregatable: true, - category: 'destination', - description: 'Port of the destination.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.port', - searchable: true, - type: 'long', - }, - { - aggregatable: true, - category: 'source', - description: - 'IP address of the source. Can be one or multiple IPv4 or IPv6 addresses.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'source.ip', - searchable: true, - type: 'ip', - }, - { - aggregatable: true, - category: 'source', - description: 'Port of the source.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'source.port', - searchable: true, - type: 'long', - }, - { - aggregatable: true, - category: 'event', - description: - 'event.end contains the date when the event ended or when the activity was last observed.', - example: null, - format: '', - indexes: DEFAULT_INDEX_PATTERN, - name: 'event.end', - searchable: true, - type: 'date', - }, - ], - }, - }, - }, + { + category: 'agent', + description: + 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', + example: '8a4f500f', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'agent.ephemeral_id', + searchable: true, + type: 'string', + aggregatable: true, }, - }, -]; + { + category: 'agent', + description: null, + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'agent.hostname', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'agent', + description: + 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', + example: '8a4f500d', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'agent.id', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'agent', + description: + 'Name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', + example: 'foo', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'agent.name', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'auditd', + description: null, + example: null, + format: '', + indexes: ['auditbeat'], + name: 'auditd.data.a0', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'auditd', + description: null, + example: null, + format: '', + indexes: ['auditbeat'], + name: 'auditd.data.a1', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'auditd', + description: null, + example: null, + format: '', + indexes: ['auditbeat'], + name: 'auditd.data.a2', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'client', + description: + 'Some event client addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'client.address', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'client', + description: 'Bytes sent from the client to the server.', + example: '184', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'client.bytes', + searchable: true, + type: 'number', + aggregatable: true, + }, + { + category: 'client', + description: 'Client domain.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'client.domain', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'client', + description: 'Country ISO code.', + example: 'CA', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'client.geo.country_iso_code', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'cloud', + description: + 'The cloud account or organization id used to identify different entities in a multi-tenant environment. Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.', + example: '666777888999', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'cloud.account.id', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'cloud', + description: 'Availability zone in which this host is running.', + example: 'us-east-1c', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'cloud.availability_zone', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'container', + description: 'Unique container id.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'container.id', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'container', + description: 'Name of the image the container was built on.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'container.image.name', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'container', + description: 'Container image tag.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'container.image.tag', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'destination', + description: + 'Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'destination.address', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + category: 'destination', + description: 'Bytes sent from the destination to the source.', + example: '184', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'destination.bytes', + searchable: true, + type: 'number', + aggregatable: true, + }, + { + category: 'destination', + description: 'Destination domain.', + example: null, + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'destination.domain', + searchable: true, + type: 'string', + aggregatable: true, + }, + { + aggregatable: true, + category: 'destination', + description: 'IP address of the destination. Can be one or multiple IPv4 or IPv6 addresses.', + example: '', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'destination.ip', + searchable: true, + type: 'ip', + }, + { + aggregatable: true, + category: 'destination', + description: 'Port of the destination.', + example: '', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'destination.port', + searchable: true, + type: 'long', + }, + { + aggregatable: true, + category: 'source', + description: 'IP address of the source. Can be one or multiple IPv4 or IPv6 addresses.', + example: '', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'source.ip', + searchable: true, + type: 'ip', + }, + { + aggregatable: true, + category: 'source', + description: 'Port of the source.', + example: '', + format: '', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'source.port', + searchable: true, + type: 'long', + }, + { + aggregatable: true, + category: 'event', + description: + 'event.end contains the date when the event ended or when the activity was last observed.', + example: null, + format: '', + indexes: DEFAULT_INDEX_PATTERN, + name: 'event.end', + searchable: true, + type: 'date', + }, + ], +}; export const mockIndexFields = [ { aggregatable: true, name: '@timestamp', searchable: true, type: 'date' }, diff --git a/x-pack/plugins/security_solution/public/common/containers/source/translations.ts b/x-pack/plugins/security_solution/public/common/containers/source/translations.ts new file mode 100644 index 00000000000000..f12a9a0b41a7be --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/source/translations.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const ERROR_BEAT_FIELDS = i18n.translate( + 'xpack.securitySolution.beatFields.errorSearchDescription', + { + defaultMessage: `An error has occurred on getting beat fields`, + } +); + +export const FAIL_BEAT_FIELDS = i18n.translate( + 'xpack.securitySolution.beatFields.failSearchDescription', + { + defaultMessage: `Failed to run search on beat fields`, + } +); diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/constants.ts b/x-pack/plugins/security_solution/public/common/containers/sourcerer/constants.ts index 106294ba54f5a2..be3d074811032d 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/constants.ts +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/constants.ts @@ -4,26 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export const SOURCERER_FEATURE_FLAG_ON = false; - -export enum SecurityPageName { - default = 'default', - host = 'host', - detections = 'detections', - timeline = 'timeline', - network = 'network', -} - -export type SourceGroupsType = keyof typeof SecurityPageName; - -export const sourceGroups = { - [SecurityPageName.default]: [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'winlogbeat-*', - 'blobbeat-*', - ], -}; +export const SOURCERER_FEATURE_FLAG_ON = true; diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/format.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/format.test.tsx deleted file mode 100644 index b8017df09b7380..00000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/format.test.tsx +++ /dev/null @@ -1,23 +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 { indicesExistOrDataTemporarilyUnavailable } from './format'; - -describe('indicesExistOrDataTemporarilyUnavailable', () => { - it('it returns true when undefined', () => { - let undefVar; - const result = indicesExistOrDataTemporarilyUnavailable(undefVar); - expect(result).toBeTruthy(); - }); - it('it returns true when true', () => { - const result = indicesExistOrDataTemporarilyUnavailable(true); - expect(result).toBeTruthy(); - }); - it('it returns false when false', () => { - const result = indicesExistOrDataTemporarilyUnavailable(false); - expect(result).toBeFalsy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/format.ts b/x-pack/plugins/security_solution/public/common/containers/sourcerer/format.ts deleted file mode 100644 index 8c9a16ed705ef6..00000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/format.ts +++ /dev/null @@ -1,96 +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 { isEmpty, pick } from 'lodash/fp'; -import memoizeOne from 'memoize-one'; -import { set } from '@elastic/safer-lodash-set/fp'; -import { isUndefined } from 'lodash'; -import { IndexField } from '../../../graphql/types'; -import { IIndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns'; - -export interface BrowserField { - aggregatable: boolean; - category: string; - description: string | null; - example: string | number | null; - fields: Readonly>>; - format: string; - indexes: string[]; - name: string; - searchable: boolean; - type: string; -} - -export interface DocValueFields { - field: string; - format: string; -} - -export type BrowserFields = Readonly>>; - -export const getAllBrowserFields = (browserFields: BrowserFields): Array> => - Object.values(browserFields).reduce>>( - (acc, namespace) => [ - ...acc, - ...Object.values(namespace.fields != null ? namespace.fields : {}), - ], - [] - ); - -export const getIndexFields = memoizeOne( - (title: string, fields: IndexField[]): IIndexPattern => - fields && fields.length > 0 - ? { - fields: fields.map((field) => - pick(['name', 'searchable', 'type', 'aggregatable', 'esTypes', 'subType'], field) - ), - title, - } - : { fields: [], title }, - (newArgs, lastArgs) => newArgs[0] === lastArgs[0] && newArgs[1].length === lastArgs[1].length -); - -export const getBrowserFields = memoizeOne( - (_title: string, fields: IndexField[]): BrowserFields => - fields && fields.length > 0 - ? fields.reduce( - (accumulator: BrowserFields, field: IndexField) => - set([field.category, 'fields', field.name], field, accumulator), - {} - ) - : {}, - // Update the value only if _title has changed - (newArgs, lastArgs) => newArgs[0] === lastArgs[0] -); - -export const getDocValueFields = memoizeOne( - (_title: string, fields: IndexField[]): DocValueFields[] => - fields && fields.length > 0 - ? fields.reduce((accumulator: DocValueFields[], field: IndexField) => { - if (field.type === 'date' && accumulator.length < 100) { - const format: string = - field.format != null && !isEmpty(field.format) ? field.format : 'date_time'; - return [ - ...accumulator, - { - field: field.name, - format, - }, - ]; - } - return accumulator; - }, []) - : [], - // Update the value only if _title has changed - (newArgs, lastArgs) => newArgs[0] === lastArgs[0] -); - -export const indicesExistOrDataTemporarilyUnavailable = ( - indicesExist: boolean | null | undefined -) => indicesExist || isUndefined(indicesExist); - -export const EMPTY_BROWSER_FIELDS = {}; -export const EMPTY_DOCVALUE_FIELD: DocValueFields[] = []; diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx index 38af84e0968f86..673db7af2b5e6d 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx @@ -4,28 +4,73 @@ * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable react/display-name */ + +import React from 'react'; import { act, renderHook } from '@testing-library/react-hooks'; +import { Provider } from 'react-redux'; -import { getSourceDefaults, useSourceManager, UseSourceManager } from '.'; +import { useInitSourcerer } from '.'; +import { mockPatterns, mockSource } from './mocks'; +// import { SourcererScopeName } from '../../store/sourcerer/model'; +import { RouteSpyState } from '../../utils/route/types'; +import { SecurityPageName } from '../../../../common/constants'; +import { createStore, State } from '../../store'; import { - mockSourceSelections, - mockSourceGroup, - mockSourceGroups, - mockPatterns, - mockSource, -} from './mocks'; -import { SecurityPageName } from './constants'; -const mockSourceDefaults = mockSource(SecurityPageName.default); + apolloClientObservable, + createSecuritySolutionStorageMock, + kibanaObservable, + mockGlobalState, + SUB_PLUGINS_REDUCER, +} from '../../mock'; +const mockSourceDefaults = mockSource; + +const mockRouteSpy: RouteSpyState = { + pageName: SecurityPageName.overview, + detailName: undefined, + tabName: undefined, + search: '', + pathName: '/', +}; +const mockDispatch = jest.fn(); +jest.mock('react-redux', () => { + const original = jest.requireActual('react-redux'); + + return { + ...original, + useDispatch: () => mockDispatch, + }; +}); +jest.mock('../../utils/route/use_route_spy', () => ({ + useRouteSpy: () => [mockRouteSpy], +})); jest.mock('../../lib/kibana', () => ({ useKibana: jest.fn().mockReturnValue({ services: { + application: { + capabilities: { + siem: { + crud: true, + }, + }, + }, data: { indexPatterns: { getTitles: jest.fn().mockImplementation(() => Promise.resolve(mockPatterns)), }, + search: { + search: jest.fn().mockImplementation(() => ({ + subscribe: jest.fn().mockImplementation(() => ({ + error: jest.fn(), + next: jest.fn(), + })), + })), + }, }, + notifications: {}, }, }), + useUiSetting$: jest.fn().mockImplementation(() => [mockPatterns]), })); jest.mock('../../utils/apollo_context', () => ({ useApolloClient: jest.fn().mockReturnValue({ @@ -34,148 +79,193 @@ jest.mock('../../utils/apollo_context', () => ({ })); describe('Sourcerer Hooks', () => { - const testId = SecurityPageName.default; - const uninitializedId = SecurityPageName.host; + // const testId = SourcererScopeName.default; + // const uninitializedId = SourcererScopeName.detections; beforeEach(() => { jest.clearAllMocks(); jest.restoreAllMocks(); }); + const state: State = mockGlobalState; + const { storage } = createSecuritySolutionStorageMock(); + let store = createStore( + state, + SUB_PLUGINS_REDUCER, + apolloClientObservable, + kibanaObservable, + storage + ); + + beforeEach(() => { + store = createStore( + state, + SUB_PLUGINS_REDUCER, + apolloClientObservable, + kibanaObservable, + storage + ); + }); describe('Initialization', () => { - it('initializes loading default index patterns', async () => { + it('initializes loading default and timeline index patterns', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - expect(result.current).toEqual({ - activeSourceGroupId: 'default', - availableIndexPatterns: [], - availableSourceGroupIds: [], - isIndexPatternsLoading: true, - sourceGroups: {}, - getManageSourceGroupById: result.current.getManageSourceGroupById, - initializeSourceGroup: result.current.initializeSourceGroup, - setActiveSourceGroupId: result.current.setActiveSourceGroupId, - updateSourceGroupIndicies: result.current.updateSourceGroupIndicies, + const { waitForNextUpdate } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, }); - }); - }); - it('initializes loading default source group', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); await waitForNextUpdate(); await waitForNextUpdate(); - expect(result.current).toEqual({ - activeSourceGroupId: 'default', - availableIndexPatterns: mockPatterns, - availableSourceGroupIds: [], - isIndexPatternsLoading: false, - sourceGroups: {}, - getManageSourceGroupById: result.current.getManageSourceGroupById, - initializeSourceGroup: result.current.initializeSourceGroup, - setActiveSourceGroupId: result.current.setActiveSourceGroupId, - updateSourceGroupIndicies: result.current.updateSourceGroupIndicies, + expect(mockDispatch).toBeCalledTimes(2); + expect(mockDispatch.mock.calls[0][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', + payload: { id: 'default', loading: true }, }); - }); - }); - it('initialize completes with formatted source group data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - activeSourceGroupId: testId, - availableIndexPatterns: mockPatterns, - availableSourceGroupIds: [testId], - isIndexPatternsLoading: false, - sourceGroups: { - default: mockSourceGroup(testId), - }, - getManageSourceGroupById: result.current.getManageSourceGroupById, - initializeSourceGroup: result.current.initializeSourceGroup, - setActiveSourceGroupId: result.current.setActiveSourceGroupId, - updateSourceGroupIndicies: result.current.updateSourceGroupIndicies, + expect(mockDispatch.mock.calls[1][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', + payload: { id: 'timeline', loading: true }, }); + // expect(mockDispatch.mock.calls[1][0]).toEqual({ + // type: 'x-pack/security_solution/local/sourcerer/SET_INDEX_PATTERNS_LIST', + // payload: { allIndexPatterns: mockPatterns, kibanaIndexPatterns: [] }, + // }); }); }); + // TO DO sourcerer @S + // it('initializes loading default source group', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook( + // () => useInitSourcerer(), + // { + // wrapper: ({ children }) => {children}, + // } + // ); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // expect(result.current).toEqual({ + // activeSourcererScopeId: 'default', + // kibanaIndexPatterns: mockPatterns, + // isIndexPatternsLoading: false, + // getSourcererScopeById: result.current.getSourcererScopeById, + // setActiveSourcererScopeId: result.current.setActiveSourcererScopeId, + // updateSourcererScopeIndices: result.current.updateSourcererScopeIndices, + // }); + // }); + // }); + // it('initialize completes with formatted source group data', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook( + // () => useInitSourcerer(), + // { + // wrapper: ({ children }) => {children}, + // } + // ); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // expect(result.current).toEqual({ + // activeSourcererScopeId: testId, + // kibanaIndexPatterns: mockPatterns, + // isIndexPatternsLoading: false, + // getSourcererScopeById: result.current.getSourcererScopeById, + // setActiveSourcererScopeId: result.current.setActiveSourcererScopeId, + // updateSourcererScopeIndices: result.current.updateSourcererScopeIndices, + // }); + // }); + // }); }); - describe('Methods', () => { - it('getManageSourceGroupById: initialized source group returns defaults', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - const initializedSourceGroup = result.current.getManageSourceGroupById(testId); - expect(initializedSourceGroup).toEqual(mockSourceGroup(testId)); - }); - }); - it('getManageSourceGroupById: uninitialized source group returns defaults', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - const uninitializedSourceGroup = result.current.getManageSourceGroupById(uninitializedId); - expect(uninitializedSourceGroup).toEqual(getSourceDefaults(uninitializedId, mockPatterns)); - }); - }); - it('initializeSourceGroup: initializes source group', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - result.current.initializeSourceGroup( - uninitializedId, - mockSourceGroups[uninitializedId], - true - ); - await waitForNextUpdate(); - const initializedSourceGroup = result.current.getManageSourceGroupById(uninitializedId); - expect(initializedSourceGroup.indexPatterns).toEqual(mockSourceSelections[uninitializedId]); - }); - }); - it('setActiveSourceGroupId: active source group id gets set only if it gets initialized first', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - expect(result.current.activeSourceGroupId).toEqual(testId); - result.current.setActiveSourceGroupId(uninitializedId); - expect(result.current.activeSourceGroupId).toEqual(testId); - result.current.initializeSourceGroup(uninitializedId); - result.current.setActiveSourceGroupId(uninitializedId); - expect(result.current.activeSourceGroupId).toEqual(uninitializedId); - }); - }); - it('updateSourceGroupIndicies: updates source group indicies', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useSourceManager() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - let sourceGroup = result.current.getManageSourceGroupById(testId); - expect(sourceGroup.indexPatterns).toEqual(mockSourceSelections[testId]); - result.current.updateSourceGroupIndicies(testId, ['endgame-*', 'filebeat-*']); - await waitForNextUpdate(); - sourceGroup = result.current.getManageSourceGroupById(testId); - expect(sourceGroup.indexPatterns).toEqual(['endgame-*', 'filebeat-*']); - }); - }); - }); + // describe('Methods', () => { + // it('getSourcererScopeById: initialized source group returns defaults', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook( + // () => useInitSourcerer(), + // { + // wrapper: ({ children }) => {children}, + // } + // ); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // const initializedSourcererScope = result.current.getSourcererScopeById(testId); + // expect(initializedSourcererScope).toEqual(mockSourcererScope(testId)); + // }); + // }); + // it('getSourcererScopeById: uninitialized source group returns defaults', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook( + // () => useInitSourcerer(), + // { + // wrapper: ({ children }) => {children}, + // } + // ); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // const uninitializedSourcererScope = result.current.getSourcererScopeById(uninitializedId); + // expect(uninitializedSourcererScope).toEqual( + // getSourceDefaults(uninitializedId, mockPatterns) + // ); + // }); + // }); + // // it('initializeSourcererScope: initializes source group', async () => { + // // await act(async () => { + // // const { result, waitForNextUpdate } = renderHook( + // // () => useSourcerer(), + // // { + // // wrapper: ({ children }) => {children}, + // // } + // // ); + // // await waitForNextUpdate(); + // // await waitForNextUpdate(); + // // await waitForNextUpdate(); + // // result.current.initializeSourcererScope( + // // uninitializedId, + // // mockSourcererScopes[uninitializedId], + // // true + // // ); + // // await waitForNextUpdate(); + // // const initializedSourcererScope = result.current.getSourcererScopeById(uninitializedId); + // // expect(initializedSourcererScope.selectedPatterns).toEqual( + // // mockSourcererScopes[uninitializedId] + // // ); + // // }); + // // }); + // it('setActiveSourcererScopeId: active source group id gets set only if it gets initialized first', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook( + // () => useInitSourcerer(), + // { + // wrapper: ({ children }) => {children}, + // } + // ); + // await waitForNextUpdate(); + // expect(result.current.activeSourcererScopeId).toEqual(testId); + // result.current.setActiveSourcererScopeId(uninitializedId); + // expect(result.current.activeSourcererScopeId).toEqual(testId); + // // result.current.initializeSourcererScope(uninitializedId); + // result.current.setActiveSourcererScopeId(uninitializedId); + // expect(result.current.activeSourcererScopeId).toEqual(uninitializedId); + // }); + // }); + // it('updateSourcererScopeIndices: updates source group indices', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook( + // () => useInitSourcerer(), + // { + // wrapper: ({ children }) => {children}, + // } + // ); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // await waitForNextUpdate(); + // let sourceGroup = result.current.getSourcererScopeById(testId); + // expect(sourceGroup.selectedPatterns).toEqual(mockSourcererScopes[testId]); + // expect(sourceGroup.scopePatterns).toEqual(mockSourcererScopes[testId]); + // result.current.updateSourcererScopeIndices({ + // id: testId, + // selectedPatterns: ['endgame-*', 'filebeat-*'], + // }); + // await waitForNextUpdate(); + // sourceGroup = result.current.getSourcererScopeById(testId); + // expect(sourceGroup.scopePatterns).toEqual(mockSourcererScopes[testId]); + // expect(sourceGroup.selectedPatterns).toEqual(['endgame-*', 'filebeat-*']); + // }); + // }); + // }); }); diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx index 91907b45aa449b..afacd68d715920 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx @@ -4,412 +4,72 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get, noop, isEmpty } from 'lodash/fp'; -import React, { createContext, useCallback, useContext, useEffect, useReducer } from 'react'; -import { IIndexPattern } from 'src/plugins/data/public'; - -import { NO_ALERT_INDEX } from '../../../../common/constants'; -import { useKibana } from '../../lib/kibana'; - -import { SourceQuery } from '../../../graphql/types'; - -import { sourceQuery } from '../source/index.gql_query'; -import { useApolloClient } from '../../utils/apollo_context'; -import { - sourceGroups, - SecurityPageName, - SourceGroupsType, - SOURCERER_FEATURE_FLAG_ON, -} from './constants'; -import { - BrowserFields, - DocValueFields, - EMPTY_BROWSER_FIELDS, - EMPTY_DOCVALUE_FIELD, - getBrowserFields, - getDocValueFields, - getIndexFields, - indicesExistOrDataTemporarilyUnavailable, -} from './format'; - -// TYPES -interface ManageSource { - browserFields: BrowserFields; - defaultPatterns: string[]; - docValueFields: DocValueFields[]; - errorMessage: string | null; - id: SourceGroupsType; - indexPattern: IIndexPattern; - indexPatterns: string[]; - indicesExist: boolean | undefined | null; - loading: boolean; -} - -interface ManageSourceInit extends Partial { - id: SourceGroupsType; -} - -type ManageSourceGroupById = { - [id in SourceGroupsType]?: ManageSource; -}; - -type ActionManageSource = - | { - type: 'SET_SOURCE'; - id: SourceGroupsType; - defaultIndex: string[]; - payload: ManageSourceInit; - } - | { - type: 'SET_IS_SOURCE_LOADING'; - id: SourceGroupsType; - payload: boolean; - } - | { - type: 'SET_ACTIVE_SOURCE_GROUP_ID'; - payload: SourceGroupsType; - } - | { - type: 'SET_AVAILABLE_INDEX_PATTERNS'; - payload: string[]; - } - | { - type: 'SET_IS_INDEX_PATTERNS_LOADING'; - payload: boolean; - }; - -interface ManageSourcerer { - activeSourceGroupId: SourceGroupsType; - availableIndexPatterns: string[]; - availableSourceGroupIds: SourceGroupsType[]; - isIndexPatternsLoading: boolean; - sourceGroups: ManageSourceGroupById; -} - -export interface UseSourceManager extends ManageSourcerer { - getManageSourceGroupById: (id: SourceGroupsType) => ManageSource; - initializeSourceGroup: ( - id: SourceGroupsType, - indexToAdd?: string[] | null, - onlyCheckIndexToAdd?: boolean - ) => void; - setActiveSourceGroupId: (id: SourceGroupsType) => void; - updateSourceGroupIndicies: (id: SourceGroupsType, updatedIndicies: string[]) => void; -} - -// DEFAULTS/INIT -export const getSourceDefaults = (id: SourceGroupsType, defaultIndex: string[]) => ({ - browserFields: EMPTY_BROWSER_FIELDS, - defaultPatterns: defaultIndex, - docValueFields: EMPTY_DOCVALUE_FIELD, - errorMessage: null, - id, - indexPattern: getIndexFields(defaultIndex.join(), []), - indexPatterns: defaultIndex, - indicesExist: indicesExistOrDataTemporarilyUnavailable(undefined), - loading: true, -}); - -const initManageSource: ManageSourcerer = { - activeSourceGroupId: SecurityPageName.default, - availableIndexPatterns: [], - availableSourceGroupIds: [], - isIndexPatternsLoading: true, - sourceGroups: {}, -}; -const init: UseSourceManager = { - ...initManageSource, - getManageSourceGroupById: (id: SourceGroupsType) => getSourceDefaults(id, []), - initializeSourceGroup: () => noop, - setActiveSourceGroupId: () => noop, - updateSourceGroupIndicies: () => noop, -}; - -const reducerManageSource = (state: ManageSourcerer, action: ActionManageSource) => { - switch (action.type) { - case 'SET_SOURCE': - return { - ...state, - sourceGroups: { - ...state.sourceGroups, - [action.id]: { - ...getSourceDefaults(action.id, action.defaultIndex), - ...state.sourceGroups[action.id], - ...action.payload, - }, - }, - availableSourceGroupIds: state.availableSourceGroupIds.includes(action.id) - ? state.availableSourceGroupIds - : [...state.availableSourceGroupIds, action.id], - }; - case 'SET_IS_SOURCE_LOADING': - return { - ...state, - sourceGroups: { - ...state.sourceGroups, - [action.id]: { - ...state.sourceGroups[action.id], - id: action.id, - loading: action.payload, - }, - }, - }; - case 'SET_ACTIVE_SOURCE_GROUP_ID': - return { - ...state, - activeSourceGroupId: action.payload, - }; - case 'SET_AVAILABLE_INDEX_PATTERNS': - return { - ...state, - availableIndexPatterns: action.payload, - }; - case 'SET_IS_INDEX_PATTERNS_LOADING': - return { - ...state, - isIndexPatternsLoading: action.payload, - }; - default: - return state; - } -}; - -// HOOKS -export const useSourceManager = (): UseSourceManager => { - const { - services: { - data: { indexPatterns }, - }, - } = useKibana(); - const apolloClient = useApolloClient(); - const [state, dispatch] = useReducer(reducerManageSource, initManageSource); - - // Kibana Index Patterns - const setIsIndexPatternsLoading = useCallback((loading: boolean) => { - dispatch({ - type: 'SET_IS_INDEX_PATTERNS_LOADING', - payload: loading, - }); - }, []); - const getDefaultIndex = useCallback( - (indexToAdd?: string[] | null, onlyCheckIndexToAdd?: boolean) => { - const filterIndexAdd = (indexToAdd ?? []).filter((item) => item !== NO_ALERT_INDEX); - if (!isEmpty(filterIndexAdd)) { - return onlyCheckIndexToAdd - ? filterIndexAdd.sort() - : [ - ...state.availableIndexPatterns, - ...filterIndexAdd.filter((index) => !state.availableIndexPatterns.includes(index)), - ].sort(); - } - return state.availableIndexPatterns.sort(); - }, - [state.availableIndexPatterns] - ); - const setAvailableIndexPatterns = useCallback((availableIndexPatterns: string[]) => { - dispatch({ - type: 'SET_AVAILABLE_INDEX_PATTERNS', - payload: availableIndexPatterns, - }); - }, []); - const fetchKibanaIndexPatterns = useCallback(() => { - setIsIndexPatternsLoading(true); - const abortCtrl = new AbortController(); - - async function fetchTitles() { - try { - const result = await indexPatterns.getTitles(); - setAvailableIndexPatterns(result); - setIsIndexPatternsLoading(false); - } catch (error) { - setIsIndexPatternsLoading(false); - } - } - - fetchTitles(); - - return () => { - return abortCtrl.abort(); - }; - }, [indexPatterns, setAvailableIndexPatterns, setIsIndexPatternsLoading]); - - // Security Solution Source Groups - const setActiveSourceGroupId = useCallback( - (sourceGroupId: SourceGroupsType) => { - if (state.availableSourceGroupIds.includes(sourceGroupId)) { - dispatch({ - type: 'SET_ACTIVE_SOURCE_GROUP_ID', - payload: sourceGroupId, - }); - } - }, - [state.availableSourceGroupIds] - ); - const setIsSourceLoading = useCallback( - ({ id, loading }: { id: SourceGroupsType; loading: boolean }) => { - dispatch({ - type: 'SET_IS_SOURCE_LOADING', - id, - payload: loading, - }); - }, +import deepEqual from 'fast-deep-equal'; +import isEqual from 'lodash/isEqual'; +import { useEffect, useMemo } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { sourcererActions, sourcererSelectors } from '../../store/sourcerer'; +import { ManageScope, SourcererScopeName } from '../../store/sourcerer/model'; +import { useIndexFields } from '../source'; +import { State } from '../../store'; +import { useUserInfo } from '../../../detections/components/user_info'; + +export const useInitSourcerer = ( + scopeId: SourcererScopeName.default | SourcererScopeName.detections = SourcererScopeName.default +) => { + const dispatch = useDispatch(); + + const { loading: loadingSignalIndex, isSignalIndexExists, signalIndexName } = useUserInfo(); + const getConfigIndexPatternsSelector = useMemo( + () => sourcererSelectors.configIndexPatternsSelector(), [] ); - const enrichSource = useCallback( - (id: SourceGroupsType, indexToAdd?: string[] | null, onlyCheckIndexToAdd?: boolean) => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - const defaultIndex = getDefaultIndex(indexToAdd, onlyCheckIndexToAdd); - const selectedPatterns = defaultIndex.filter((pattern) => - state.availableIndexPatterns.includes(pattern) - ); - if (state.sourceGroups[id] == null) { - dispatch({ - type: 'SET_SOURCE', - id, - defaultIndex: selectedPatterns, - payload: { defaultPatterns: defaultIndex, id }, - }); - } - - async function fetchSource() { - if (!apolloClient) return; - setIsSourceLoading({ id, loading: true }); - try { - const result = await apolloClient.query({ - query: sourceQuery, - fetchPolicy: 'network-only', - variables: { - sourceId: 'default', // always - defaultIndex: selectedPatterns, - }, - context: { - fetchOptions: { - signal: abortCtrl.signal, - }, - }, - }); - if (isSubscribed) { - dispatch({ - type: 'SET_SOURCE', - id, - defaultIndex: selectedPatterns, - payload: { - browserFields: getBrowserFields( - selectedPatterns.join(), - get('data.source.status.indexFields', result) - ), - docValueFields: getDocValueFields( - selectedPatterns.join(), - get('data.source.status.indexFields', result) - ), - errorMessage: null, - id, - indexPattern: getIndexFields( - selectedPatterns.join(), - get('data.source.status.indexFields', result) - ), - indexPatterns: selectedPatterns, - indicesExist: indicesExistOrDataTemporarilyUnavailable( - get('data.source.status.indicesExist', result) - ), - loading: false, - }, - }); - } - } catch (error) { - if (isSubscribed) { - dispatch({ - type: 'SET_SOURCE', - id, - defaultIndex: selectedPatterns, - payload: { - errorMessage: error.message, - id, - loading: false, - }, - }); - } - } - } - - fetchSource(); - - return () => { - isSubscribed = false; - return abortCtrl.abort(); - }; - }, - [ - apolloClient, - getDefaultIndex, - setIsSourceLoading, - state.availableIndexPatterns, - state.sourceGroups, - ] - ); + const ConfigIndexPatterns = useSelector(getConfigIndexPatternsSelector, isEqual); - const initializeSourceGroup = useCallback( - (id: SourceGroupsType, indexToAdd?: string[] | null, onlyCheckIndexToAdd?: boolean) => - enrichSource(id, indexToAdd, onlyCheckIndexToAdd), - [enrichSource] - ); - - const updateSourceGroupIndicies = useCallback( - (id: SourceGroupsType, updatedIndicies: string[]) => enrichSource(id, updatedIndicies, true), - [enrichSource] - ); - const getManageSourceGroupById = useCallback( - (id: SourceGroupsType) => { - const sourceById = state.sourceGroups[id]; - if (sourceById != null) { - return sourceById; - } - return getSourceDefaults(id, getDefaultIndex()); - }, - [getDefaultIndex, state.sourceGroups] - ); + useIndexFields(scopeId); + useIndexFields(SourcererScopeName.timeline); - // load initial default index useEffect(() => { - fetchKibanaIndexPatterns(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + if (!loadingSignalIndex && signalIndexName != null) { + dispatch(sourcererActions.setSignalIndexName({ signalIndexName })); + } + }, [dispatch, loadingSignalIndex, signalIndexName]); + // Related to timeline useEffect(() => { - if (!state.isIndexPatternsLoading) { - Object.entries(sourceGroups).forEach(([key, value]) => - initializeSourceGroup(key as SourceGroupsType, value, true) + if (!loadingSignalIndex && signalIndexName != null) { + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: SourcererScopeName.timeline, + selectedPatterns: [...ConfigIndexPatterns, signalIndexName], + }) ); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [state.isIndexPatternsLoading]); + }, [ConfigIndexPatterns, dispatch, loadingSignalIndex, signalIndexName]); - return { - ...state, - getManageSourceGroupById, - initializeSourceGroup, - setActiveSourceGroupId, - updateSourceGroupIndicies, - }; + // Related to the detection page + useEffect(() => { + if ( + scopeId === SourcererScopeName.detections && + isSignalIndexExists && + signalIndexName != null + ) { + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: scopeId, + selectedPatterns: [signalIndexName], + }) + ); + } + }, [dispatch, isSignalIndexExists, scopeId, signalIndexName]); }; -const ManageSourceContext = createContext(init); - -export const useManageSource = () => useContext(ManageSourceContext); - -interface ManageSourceProps { - children: React.ReactNode; -} - -export const MaybeManageSource = ({ children }: ManageSourceProps) => { - const indexPatternManager = useSourceManager(); - return ( - - {children} - +export const useSourcererScope = (scope: SourcererScopeName = SourcererScopeName.default) => { + const sourcererScopeSelector = useMemo(() => sourcererSelectors.getSourcererScopeSelector(), []); + const SourcererScope = useSelector( + (state) => sourcererScopeSelector(state, scope), + deepEqual ); + return SourcererScope; }; -export const ManageSource = SOURCERER_FEATURE_FLAG_ON - ? MaybeManageSource - : ({ children }: ManageSourceProps) => <>{children}; diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/mocks.ts b/x-pack/plugins/security_solution/public/common/containers/sourcerer/mocks.ts index cde14e54694f08..c34a6917f300ec 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/mocks.ts +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/mocks.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SecurityPageName } from './constants'; -import { getSourceDefaults } from './index'; +import { initSourcererScope } from '../../store/sourcerer/model'; export const mockPatterns = [ 'auditbeat-*', @@ -14,32 +13,10 @@ export const mockPatterns = [ 'logs-*', 'packetbeat-*', 'winlogbeat-*', + 'journalbeat-*', ]; -export const mockSourceGroups = { - [SecurityPageName.default]: [ - 'apm-*-transaction*', - 'auditbeat-*', - 'blobbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'winlogbeat-*', - ], - [SecurityPageName.host]: [ - 'apm-*-transaction*', - 'endgame-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], -}; - -export const mockSourceSelections = { - [SecurityPageName.default]: ['auditbeat-*', 'endgame-*', 'filebeat-*', 'logs-*', 'winlogbeat-*'], - [SecurityPageName.host]: ['endgame-*', 'logs-*', 'packetbeat-*', 'winlogbeat-*'], -}; -export const mockSource = (testId: SecurityPageName.default | SecurityPageName.host) => ({ +export const mockSource = { data: { source: { id: 'default', @@ -50,7 +27,7 @@ export const mockSource = (testId: SecurityPageName.default | SecurityPageName.h category: '_id', description: 'Each document has an _id that uniquely identifies it', example: 'Y-6TfmcB0WOhS6qyMv3s', - indexes: mockSourceSelections[testId], + indexes: mockPatterns, name: '_id', searchable: true, type: 'string', @@ -67,48 +44,45 @@ export const mockSource = (testId: SecurityPageName.default | SecurityPageName.h loading: false, networkStatus: 7, stale: false, -}); +}; -export const mockSourceGroup = (testId: SecurityPageName.default | SecurityPageName.host) => { - const indexes = mockSourceSelections[testId]; - return { - ...getSourceDefaults(testId, mockPatterns), - defaultPatterns: mockSourceGroups[testId], - browserFields: { - _id: { - fields: { - _id: { - __typename: 'IndexField', - aggregatable: false, - category: '_id', - description: 'Each document has an _id that uniquely identifies it', - esTypes: null, - example: 'Y-6TfmcB0WOhS6qyMv3s', - format: null, - indexes, - name: '_id', - searchable: true, - subType: null, - type: 'string', - }, - }, - }, - }, - indexPattern: { - fields: [ - { +export const mockSourcererScope = { + ...initSourcererScope, + scopePatterns: mockPatterns, + browserFields: { + _id: { + fields: { + _id: { + __typename: 'IndexField', aggregatable: false, + category: '_id', + description: 'Each document has an _id that uniquely identifies it', esTypes: null, + example: 'Y-6TfmcB0WOhS6qyMv3s', + format: null, + indexes: mockPatterns, name: '_id', searchable: true, subType: null, type: 'string', }, - ], - title: indexes.join(), + }, }, - indexPatterns: indexes, - indicesExist: true, - loading: false, - }; + }, + indexPattern: { + fields: [ + { + aggregatable: false, + esTypes: null, + name: '_id', + searchable: true, + subType: null, + type: 'string', + }, + ], + title: mockPatterns.join(), + }, + selectedPatterns: mockPatterns, + indicesExist: true, + loading: false, }; diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts index 573ef92f7e0697..3051459d5de0ca 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts @@ -12,9 +12,25 @@ import { createStartServicesMock, createWithKibanaMock, } from '../kibana_react.mock'; - +const mockStartServicesMock = createStartServicesMock(); export const KibanaServices = { get: jest.fn(), getKibanaVersion: jest.fn(() => '8.0.0') }; -export const useKibana = jest.fn().mockReturnValue({ services: createStartServicesMock() }); +export const useKibana = jest.fn().mockReturnValue({ + services: { + ...mockStartServicesMock, + data: { + ...mockStartServicesMock.data, + search: { + ...mockStartServicesMock.data.search, + search: jest.fn().mockImplementation(() => ({ + subscribe: jest.fn().mockImplementation(() => ({ + error: jest.fn(), + next: jest.fn(), + })), + })), + }, + }, + }, +}); export const useUiSetting = jest.fn(createUseUiSettingMock()); export const useUiSetting$ = jest.fn(createUseUiSetting$Mock()); export const useHttp = jest.fn().mockReturnValue(createStartServicesMock().http); diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts index a74c9a6d2009da..0944b6aa27f678 100644 --- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts +++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts @@ -22,11 +22,15 @@ import { DEFAULT_TO, DEFAULT_INTERVAL_TYPE, DEFAULT_INTERVAL_VALUE, + DEFAULT_INDEX_PATTERN, } from '../../../common/constants'; import { networkModel } from '../../network/store'; import { TimelineType, TimelineStatus } from '../../../common/types/timeline'; import { mockManagementState } from '../../management/store/reducer'; import { ManagementState } from '../../management/types'; +import { initialSourcererState, SourcererScopeName } from '../store/sourcerer/model'; +import { mockBrowserFields, mockDocValueFields } from '../containers/source/mock'; +import { mockIndexPattern } from './index_pattern'; export const mockGlobalState: State = { app: { @@ -203,6 +207,7 @@ export const mockGlobalState: State = { id: 'test', savedObjectId: null, columns: defaultHeaders, + indexNames: DEFAULT_INDEX_PATTERN, itemsPerPage: 5, dataProviders: [], description: '', @@ -241,6 +246,28 @@ export const mockGlobalState: State = { }, insertTimeline: null, }, + sourcerer: { + ...initialSourcererState, + sourcererScopes: { + ...initialSourcererState.sourcererScopes, + [SourcererScopeName.default]: { + ...initialSourcererState.sourcererScopes[SourcererScopeName.default], + selectedPatterns: DEFAULT_INDEX_PATTERN, + browserFields: mockBrowserFields, + indexPattern: mockIndexPattern, + docValueFields: mockDocValueFields, + loading: false, + }, + [SourcererScopeName.timeline]: { + ...initialSourcererState.sourcererScopes[SourcererScopeName.timeline], + selectedPatterns: DEFAULT_INDEX_PATTERN, + browserFields: mockBrowserFields, + indexPattern: mockIndexPattern, + docValueFields: mockDocValueFields, + loading: false, + }, + }, + }, /** * These state's are wrapped in `Immutable`, but for compatibility with the overall app architecture, * they are cast to mutable versions here. diff --git a/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts b/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts index 826057560f942c..e4abc17e9034ce 100644 --- a/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts +++ b/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -export const mockIndexPattern = { +import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; + +export const mockIndexPattern: IIndexPattern = { fields: [ { name: '@timestamp', @@ -93,3 +95,5 @@ export const mockIndexPattern = { ], title: 'filebeat-*,auditbeat-*,packetbeat-*', }; + +export const mockIndexNames = ['filebeat-*', 'auditbeat-*', 'packetbeat-*']; diff --git a/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts b/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts index 26013915315afb..6403a50ad4a1dc 100644 --- a/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts +++ b/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts @@ -2124,6 +2124,7 @@ export const mockTimelineModel: TimelineModel = { highlightedDropAndProviderId: '', historyIds: [], id: 'ef579e40-jibber-jabber', + indexNames: [], isFavorite: false, isLive: false, isLoading: false, @@ -2228,6 +2229,7 @@ export const defaultTimelineProps: CreateTimelineProps = { highlightedDropAndProviderId: '', historyIds: [], id: TimelineId.active, + indexNames: [], isFavorite: false, isLive: false, isLoading: false, diff --git a/x-pack/plugins/security_solution/public/common/store/actions.ts b/x-pack/plugins/security_solution/public/common/store/actions.ts index 6b446ab6692d92..f4134b5c47c2cb 100644 --- a/x-pack/plugins/security_solution/public/common/store/actions.ts +++ b/x-pack/plugins/security_solution/public/common/store/actions.ts @@ -12,6 +12,7 @@ import { TrustedAppsPageAction } from '../../management/pages/trusted_apps/store export { appActions } from './app'; export { dragAndDropActions } from './drag_and_drop'; export { inputsActions } from './inputs'; +export { sourcererActions } from './sourcerer'; import { RoutingAction } from './routing'; export type AppAction = diff --git a/x-pack/plugins/security_solution/public/common/store/model.ts b/x-pack/plugins/security_solution/public/common/store/model.ts index 0032a95cce321a..04603d06075834 100644 --- a/x-pack/plugins/security_solution/public/common/store/model.ts +++ b/x-pack/plugins/security_solution/public/common/store/model.ts @@ -7,4 +7,5 @@ export { appModel } from './app'; export { dragAndDropModel } from './drag_and_drop'; export { inputsModel } from './inputs'; +export { sourcererModel } from './sourcerer'; export * from './types'; diff --git a/x-pack/plugins/security_solution/public/common/store/reducer.ts b/x-pack/plugins/security_solution/public/common/store/reducer.ts index a0977cea71da7a..60cb6a4e960bd4 100644 --- a/x-pack/plugins/security_solution/public/common/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/common/store/reducer.ts @@ -9,6 +9,7 @@ import { combineReducers, PreloadedState, AnyAction, Reducer } from 'redux'; import { appReducer, initialAppState } from './app'; import { dragAndDropReducer, initialDragAndDropState } from './drag_and_drop'; import { createInitialInputsState, inputsReducer } from './inputs'; +import { sourcererReducer, sourcererModel } from './sourcerer'; import { HostsPluginReducer } from '../../hosts/store'; import { NetworkPluginReducer } from '../../network/store'; @@ -18,6 +19,7 @@ import { SecuritySubPlugins } from '../../app/types'; import { ManagementPluginReducer } from '../../management'; import { State } from './types'; import { AppAction } from './actions'; +import { KibanaIndexPatterns } from './sourcerer/model'; export type SubPluginsInitReducer = HostsPluginReducer & NetworkPluginReducer & @@ -28,13 +30,22 @@ export type SubPluginsInitReducer = HostsPluginReducer & * Factory for the 'initialState' that is used to preload state into the Security App's redux store. */ export const createInitialState = ( - pluginsInitState: SecuritySubPlugins['store']['initialState'] + pluginsInitState: SecuritySubPlugins['store']['initialState'], + { + kibanaIndexPatterns, + configIndexPatterns, + }: { kibanaIndexPatterns: KibanaIndexPatterns; configIndexPatterns: string[] } ): PreloadedState => { const preloadedState: PreloadedState = { app: initialAppState, dragAndDrop: initialDragAndDropState, ...pluginsInitState, inputs: createInitialInputsState(), + sourcerer: { + ...sourcererModel.initialSourcererState, + kibanaIndexPatterns, + configIndexPatterns, + }, }; return preloadedState; }; @@ -49,5 +60,6 @@ export const createReducer: ( app: appReducer, dragAndDrop: dragAndDropReducer, inputs: inputsReducer, + sourcerer: sourcererReducer, ...pluginsReducer, }); diff --git a/x-pack/plugins/security_solution/public/common/store/selectors.ts b/x-pack/plugins/security_solution/public/common/store/selectors.ts index b938bae39b634b..3cefd92bf9e602 100644 --- a/x-pack/plugins/security_solution/public/common/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/common/store/selectors.ts @@ -7,3 +7,4 @@ export { appSelectors } from './app'; export { dragAndDropSelectors } from './drag_and_drop'; export { inputsSelectors } from './inputs'; +export { sourcererSelectors } from './sourcerer'; diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts new file mode 100644 index 00000000000000..0b40586798f09e --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts @@ -0,0 +1,36 @@ +/* + * 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 actionCreatorFactory from 'typescript-fsa'; +import { TimelineEventsType } from '../../../../common/types/timeline'; + +import { KibanaIndexPatterns, ManageScopeInit, SourcererScopeName } from './model'; + +const actionCreator = actionCreatorFactory('x-pack/security_solution/local/sourcerer'); + +export const setSource = actionCreator<{ + id: SourcererScopeName; + payload: ManageScopeInit; +}>('SET_SOURCE'); + +export const setIndexPatternsList = actionCreator<{ + kibanaIndexPatterns: KibanaIndexPatterns; + configIndexPatterns: string[]; +}>('SET_INDEX_PATTERNS_LIST'); + +export const setSignalIndexName = actionCreator<{ signalIndexName: string }>( + 'SET_SIGNAL_INDEX_NAME' +); + +export const setSourcererScopeLoading = actionCreator<{ id: SourcererScopeName; loading: boolean }>( + 'SET_SOURCERER_SCOPE_LOADING' +); + +export const setSelectedIndexPatterns = actionCreator<{ + id: SourcererScopeName; + selectedPatterns: string[]; + eventType?: TimelineEventsType; +}>('SET_SELECTED_INDEX_PATTERNS'); diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/index.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/index.ts new file mode 100644 index 00000000000000..551c7d8e3efbc6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/index.ts @@ -0,0 +1,12 @@ +/* + * 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 * as sourcererActions from './actions'; +import * as sourcererModel from './model'; +import * as sourcererSelectors from './selectors'; + +export { sourcererActions, sourcererModel, sourcererSelectors }; +export * from './reducer'; diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts new file mode 100644 index 00000000000000..93f7ff95dfb00e --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IIndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns'; +import { DocValueFields } from '../../../../common/search_strategy/common'; +import { + BrowserFields, + EMPTY_BROWSER_FIELDS, + EMPTY_DOCVALUE_FIELD, + EMPTY_INDEX_PATTERN, +} from '../../../../common/search_strategy/index_fields'; + +export type ErrorModel = Error[]; + +export enum SourcererScopeName { + default = 'default', + detections = 'detections', + timeline = 'timeline', +} + +export interface ManageScope { + browserFields: BrowserFields; + docValueFields: DocValueFields[]; + errorMessage: string | null; + id: SourcererScopeName; + indexPattern: IIndexPattern; + indicesExist: boolean | undefined | null; + loading: boolean; + selectedPatterns: string[]; +} + +export interface ManageScopeInit extends Partial { + id: SourcererScopeName; +} + +export type SourcererScopeById = { + [id in SourcererScopeName]: ManageScope; +}; + +export type KibanaIndexPatterns = Array<{ id: string; title: string }>; + +// ManageSourcerer +export interface SourcererModel { + kibanaIndexPatterns: KibanaIndexPatterns; + configIndexPatterns: string[]; + signalIndexName: string | null; + sourcererScopes: SourcererScopeById; +} + +export const initSourcererScope = { + browserFields: EMPTY_BROWSER_FIELDS, + docValueFields: EMPTY_DOCVALUE_FIELD, + errorMessage: null, + indexPattern: EMPTY_INDEX_PATTERN, + indicesExist: true, + loading: true, + selectedPatterns: [], +}; + +export const initialSourcererState: SourcererModel = { + kibanaIndexPatterns: [], + configIndexPatterns: [], + signalIndexName: null, + sourcererScopes: { + [SourcererScopeName.default]: { + ...initSourcererScope, + id: SourcererScopeName.default, + }, + [SourcererScopeName.detections]: { + ...initSourcererScope, + id: SourcererScopeName.detections, + }, + [SourcererScopeName.timeline]: { + ...initSourcererScope, + id: SourcererScopeName.timeline, + }, + }, +}; + +export type FSourcererScopePatterns = { + [id in SourcererScopeName]: string[]; +}; +export type SourcererScopePatterns = Partial; diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts new file mode 100644 index 00000000000000..b65d4d6338e504 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import isEmpty from 'lodash/isEmpty'; +import { reducerWithInitialState } from 'typescript-fsa-reducers'; + +import { + setIndexPatternsList, + setSourcererScopeLoading, + setSelectedIndexPatterns, + setSignalIndexName, + setSource, +} from './actions'; +import { initialSourcererState, SourcererModel, SourcererScopeName } from './model'; + +export type SourcererState = SourcererModel; + +export const sourcererReducer = reducerWithInitialState(initialSourcererState) + .case(setIndexPatternsList, (state, { kibanaIndexPatterns, configIndexPatterns }) => ({ + ...state, + kibanaIndexPatterns, + configIndexPatterns, + })) + .case(setSignalIndexName, (state, { signalIndexName }) => ({ + ...state, + signalIndexName, + })) + .case(setSourcererScopeLoading, (state, { id, loading }) => ({ + ...state, + sourcererScopes: { + ...state.sourcererScopes, + [id]: { + ...state.sourcererScopes[id], + loading, + }, + }, + })) + .case(setSelectedIndexPatterns, (state, { id, selectedPatterns, eventType }) => { + const kibanaIndexPatterns = state.kibanaIndexPatterns.map((kip) => kip.title); + const newSelectedPatterns = selectedPatterns.filter( + (sp) => + state.configIndexPatterns.includes(sp) || + kibanaIndexPatterns.includes(sp) || + (!isEmpty(state.signalIndexName) && state.signalIndexName === sp) + ); + let defaultIndexPatterns = state.configIndexPatterns; + if (id === SourcererScopeName.timeline && isEmpty(newSelectedPatterns)) { + if (eventType === 'all' && !isEmpty(state.signalIndexName)) { + defaultIndexPatterns = [...state.configIndexPatterns, state.signalIndexName ?? '']; + } else if (eventType === 'raw') { + defaultIndexPatterns = state.configIndexPatterns; + } else if ( + !isEmpty(state.signalIndexName) && + (eventType === 'signal' || eventType === 'alert') + ) { + defaultIndexPatterns = [state.signalIndexName ?? '']; + } + } else if (id === SourcererScopeName.detections && isEmpty(newSelectedPatterns)) { + defaultIndexPatterns = [state.signalIndexName ?? '']; + } + return { + ...state, + sourcererScopes: { + ...state.sourcererScopes, + [id]: { + ...state.sourcererScopes[id], + selectedPatterns: isEmpty(newSelectedPatterns) + ? defaultIndexPatterns + : newSelectedPatterns, + }, + }, + }; + }) + .case(setSource, (state, { id, payload }) => { + const { ...sourcererScopes } = payload; + return { + ...state, + sourcererScopes: { + ...state.sourcererScopes, + [id]: { + ...state.sourcererScopes[id], + ...sourcererScopes, + ...(state.sourcererScopes[id].selectedPatterns.length === 0 + ? { selectedPatterns: state.configIndexPatterns } + : {}), + }, + }, + }; + }) + .build(); diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts new file mode 100644 index 00000000000000..ca9ea26ba5bac0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts @@ -0,0 +1,91 @@ +/* + * 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 { createSelector } from 'reselect'; +import { State } from '../types'; +import { SourcererScopeById, KibanaIndexPatterns, SourcererScopeName, ManageScope } from './model'; + +export const sourcererKibanaIndexPatternsSelector = ({ sourcerer }: State): KibanaIndexPatterns => + sourcerer.kibanaIndexPatterns; + +export const sourcererSignalIndexNameSelector = ({ sourcerer }: State): string | null => + sourcerer.signalIndexName; + +export const sourcererConfigIndexPatternsSelector = ({ sourcerer }: State): string[] => + sourcerer.configIndexPatterns; + +export const sourcererScopesSelector = ({ sourcerer }: State): SourcererScopeById => + sourcerer.sourcererScopes; + +export const scopesSelector = () => createSelector(sourcererScopesSelector, (scopes) => scopes); + +export const kibanaIndexPatternsSelector = () => + createSelector( + sourcererKibanaIndexPatternsSelector, + (kibanaIndexPatterns) => kibanaIndexPatterns + ); + +export const signalIndexNameSelector = () => + createSelector(sourcererSignalIndexNameSelector, (signalIndexName) => signalIndexName); + +export const configIndexPatternsSelector = () => + createSelector( + sourcererConfigIndexPatternsSelector, + (configIndexPatterns) => configIndexPatterns + ); + +export const getIndexNamesSelectedSelector = () => { + const getScopesSelector = scopesSelector(); + const getConfigIndexPatternsSelector = configIndexPatternsSelector(); + + const mapStateToProps = (state: State, scopeId: SourcererScopeName): string[] => { + const scope = getScopesSelector(state)[scopeId]; + const configIndexPatterns = getConfigIndexPatternsSelector(state); + + return scope.selectedPatterns.length === 0 ? configIndexPatterns : scope.selectedPatterns; + }; + + return mapStateToProps; +}; + +export const getAllExistingIndexNamesSelector = () => { + const getSignalIndexNameSelector = signalIndexNameSelector(); + const getConfigIndexPatternsSelector = configIndexPatternsSelector(); + + const mapStateToProps = (state: State): string[] => { + const signalIndexName = getSignalIndexNameSelector(state); + const configIndexPatterns = getConfigIndexPatternsSelector(state); + + return signalIndexName != null + ? [...configIndexPatterns, signalIndexName] + : configIndexPatterns; + }; + + return mapStateToProps; +}; + +export const defaultIndexNamesSelector = () => { + const getScopesSelector = scopesSelector(); + const getConfigIndexPatternsSelector = configIndexPatternsSelector(); + + const mapStateToProps = (state: State, scopeId: SourcererScopeName): string[] => { + const scope = getScopesSelector(state)[scopeId]; + const configIndexPatterns = getConfigIndexPatternsSelector(state); + + return scope.selectedPatterns.length === 0 ? configIndexPatterns : scope.selectedPatterns; + }; + + return mapStateToProps; +}; + +export const getSourcererScopeSelector = () => { + const getScopesSelector = scopesSelector(); + + const mapStateToProps = (state: State, scopeId: SourcererScopeName): ManageScope => + getScopesSelector(state)[scopeId]; + + return mapStateToProps; +}; diff --git a/x-pack/plugins/security_solution/public/common/store/types.ts b/x-pack/plugins/security_solution/public/common/store/types.ts index 91d92e4758c4a0..6903567c752bc2 100644 --- a/x-pack/plugins/security_solution/public/common/store/types.ts +++ b/x-pack/plugins/security_solution/public/common/store/types.ts @@ -12,6 +12,7 @@ import { AppAction } from './actions'; import { Immutable } from '../../../common/endpoint/types'; import { AppState } from './app/reducer'; import { InputsState } from './inputs/reducer'; +import { SourcererState } from './sourcerer/reducer'; import { HostsPluginState } from '../../hosts/store'; import { DragAndDropState } from './drag_and_drop/reducer'; import { TimelinePluginState } from '../../timelines/store/timeline'; @@ -25,6 +26,7 @@ export type StoreState = HostsPluginState & app: AppState; dragAndDrop: DragAndDropState; inputs: InputsState; + sourcerer: SourcererState; }; /** * The redux `State` type for the Security App. diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx index 678aaf06e50e45..e3440f41585130 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx @@ -197,6 +197,7 @@ describe('alert actions', () => { highlightedDropAndProviderId: '', historyIds: [], id: '', + indexNames: [], isFavorite: false, isLive: false, isLoading: false, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx index 640726bb2e7c86..7f98d3b2f71de2 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx @@ -279,6 +279,7 @@ export const sendAlertToTimelineAction = async ({ ...getThresholdAggregationDataProvider(ecsData, nonEcsData), ], id: TimelineId.active, + indexNames: [], dateRange: { start: from, end: to, @@ -329,6 +330,7 @@ export const sendAlertToTimelineAction = async ({ }, ], id: TimelineId.active, + indexNames: [], dateRange: { start: from, end: to, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx index be249576020370..6724d3a83d6175 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx @@ -22,7 +22,6 @@ describe('AlertsTableComponent', () => { hasIndexWrite from={'2020-07-07T08:20:18.966Z'} loading - signalsIndex="index" to={'2020-07-08T08:20:18.966Z'} globalQuery={{ query: 'query', diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index 0416b3d2a459f9..d66d37a020040b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -13,7 +13,6 @@ import { Status } from '../../../../common/detection_engine/schemas/common/schem import { Filter, esQuery } from '../../../../../../../src/plugins/data/public'; import { TimelineIdLiteral } from '../../../../common/types/timeline'; import { useAppToasts } from '../../../common/hooks/use_app_toasts'; -import { useFetchIndexPatterns } from '../../containers/detection_engine/rules/fetch_index_patterns'; import { StatefulEventsViewer } from '../../../common/components/events_viewer'; import { HeaderSection } from '../../../common/components/header_section'; import { combineQueries } from '../../../timelines/components/timeline/helpers'; @@ -45,6 +44,8 @@ import { displaySuccessToast, displayErrorToast, } from '../../../common/components/toasters'; +import { SourcererScopeName } from '../../../common/store/sourcerer/model'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; interface OwnProps { timelineId: TimelineIdLiteral; @@ -55,7 +56,6 @@ interface OwnProps { loading: boolean; showBuildingBlockAlerts: boolean; onShowBuildingBlockAlertsChanged: (showBuildingBlockAlerts: boolean) => void; - signalsIndex: string; to: string; } @@ -80,19 +80,20 @@ export const AlertsTableComponent: React.FC = ({ setEventsLoading, showBuildingBlockAlerts, onShowBuildingBlockAlertsChanged, - signalsIndex, to, }) => { const [showClearSelectionAction, setShowClearSelectionAction] = useState(false); const [filterGroup, setFilterGroup] = useState(FILTER_OPEN); - const [{ browserFields, indexPatterns, isLoading: indexPatternsLoading }] = useFetchIndexPatterns( - signalsIndex !== '' ? [signalsIndex] : [], - 'alerts_table' - ); + const { + browserFields, + indexPattern: indexPatterns, + loading: indexPatternsLoading, + selectedPatterns, + } = useSourcererScope(SourcererScopeName.detections); const kibana = useKibana(); const [, dispatchToaster] = useStateToaster(); const { addWarning } = useAppToasts(); - const { initializeTimeline, setSelectAll, setIndexToAdd } = useManageTimeline(); + const { initializeTimeline, setSelectAll } = useManageTimeline(); const getGlobalQuery = useCallback( (customFilters: Filter[]) => { @@ -284,7 +285,6 @@ export const AlertsTableComponent: React.FC = ({ ] ); - const defaultIndices = useMemo(() => [signalsIndex], [signalsIndex]); const defaultFiltersMemo = useMemo(() => { if (isEmpty(defaultFilters)) { return buildAlertStatusFilter(filterGroup); @@ -301,7 +301,6 @@ export const AlertsTableComponent: React.FC = ({ filterManager, footerText: i18n.TOTAL_COUNT_OF_ALERTS, id: timelineId, - indexToAdd: defaultIndices, loadingText: i18n.LOADING_ALERTS, selectAll: false, queryFields: requiredFieldsForActions, @@ -310,16 +309,12 @@ export const AlertsTableComponent: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { - setIndexToAdd({ id: timelineId, indexToAdd: defaultIndices }); - }, [timelineId, defaultIndices, setIndexToAdd]); - const headerFilterGroup = useMemo( () => , [onFilterGroupChangedCallback] ); - if (loading || indexPatternsLoading || isEmpty(signalsIndex)) { + if (loading || indexPatternsLoading || isEmpty(selectedPatterns)) { return ( @@ -330,12 +325,12 @@ export const AlertsTableComponent: React.FC = ({ return ( diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index 4559e44b8c3c5c..82fed152ea66d9 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -109,7 +109,7 @@ const AlertContextMenuComponent: React.FC = ({ const closeAddExceptionModal = useCallback(() => { setShouldShowAddExceptionModal(false); setAddExceptionModalState(addExceptionModalInitialState); - }, [setShouldShowAddExceptionModal, setAddExceptionModalState]); + }, []); const onAddExceptionCancel = useCallback(() => { closeAddExceptionModal(); @@ -305,33 +305,6 @@ const AlertContextMenuComponent: React.FC = ({ [setShouldShowAddExceptionModal, setAddExceptionModalState] ); - const AddExceptionModal = useCallback( - () => - shouldShowAddExceptionModal === true && addExceptionModalState.alertData !== null ? ( - - ) : null, - [ - shouldShowAddExceptionModal, - addExceptionModalState.alertData, - addExceptionModalState.ruleName, - addExceptionModalState.ruleId, - addExceptionModalState.ruleIndices, - addExceptionModalState.exceptionListType, - onAddExceptionCancel, - onAddExceptionConfirm, - alertStatus, - ] - ); - const button = ( = ({ - + {shouldShowAddExceptionModal === true && addExceptionModalState.alertData !== null && ( + + )} ); }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx index 4ab5fa5e6012fd..f4649b016f67c7 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.tsx @@ -15,7 +15,6 @@ import { useApolloClient } from '../../../../common/utils/apollo_context'; import { sendAlertToTimelineAction } from '../actions'; import { dispatchUpdateTimeline } from '../../../../timelines/components/open_timeline/helpers'; import { ActionIconItem } from '../../../../timelines/components/timeline/body/actions/action_icon_item'; - import { CreateTimelineProps } from '../types'; import { ACTION_INVESTIGATE_IN_TIMELINE, @@ -49,6 +48,8 @@ const InvestigateInTimelineActionComponent: React.FC = (props) => ( - + ); DetectionEngineHeaderPageComponent.defaultProps = { diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx index cb25785eaa5b29..4312be0b469904 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx @@ -8,8 +8,9 @@ import { mount, shallow } from 'enzyme'; import { ThemeProvider } from 'styled-components'; import euiDarkVars from '@elastic/eui/dist/eui_theme_light.json'; +import { stubIndexPattern } from 'src/plugins/data/common/index_patterns/index_pattern.stub'; import { StepAboutRule } from '.'; - +import { useFetchIndex } from '../../../../common/containers/source'; import { mockAboutStepRule } from '../../../pages/detection_engine/rules/all/__mocks__/mock'; import { StepRuleDescription } from '../description_step'; import { stepAboutDefaultValue } from './default_value'; @@ -20,6 +21,7 @@ import { } from '../../../pages/detection_engine/rules/types'; import { fillEmptySeverityMappings } from '../../../pages/detection_engine/rules/helpers'; +jest.mock('../../../../common/containers/source'); const theme = () => ({ eui: euiDarkVars, darkMode: true }); /* eslint-disable no-console */ @@ -44,6 +46,12 @@ describe('StepAboutRuleComponent', () => { beforeEach(() => { formHook = null; + (useFetchIndex as jest.Mock).mockImplementation(() => [ + false, + { + indexPatterns: stubIndexPattern, + }, + ]); }); test('it renders StepRuleDescription if isReadOnlyView is true and "name" property exists', () => { diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx index 66f95f5ce15d21..90b70e53a459e0 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx @@ -39,8 +39,8 @@ import { NextStep } from '../next_step'; import { MarkdownEditorForm } from '../../../../common/components/markdown_editor/eui_form'; import { SeverityField } from '../severity_mapping'; import { RiskScoreField } from '../risk_score_mapping'; -import { useFetchIndexPatterns } from '../../../containers/detection_engine/rules'; import { AutocompleteField } from '../autocomplete_field'; +import { useFetchIndex } from '../../../../common/containers/source'; const CommonUseField = getUseField({ component: Field }); @@ -74,10 +74,8 @@ const StepAboutRuleComponent: FC = ({ }) => { const initialState = defaultValues ?? stepAboutDefaultValue; const [severityValue, setSeverityValue] = useState(initialState.severity.value); - const [{ isLoading: indexPatternLoading, indexPatterns }] = useFetchIndexPatterns( - defineRuleData?.index ?? [], - RuleStep.aboutRule - ); + const [indexPatternLoading, { indexPatterns }] = useFetchIndex(defineRuleData?.index ?? []); + const canUseExceptions = defineRuleData?.ruleType && !isMlRule(defineRuleData.ruleType) && diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx index 7846f0c406668c..99999ddbf19767 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx @@ -14,7 +14,6 @@ import { DEFAULT_TIMELINE_TITLE } from '../../../../timelines/components/timelin import { isMlRule } from '../../../../../common/machine_learning/helpers'; import { hasMlAdminPermissions } from '../../../../../common/machine_learning/has_ml_admin_permissions'; import { hasMlLicense } from '../../../../../common/machine_learning/has_ml_license'; -import { useFetchIndexPatterns } from '../../../containers/detection_engine/rules'; import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; import { useUiSetting$ } from '../../../../common/lib/kibana'; import { @@ -48,6 +47,7 @@ import { schema } from './schema'; import * as i18n from './translations'; import { isEqlRule, isThresholdRule } from '../../../../../common/detection_engine/utils'; import { EqlQueryBar } from '../eql_query_bar'; +import { useFetchIndex } from '../../../../common/containers/source'; const CommonUseField = getUseField({ component: Field }); @@ -125,10 +125,7 @@ const StepDefineRuleComponent: FC = ({ }) as unknown) as [Partial]; const index = formIndex || initialState.index; const ruleType = formRuleType || initialState.ruleType; - const [{ browserFields, indexPatterns, isLoading: indexPatternsLoading }] = useFetchIndexPatterns( - index, - RuleStep.defineRule - ); + const [indexPatternsLoading, { browserFields, indexPatterns }] = useFetchIndex(index); // reset form when rule type changes useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx b/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx index e1a29c3575d95c..00e108ffb89b64 100644 --- a/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx @@ -169,22 +169,19 @@ export const useUserInfo = (): State => { if (loading !== privilegeLoading || indexNameLoading) { dispatch({ type: 'updateLoading', loading: privilegeLoading || indexNameLoading }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, privilegeLoading, indexNameLoading]); + }, [dispatch, loading, privilegeLoading, indexNameLoading]); useEffect(() => { if (!loading && hasIndexManage !== hasApiIndexManage && hasApiIndexManage != null) { dispatch({ type: 'updateHasIndexManage', hasIndexManage: hasApiIndexManage }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, hasIndexManage, hasApiIndexManage]); + }, [dispatch, loading, hasIndexManage, hasApiIndexManage]); useEffect(() => { if (!loading && hasIndexWrite !== hasApiIndexWrite && hasApiIndexWrite != null) { dispatch({ type: 'updateHasIndexWrite', hasIndexWrite: hasApiIndexWrite }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, hasIndexWrite, hasApiIndexWrite]); + }, [dispatch, loading, hasIndexWrite, hasApiIndexWrite]); useEffect(() => { if ( @@ -194,36 +191,31 @@ export const useUserInfo = (): State => { ) { dispatch({ type: 'updateIsSignalIndexExists', isSignalIndexExists: isApiSignalIndexExists }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, isSignalIndexExists, isApiSignalIndexExists]); + }, [dispatch, loading, isSignalIndexExists, isApiSignalIndexExists]); useEffect(() => { if (!loading && isAuthenticated !== isApiAuthenticated && isApiAuthenticated != null) { dispatch({ type: 'updateIsAuthenticated', isAuthenticated: isApiAuthenticated }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, isAuthenticated, isApiAuthenticated]); + }, [dispatch, loading, isAuthenticated, isApiAuthenticated]); useEffect(() => { if (!loading && hasEncryptionKey !== isApiEncryptionKey && isApiEncryptionKey != null) { dispatch({ type: 'updateHasEncryptionKey', hasEncryptionKey: isApiEncryptionKey }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, hasEncryptionKey, isApiEncryptionKey]); + }, [dispatch, loading, hasEncryptionKey, isApiEncryptionKey]); useEffect(() => { if (!loading && canUserCRUD !== capabilitiesCanUserCRUD && capabilitiesCanUserCRUD != null) { dispatch({ type: 'updateCanUserCRUD', canUserCRUD: capabilitiesCanUserCRUD }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, canUserCRUD, capabilitiesCanUserCRUD]); + }, [dispatch, loading, canUserCRUD, capabilitiesCanUserCRUD]); useEffect(() => { if (!loading && signalIndexName !== apiSignalIndexName && apiSignalIndexName != null) { dispatch({ type: 'updateSignalIndexName', signalIndexName: apiSignalIndexName }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loading, signalIndexName, apiSignalIndexName]); + }, [dispatch, loading, signalIndexName, apiSignalIndexName]); useEffect(() => { if ( diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/fetch_index_patterns.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/fetch_index_patterns.test.tsx deleted file mode 100644 index d36c19a6a35c66..00000000000000 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/fetch_index_patterns.test.tsx +++ /dev/null @@ -1,475 +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 { renderHook, act } from '@testing-library/react-hooks'; - -import { DEFAULT_INDEX_PATTERN } from '../../../../../common/constants'; -import { useApolloClient } from '../../../../common/utils/apollo_context'; -import { mocksSource } from '../../../../common/containers/source/mock'; - -import { useFetchIndexPatterns, Return } from './fetch_index_patterns'; - -const mockUseApolloClient = useApolloClient as jest.Mock; -jest.mock('../../../../common/utils/apollo_context'); - -describe('useFetchIndexPatterns', () => { - beforeEach(() => { - mockUseApolloClient.mockClear(); - }); - test('happy path', async () => { - await act(async () => { - mockUseApolloClient.mockImplementation(() => ({ - query: () => Promise.resolve(mocksSource[0].result), - })); - const { result, waitForNextUpdate } = renderHook(() => - useFetchIndexPatterns(DEFAULT_INDEX_PATTERN) - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(result.current).toEqual([ - { - browserFields: { - base: { - fields: { - '@timestamp': { - category: 'base', - description: - 'Date/time when the event originated. For log events this is the date/time when the event was generated, and not when it was read. Required field for all events.', - example: '2016-05-23T08:05:34.853Z', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: '@timestamp', - searchable: true, - type: 'date', - aggregatable: true, - }, - }, - }, - agent: { - fields: { - 'agent.ephemeral_id': { - category: 'agent', - description: - 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.ephemeral_id', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'agent.hostname': { - category: 'agent', - description: null, - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.hostname', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'agent.id': { - category: 'agent', - description: - 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', - example: '8a4f500d', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.id', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'agent.name': { - category: 'agent', - description: - 'Name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', - example: 'foo', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'agent.name', - searchable: true, - type: 'string', - aggregatable: true, - }, - }, - }, - auditd: { - fields: { - 'auditd.data.a0': { - category: 'auditd', - description: null, - example: null, - format: '', - indexes: ['auditbeat'], - name: 'auditd.data.a0', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'auditd.data.a1': { - category: 'auditd', - description: null, - example: null, - format: '', - indexes: ['auditbeat'], - name: 'auditd.data.a1', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'auditd.data.a2': { - category: 'auditd', - description: null, - example: null, - format: '', - indexes: ['auditbeat'], - name: 'auditd.data.a2', - searchable: true, - type: 'string', - aggregatable: true, - }, - }, - }, - client: { - fields: { - 'client.address': { - category: 'client', - description: - 'Some event client addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.address', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'client.bytes': { - category: 'client', - description: 'Bytes sent from the client to the server.', - example: '184', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.bytes', - searchable: true, - type: 'number', - aggregatable: true, - }, - 'client.domain': { - category: 'client', - description: 'Client domain.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.domain', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'client.geo.country_iso_code': { - category: 'client', - description: 'Country ISO code.', - example: 'CA', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'client.geo.country_iso_code', - searchable: true, - type: 'string', - aggregatable: true, - }, - }, - }, - cloud: { - fields: { - 'cloud.account.id': { - category: 'cloud', - description: - 'The cloud account or organization id used to identify different entities in a multi-tenant environment. Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: '666777888999', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'cloud.account.id', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'cloud.availability_zone': { - category: 'cloud', - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'cloud.availability_zone', - searchable: true, - type: 'string', - aggregatable: true, - }, - }, - }, - container: { - fields: { - 'container.id': { - category: 'container', - description: 'Unique container id.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'container.id', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'container.image.name': { - category: 'container', - description: 'Name of the image the container was built on.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'container.image.name', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'container.image.tag': { - category: 'container', - description: 'Container image tag.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'container.image.tag', - searchable: true, - type: 'string', - aggregatable: true, - }, - }, - }, - destination: { - fields: { - 'destination.address': { - category: 'destination', - description: - 'Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.address', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'destination.bytes': { - category: 'destination', - description: 'Bytes sent from the destination to the source.', - example: '184', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.bytes', - searchable: true, - type: 'number', - aggregatable: true, - }, - 'destination.domain': { - category: 'destination', - description: 'Destination domain.', - example: null, - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.domain', - searchable: true, - type: 'string', - aggregatable: true, - }, - 'destination.ip': { - aggregatable: true, - category: 'destination', - description: - 'IP address of the destination. Can be one or multiple IPv4 or IPv6 addresses.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.ip', - searchable: true, - type: 'ip', - }, - 'destination.port': { - aggregatable: true, - category: 'destination', - description: 'Port of the destination.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'destination.port', - searchable: true, - type: 'long', - }, - }, - }, - source: { - fields: { - 'source.ip': { - aggregatable: true, - category: 'source', - description: - 'IP address of the source. Can be one or multiple IPv4 or IPv6 addresses.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'source.ip', - searchable: true, - type: 'ip', - }, - 'source.port': { - aggregatable: true, - category: 'source', - description: 'Port of the source.', - example: '', - format: '', - indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'source.port', - searchable: true, - type: 'long', - }, - }, - }, - event: { - fields: { - 'event.end': { - aggregatable: true, - category: 'event', - description: - 'event.end contains the date when the event ended or when the activity was last observed.', - example: null, - format: '', - indexes: [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - name: 'event.end', - searchable: true, - type: 'date', - }, - }, - }, - }, - isLoading: false, - indices: [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - indicesExists: true, - docValueFields: [ - { - field: '@timestamp', - format: 'date_time', - }, - { - field: 'event.end', - format: 'date_time', - }, - ], - indexPatterns: { - fields: [ - { name: '@timestamp', searchable: true, type: 'date', aggregatable: true }, - { name: 'agent.ephemeral_id', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.hostname', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.id', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.name', searchable: true, type: 'string', aggregatable: true }, - { name: 'auditd.data.a0', searchable: true, type: 'string', aggregatable: true }, - { name: 'auditd.data.a1', searchable: true, type: 'string', aggregatable: true }, - { name: 'auditd.data.a2', searchable: true, type: 'string', aggregatable: true }, - { name: 'client.address', searchable: true, type: 'string', aggregatable: true }, - { name: 'client.bytes', searchable: true, type: 'number', aggregatable: true }, - { name: 'client.domain', searchable: true, type: 'string', aggregatable: true }, - { - name: 'client.geo.country_iso_code', - searchable: true, - type: 'string', - aggregatable: true, - }, - { name: 'cloud.account.id', searchable: true, type: 'string', aggregatable: true }, - { - name: 'cloud.availability_zone', - searchable: true, - type: 'string', - aggregatable: true, - }, - { name: 'container.id', searchable: true, type: 'string', aggregatable: true }, - { - name: 'container.image.name', - searchable: true, - type: 'string', - aggregatable: true, - }, - { name: 'container.image.tag', searchable: true, type: 'string', aggregatable: true }, - { name: 'destination.address', searchable: true, type: 'string', aggregatable: true }, - { name: 'destination.bytes', searchable: true, type: 'number', aggregatable: true }, - { name: 'destination.domain', searchable: true, type: 'string', aggregatable: true }, - { name: 'destination.ip', searchable: true, type: 'ip', aggregatable: true }, - { name: 'destination.port', searchable: true, type: 'long', aggregatable: true }, - { name: 'source.ip', searchable: true, type: 'ip', aggregatable: true }, - { name: 'source.port', searchable: true, type: 'long', aggregatable: true }, - { name: 'event.end', searchable: true, type: 'date', aggregatable: true }, - ], - title: - 'apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', - }, - }, - result.current[1], - ]); - }); - }); - - test('unhappy path', async () => { - await act(async () => { - mockUseApolloClient.mockImplementation(() => ({ - query: () => Promise.reject(new Error('Something went wrong')), - })); - const { result, waitForNextUpdate } = renderHook(() => - useFetchIndexPatterns(DEFAULT_INDEX_PATTERN) - ); - - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(result.current).toEqual([ - { - browserFields: {}, - docValueFields: [], - indexPatterns: { - fields: [], - title: '', - }, - indices: [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - indicesExists: false, - isLoading: false, - }, - result.current[1], - ]); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/fetch_index_patterns.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/fetch_index_patterns.tsx deleted file mode 100644 index 82c9292af74515..00000000000000 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/fetch_index_patterns.tsx +++ /dev/null @@ -1,132 +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 { isEmpty, get } from 'lodash/fp'; -import { useEffect, useState, Dispatch, SetStateAction } from 'react'; -import deepEqual from 'fast-deep-equal'; - -import { IIndexPattern } from '../../../../../../../../src/plugins/data/public'; -import { - BrowserFields, - getBrowserFields, - getDocValueFields, - getIndexFields, - sourceQuery, - DocValueFields, -} from '../../../../common/containers/source'; -import { errorToToaster, useStateToaster } from '../../../../common/components/toasters'; -import { SourceQuery } from '../../../../graphql/types'; -import { useApolloClient } from '../../../../common/utils/apollo_context'; - -import * as i18n from './translations'; - -interface FetchIndexPatternReturn { - browserFields: BrowserFields; - docValueFields: DocValueFields[]; - isLoading: boolean; - indices: string[]; - indicesExists: boolean; - indexPatterns: IIndexPattern; -} - -export type Return = [FetchIndexPatternReturn, Dispatch>]; - -const DEFAULT_BROWSER_FIELDS = {}; -const DEFAULT_INDEX_PATTERNS = { fields: [], title: '' }; -const DEFAULT_DOC_VALUE_FIELDS: DocValueFields[] = []; - -// Fun fact: When using this hook multiple times within a component (e.g. add_exception_modal & edit_exception_modal), -// the apolloClient will perform queryDeduplication and prevent the first query from executing. A deep compare is not -// performed on `indices`, so another field must be passed to circumvent this. -// For details, see https://github.com/apollographql/react-apollo/issues/2202 -export const useFetchIndexPatterns = ( - defaultIndices: string[] = [], - queryDeduplication?: string -): Return => { - const apolloClient = useApolloClient(); - const [indices, setIndices] = useState(defaultIndices); - - const [state, setState] = useState({ - browserFields: DEFAULT_BROWSER_FIELDS, - docValueFields: DEFAULT_DOC_VALUE_FIELDS, - indices: defaultIndices, - indicesExists: false, - indexPatterns: DEFAULT_INDEX_PATTERNS, - isLoading: false, - }); - - const [, dispatchToaster] = useStateToaster(); - - useEffect(() => { - if (!deepEqual(defaultIndices, indices)) { - setIndices(defaultIndices); - setState((prevState) => ({ ...prevState, indices: defaultIndices })); - } - }, [defaultIndices, indices]); - - useEffect(() => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - - async function fetchIndexPatterns() { - if (apolloClient && !isEmpty(indices)) { - setState((prevState) => ({ ...prevState, isLoading: true })); - apolloClient - .query({ - query: sourceQuery, - fetchPolicy: 'cache-first', - variables: { - sourceId: 'default', - defaultIndex: indices, - ...(queryDeduplication != null ? { queryDeduplication } : {}), - }, - context: { - fetchOptions: { - signal: abortCtrl.signal, - }, - }, - }) - .then( - (result) => { - if (isSubscribed) { - setState({ - browserFields: getBrowserFields( - indices.join(), - get('data.source.status.indexFields', result) - ), - docValueFields: getDocValueFields( - indices.join(), - get('data.source.status.indexFields', result) - ), - indices, - isLoading: false, - indicesExists: get('data.source.status.indicesExist', result), - indexPatterns: getIndexFields( - indices.join(), - get('data.source.status.indexFields', result) - ), - }); - } - }, - (error) => { - if (isSubscribed) { - setState((prevState) => ({ ...prevState, isLoading: false })); - errorToToaster({ title: i18n.RULE_ADD_FAILURE, error, dispatchToaster }); - } - } - ); - } - } - fetchIndexPatterns(); - return () => { - isSubscribed = false; - abortCtrl.abort(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [indices]); - - return [state, setIndices]; -}; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/index.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/index.ts index a40ab2e4878519..930391261ac873 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/index.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/index.ts @@ -5,7 +5,6 @@ */ export * from './api'; -export * from './fetch_index_patterns'; export * from './use_update_rule'; export * from './use_create_rule'; export * from './types'; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index 8c21f6a1e8cb78..a5d21d28475860 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -20,7 +20,7 @@ import { import { setAbsoluteRangeDatePicker } from '../../../common/store/inputs/actions'; import { DetectionEnginePageComponent } from './detection_engine'; import { useUserData } from '../../components/user_info'; -import { useWithSource } from '../../../common/containers/source'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; import { createStore, State } from '../../../common/store'; import { mockHistory, Router } from '../../../cases/components/__mock__/router'; @@ -34,7 +34,7 @@ jest.mock('../../../common/components/query_bar', () => ({ })); jest.mock('../../containers/detection_engine/lists/use_lists_config'); jest.mock('../../components/user_info'); -jest.mock('../../../common/containers/source'); +jest.mock('../../../common/containers/sourcerer'); jest.mock('../../../common/components/link_to'); jest.mock('../../../common/containers/use_global_time', () => ({ useGlobalTime: jest.fn().mockReturnValue({ @@ -74,7 +74,7 @@ describe('DetectionEnginePageComponent', () => { beforeAll(() => { (useParams as jest.Mock).mockReturnValue({}); (useUserData as jest.Mock).mockReturnValue([{}]); - (useWithSource as jest.Mock).mockReturnValue({ + (useSourcererScope as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx index 3a3854f145db3d..b39cd375216028 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx @@ -13,7 +13,6 @@ import { useHistory } from 'react-router-dom'; import { SecurityPageName } from '../../../app/types'; import { TimelineId } from '../../../../common/types/timeline'; import { useGlobalTime } from '../../../common/containers/use_global_time'; -import { useWithSource } from '../../../common/containers/source'; import { UpdateDateRange } from '../../../common/components/charts/common'; import { FiltersGlobal } from '../../../common/components/filters_global'; import { getRulesUrl } from '../../../common/components/link_to/redirect_to_detection_engine'; @@ -46,6 +45,8 @@ import { timelineSelectors } from '../../../timelines/store/timeline'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; import { TimelineModel } from '../../../timelines/store/timeline/model'; import { buildShowBuildingBlockFilter } from '../../components/alerts_table/default_config'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; +import { SourcererScopeName } from '../../../common/store/sourcerer/model'; export const DetectionEnginePageComponent: React.FC = ({ filters, @@ -117,10 +118,7 @@ export const DetectionEnginePageComponent: React.FC = ({ [setShowBuildingBlockAlerts] ); - const indexToAdd = useMemo(() => (signalIndexName == null ? [] : [signalIndexName]), [ - signalIndexName, - ]); - const { indicesExist, indexPattern } = useWithSource('default', indexToAdd); + const { indicesExist, indexPattern } = useSourcererScope(SourcererScopeName.detections); if (isUserAuthenticated != null && !isUserAuthenticated && !loading) { return ( @@ -202,7 +200,6 @@ export const DetectionEnginePageComponent: React.FC = ({ defaultFilters={alertsTableDefaultFilters} showBuildingBlockAlerts={showBuildingBlockAlerts} onShowBuildingBlockAlertsChanged={onShowBuildingBlockAlertsChangedCallback} - signalsIndex={signalIndexName ?? ''} to={to} /> diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx index f8f9da78b2a062..22c3c43fb23563 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx @@ -20,7 +20,7 @@ import { RuleDetailsPageComponent } from './index'; import { createStore, State } from '../../../../../common/store'; import { setAbsoluteRangeDatePicker } from '../../../../../common/store/inputs/actions'; import { useUserData } from '../../../../components/user_info'; -import { useWithSource } from '../../../../../common/containers/source'; +import { useSourcererScope } from '../../../../../common/containers/sourcerer'; import { useParams } from 'react-router-dom'; import { mockHistory, Router } from '../../../../../cases/components/__mock__/router'; @@ -35,7 +35,7 @@ jest.mock('../../../../../common/components/query_bar', () => ({ jest.mock('../../../../containers/detection_engine/lists/use_lists_config'); jest.mock('../../../../../common/components/link_to'); jest.mock('../../../../components/user_info'); -jest.mock('../../../../../common/containers/source'); +jest.mock('../../../../../common/containers/sourcerer'); jest.mock('../../../../../common/containers/use_global_time', () => ({ useGlobalTime: jest.fn().mockReturnValue({ from: '2020-07-07T08:20:18.966Z', @@ -71,7 +71,7 @@ describe('RuleDetailsPageComponent', () => { beforeAll(() => { (useUserData as jest.Mock).mockReturnValue([{}]); (useParams as jest.Mock).mockReturnValue({}); - (useWithSource as jest.Mock).mockReturnValue({ + (useSourcererScope as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index 68799f46eee57c..ad8ab3ed3a1480 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -36,10 +36,7 @@ import { SiemSearchBar } from '../../../../../common/components/search_bar'; import { WrapperPage } from '../../../../../common/components/wrapper_page'; import { Rule } from '../../../../containers/detection_engine/rules'; import { useListsConfig } from '../../../../containers/detection_engine/lists/use_lists_config'; - -import { useWithSource } from '../../../../../common/containers/source'; import { SpyRoute } from '../../../../../common/utils/route/spy_routes'; - import { StepAboutRuleToggleDetails } from '../../../../components/rules/step_about_rule_details'; import { DetectionEngineHeaderPage } from '../../../../components/detection_engine_header_page'; import { AlertsHistogramPanel } from '../../../../components/alerts_histogram_panel'; @@ -89,6 +86,9 @@ import { showGlobalFilters } from '../../../../../timelines/components/timeline/ import { timelineSelectors } from '../../../../../timelines/store/timeline'; import { timelineDefaults } from '../../../../../timelines/store/timeline/defaults'; import { TimelineModel } from '../../../../../timelines/store/timeline/model'; +import { useSourcererScope } from '../../../../../common/containers/sourcerer'; +import { SourcererScopeName } from '../../../../../common/store/sourcerer/model'; +import { AlertsHistogramOption } from '../../../../components/alerts_histogram_panel/types'; enum RuleDetailTabs { alerts = 'alerts', @@ -265,10 +265,6 @@ export const RuleDetailsPageComponent: FC = ({ [rule, ruleDetailTab] ); - const indexToAdd = useMemo(() => (signalIndexName == null ? [] : [signalIndexName]), [ - signalIndexName, - ]); - const updateDateRangeCallback = useCallback( ({ x }) => { if (!x) { @@ -308,7 +304,7 @@ export const RuleDetailsPageComponent: FC = ({ [setShowBuildingBlockAlerts] ); - const { indicesExist, indexPattern } = useWithSource('default', indexToAdd); + const { indicesExist, indexPattern } = useSourcererScope(SourcererScopeName.detections); const exceptionLists = useMemo((): { lists: ExceptionIdentifiers[]; @@ -350,6 +346,11 @@ export const RuleDetailsPageComponent: FC = ({ return null; } + const defaultRuleStackByOption: AlertsHistogramOption = { + text: 'event.category', + value: 'event.category', + }; + return ( <> {hasIndexWrite != null && !hasIndexWrite && } @@ -485,6 +486,7 @@ export const RuleDetailsPageComponent: FC = ({ signalIndexName={signalIndexName} setQuery={setQuery} stackByOptions={alertsHistogramOptions} + defaultStackByOption={defaultRuleStackByOption} to={to} updateDateRange={updateDateRangeCallback} /> @@ -500,7 +502,6 @@ export const RuleDetailsPageComponent: FC = ({ loading={loading} showBuildingBlockAlerts={showBuildingBlockAlerts} onShowBuildingBlockAlertsChanged={onShowBuildingBlockAlertsChangedCallback} - signalsIndex={signalIndexName ?? ''} to={to} /> )} diff --git a/x-pack/plugins/security_solution/public/graphql/introspection.json b/x-pack/plugins/security_solution/public/graphql/introspection.json index 0bbc1fcc80e922..ece07124143497 100644 --- a/x-pack/plugins/security_solution/public/graphql/introspection.json +++ b/x-pack/plugins/security_solution/public/graphql/introspection.json @@ -1245,174 +1245,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "IpOverview", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - }, - { - "name": "docValueFields", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "docValueFieldsInput", - "ofType": null - } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "IpOverviewData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "Users", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "UsersSortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "flowTarget", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTarget", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UsersData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "KpiNetwork", "description": "", @@ -2089,215 +1921,56 @@ "deprecationReason": null }, { - "name": "OverviewNetwork", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "OverviewNetworkData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OverviewHost", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { "kind": "OBJECT", "name": "OverviewHostData", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UncommonProcesses", - "description": "Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified", - "args": [ - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UncommonProcessesData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "whoAmI", - "description": "Just a simple example to get the app name", - "args": [], - "type": { "kind": "OBJECT", "name": "SayMyName", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SourceConfiguration", - "description": "A set of configuration options for a security data source", - "fields": [ - { - "name": "fields", - "description": "The field mapping to use for this source", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "SourceFields", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SourceFields", - "description": "A mapping of semantic fields to their document counterparts", - "fields": [ - { - "name": "container", - "description": "The field to identify a container by", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, + "name": "whoAmI", + "description": "Just a simple example to get the app name", + "args": [], + "type": { "kind": "OBJECT", "name": "SayMyName", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SourceConfiguration", + "description": "A set of configuration options for a security data source", + "fields": [ + { + "name": "fields", + "description": "The field mapping to use for this source", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "SourceFields", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SourceFields", + "description": "A mapping of semantic fields to their document counterparts", + "fields": [ + { + "name": "container", + "description": "The field to identify a container by", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null }, @@ -2443,7 +2116,7 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "IndexField", "ofType": null } + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } } } }, @@ -2467,228 +2140,81 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "IndexField", - "description": "A descriptor of a field in an index", - "fields": [ + "kind": "INPUT_OBJECT", + "name": "TimerangeInput", + "description": "", + "fields": null, + "inputFields": [ { - "name": "category", - "description": "Where the field belong", - "args": [], + "name": "interval", + "description": "The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan.", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "example", - "description": "Example of field's value", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "indexes", - "description": "whether the field's belong to an alias index", - "args": [], + "name": "to", + "description": "The end of the timerange", "type": { "kind": "NON_NULL", "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "name", - "description": "The name of the field", - "args": [], + "name": "from", + "description": "The beginning of the timerange", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null - }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "PaginationInputPaginated", + "description": "", + "fields": null, + "inputFields": [ { - "name": "type", - "description": "The type of the field's values as recognized by Kibana", - "args": [], + "name": "activePage", + "description": "The activePage parameter defines the page of results you want to fetch", "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "searchable", - "description": "Whether the field's values can be efficiently searched for", - "args": [], + "name": "cursorStart", + "description": "The cursorStart parameter defines the start of the results to be displayed", "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "aggregatable", - "description": "Whether the field's values can be aggregated", - "args": [], + "name": "fakePossibleCount", + "description": "The fakePossibleCount parameter determines the total count in order to show 5 additional pages", "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "Description of the field", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "format", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "esTypes", - "description": "the elastic type as mapped in the index", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArrayNoNullable", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subType", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToIFieldSubTypeNonNullable", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToStringArrayNoNullable", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToIFieldSubTypeNonNullable", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "TimerangeInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "interval", - "description": "The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "to", - "description": "The end of the timerange", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "from", - "description": "The beginning of the timerange", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "activePage", - "description": "The activePage parameter defines the page of results you want to fetch", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "cursorStart", - "description": "The cursorStart parameter defines the start of the results to be displayed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "fakePossibleCount", - "description": "The fakePossibleCount parameter determines the total count in order to show 5 additional pages", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null + "defaultValue": null }, { "name": "querySize", @@ -6915,109 +6441,94 @@ }, { "kind": "OBJECT", - "name": "IpOverviewData", + "name": "KpiNetworkData", "description": "", "fields": [ { - "name": "client", + "name": "networkEvents", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "destination", + "name": "uniqueFlowId", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "host", + "name": "uniqueSourcePrivateIps", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "server", + "name": "uniqueSourcePrivateIpsHistogram", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiNetworkHistogramData", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "source", + "name": "uniqueDestinationPrivateIps", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Overview", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Overview", - "description": "", - "fields": [ - { - "name": "firstSeen", + "name": "uniqueDestinationPrivateIpsHistogram", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiNetworkHistogramData", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "lastSeen", + "name": "dnsQueries", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "autonomousSystem", + "name": "tlsHandshakes", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "AutonomousSystem", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "geo", + "name": "inspect", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null } - }, + "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -7029,11 +6540,11 @@ }, { "kind": "OBJECT", - "name": "AutonomousSystem", + "name": "KpiNetworkHistogramData", "description": "", "fields": [ { - "name": "number", + "name": "x", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -7041,10 +6552,10 @@ "deprecationReason": null }, { - "name": "organization", + "name": "y", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "AutonomousSystemOrganization", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -7056,211 +6567,134 @@ }, { "kind": "OBJECT", - "name": "AutonomousSystemOrganization", + "name": "KpiHostsData", "description": "", "fields": [ { - "name": "name", + "name": "hosts", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "UsersSortField", - "description": "", - "fields": null, - "inputFields": [ + }, { - "name": "field", + "name": "hostsHistogram", "description": "", + "args": [], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, - "ofType": { "kind": "ENUM", "name": "UsersFields", "ofType": null } + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "direction", + "name": "authSuccess", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "authSuccessHistogram", "description": "", + "args": [], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + } }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "UsersFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "name", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "count", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FlowTarget", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "client", "description": "", "isDeprecated": false, "deprecationReason": null }, + "isDeprecated": false, + "deprecationReason": null + }, { - "name": "destination", + "name": "authFailure", "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, - { "name": "server", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersData", - "description": "", - "fields": [ { - "name": "edges", + "name": "authFailureHistogram", "description": "", "args": [], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UsersEdges", "ofType": null } - } + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "totalCount", + "name": "uniqueSourceIps", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "pageInfo", + "name": "uniqueSourceIpsHistogram", "description": "", "args": [], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersEdges", - "description": "", - "fields": [ - { - "name": "node", + "name": "uniqueDestinationIps", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "UsersNode", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "cursor", + "name": "uniqueDestinationIpsHistogram", "description": "", "args": [], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UsersNode", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timestamp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null }, { - "name": "user", + "name": "inspect", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "UsersItem", "ofType": null }, + "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -7272,43 +6706,19 @@ }, { "kind": "OBJECT", - "name": "UsersItem", + "name": "KpiHostHistogramData", "description": "", "fields": [ { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "groupId", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "groupName", + "name": "x", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "count", + "name": "y", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -7323,11 +6733,11 @@ }, { "kind": "OBJECT", - "name": "KpiNetworkData", + "name": "KpiHostDetailsData", "description": "", "fields": [ { - "name": "networkEvents", + "name": "authSuccess", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -7335,15 +6745,23 @@ "deprecationReason": null }, { - "name": "uniqueFlowId", + "name": "authSuccessHistogram", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "uniqueSourcePrivateIps", + "name": "authFailure", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -7351,7 +6769,7 @@ "deprecationReason": null }, { - "name": "uniqueSourcePrivateIpsHistogram", + "name": "authFailureHistogram", "description": "", "args": [], "type": { @@ -7360,14 +6778,14 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiNetworkHistogramData", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "uniqueDestinationPrivateIps", + "name": "uniqueSourceIps", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -7375,7 +6793,7 @@ "deprecationReason": null }, { - "name": "uniqueDestinationPrivateIpsHistogram", + "name": "uniqueSourceIpsHistogram", "description": "", "args": [], "type": { @@ -7384,14 +6802,14 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiNetworkHistogramData", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "dnsQueries", + "name": "uniqueDestinationIps", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -7399,10 +6817,18 @@ "deprecationReason": null }, { - "name": "tlsHandshakes", + "name": "uniqueDestinationIpsHistogram", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, @@ -7421,1037 +6847,77 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "KpiNetworkHistogramData", + "kind": "ENUM", + "name": "HistogramType", "description": "", - "fields": [ + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "x", + "name": "authentications", "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "y", + "name": "anomalies", "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null - } + }, + { "name": "events", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "alerts", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "dns", "description": "", "isDeprecated": false, "deprecationReason": null } ], - "inputFields": null, - "interfaces": [], - "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "KpiHostsData", + "name": "MatrixHistogramOverTimeData", "description": "", "fields": [ { - "name": "hosts", + "name": "inspect", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "hostsHistogram", + "name": "matrixHistogramData", "description": "", "args": [], "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "MatrixOverTimeHistogramData", + "ofType": null + } + } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "authSuccess", + "name": "totalCount", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authSuccessHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailure", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailureHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiHostHistogramData", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "KpiHostDetailsData", - "description": "", - "fields": [ - { - "name": "authSuccess", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authSuccessHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailure", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "authFailureHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueSourceIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIps", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueDestinationIpsHistogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "KpiHostHistogramData", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "HistogramType", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "authentications", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "anomalies", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "events", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "alerts", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "dns", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MatrixHistogramOverTimeData", - "description": "", - "fields": [ - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "matrixHistogramData", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MatrixOverTimeHistogramData", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "MatrixOverTimeHistogramData", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "g", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FlowTargetSourceDest", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "destination", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "NetworkTopTablesSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "NetworkTopTablesFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "NetworkTopTablesFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "bytes_in", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes_out", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "flows", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "destination_ips", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopCountriesData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopCountriesEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopCountriesItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopCountriesItemSource", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopCountriesItemDestination", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "network", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNetworkTablesEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopCountriesItemSource", - "description": "", - "fields": [ - { - "name": "country", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GeoItem", - "description": "", - "fields": [ - { - "name": "geo", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flowTarget", - "description": "", - "args": [], - "type": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopCountriesItemDestination", - "description": "", - "fields": [ - { - "name": "country", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopNetworkTablesEcsField", - "description": "", - "fields": [ - { - "name": "bytes_in", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "bytes_out", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopNFlowData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowEdges", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopNFlowEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "NetworkTopNFlowItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "source", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNFlowItemSource", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNFlowItemDestination", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "network", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "TopNetworkTablesEcsField", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TopNFlowItemSource", - "description": "", - "fields": [ - { - "name": "autonomous_system", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AutonomousSystemItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domain", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "flows", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "destination_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AutonomousSystemItem", - "description": "", - "fields": [ - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "number", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null } @@ -8463,74 +6929,60 @@ }, { "kind": "OBJECT", - "name": "TopNFlowItemDestination", + "name": "MatrixOverTimeHistogramData", "description": "", "fields": [ { - "name": "autonomous_system", + "name": "x", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "AutonomousSystemItem", "ofType": null }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "domain", + "name": "y", "description": "", "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "ip", + "name": "g", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "location", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "FlowTargetSourceDest", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "flows", + "name": "destination", "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, - { - "name": "source_ips", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } + { "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null } ], - "inputFields": null, - "interfaces": [], - "enumValues": null, "possibleTypes": null }, { "kind": "INPUT_OBJECT", - "name": "NetworkDnsSortField", + "name": "NetworkTopTablesSortField", "description": "", "fields": null, "inputFields": [ @@ -8540,7 +6992,7 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "ENUM", "name": "NetworkDnsFields", "ofType": null } + "ofType": { "kind": "ENUM", "name": "NetworkTopTablesFields", "ofType": null } }, "defaultValue": null }, @@ -8561,38 +7013,33 @@ }, { "kind": "ENUM", - "name": "NetworkDnsFields", + "name": "NetworkTopTablesFields", "description": "", "fields": null, "inputFields": null, "interfaces": null, "enumValues": [ { - "name": "dnsName", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryCount", + "name": "bytes_in", "description": "", "isDeprecated": false, "deprecationReason": null }, { - "name": "uniqueDomains", + "name": "bytes_out", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "flows", "description": "", "isDeprecated": false, "deprecationReason": null }, { - "name": "dnsBytesIn", + "name": "destination_ips", "description": "", "isDeprecated": false, "deprecationReason": null }, { - "name": "dnsBytesOut", + "name": "source_ips", "description": "", "isDeprecated": false, "deprecationReason": null @@ -8602,7 +7049,7 @@ }, { "kind": "OBJECT", - "name": "NetworkDnsData", + "name": "NetworkTopCountriesData", "description": "", "fields": [ { @@ -8618,7 +7065,7 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkDnsEdges", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesEdges", "ofType": null } } } }, @@ -8656,26 +7103,6 @@ "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "histogram", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MatrixOverOrdinalHistogramData", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -8685,7 +7112,7 @@ }, { "kind": "OBJECT", - "name": "NetworkDnsEdges", + "name": "NetworkTopCountriesEdges", "description": "", "fields": [ { @@ -8695,7 +7122,7 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkDnsItem", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "NetworkTopCountriesItem", "ofType": null } }, "isDeprecated": false, "deprecationReason": null @@ -8720,7 +7147,7 @@ }, { "kind": "OBJECT", - "name": "NetworkDnsItem", + "name": "NetworkTopCountriesItem", "description": "", "fields": [ { @@ -8732,23 +7159,42 @@ "deprecationReason": null }, { - "name": "dnsBytesIn", + "name": "source", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "OBJECT", "name": "TopCountriesItemSource", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "dnsBytesOut", + "name": "destination", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "OBJECT", "name": "TopCountriesItemDestination", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "dnsName", + "name": "network", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "TopNetworkTablesEcsField", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "TopCountriesItemSource", + "description": "", + "fields": [ + { + "name": "country", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "String", "ofType": null }, @@ -8756,7 +7202,7 @@ "deprecationReason": null }, { - "name": "queryCount", + "name": "destination_ips", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -8764,7 +7210,23 @@ "deprecationReason": null }, { - "name": "uniqueDomains", + "name": "flows", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "location", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "source_ips", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -8779,42 +7241,22 @@ }, { "kind": "OBJECT", - "name": "MatrixOverOrdinalHistogramData", + "name": "GeoItem", "description": "", "fields": [ { - "name": "x", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", + "name": "geo", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, + "type": { "kind": "OBJECT", "name": "GeoEcsFields", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "g", + "name": "flowTarget", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, + "type": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -8826,50 +7268,46 @@ }, { "kind": "OBJECT", - "name": "NetworkDsOverTimeData", + "name": "TopCountriesItemDestination", "description": "", "fields": [ { - "name": "inspect", + "name": "country", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "matrixHistogramData", + "name": "destination_ips", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "MatrixOverTimeHistogramData", - "ofType": null - } - } - } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "totalCount", + "name": "flows", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "location", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "source_ips", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -8880,29 +7318,35 @@ "possibleTypes": null }, { - "kind": "INPUT_OBJECT", - "name": "NetworkHttpSortField", + "kind": "OBJECT", + "name": "TopNetworkTablesEcsField", "description": "", - "fields": null, - "inputFields": [ + "fields": [ + { + "name": "bytes_in", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, { - "name": "direction", + "name": "bytes_out", "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null + "args": [], + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null } ], - "interfaces": null, + "inputFields": null, + "interfaces": [], "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "NetworkHttpData", + "name": "NetworkTopNFlowData", "description": "", "fields": [ { @@ -8918,7 +7362,7 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkHttpEdges", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowEdges", "ofType": null } } } }, @@ -8965,7 +7409,7 @@ }, { "kind": "OBJECT", - "name": "NetworkHttpEdges", + "name": "NetworkTopNFlowEdges", "description": "", "fields": [ { @@ -8975,7 +7419,7 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "NetworkHttpItem", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "NetworkTopNFlowItem", "ofType": null } }, "isDeprecated": false, "deprecationReason": null @@ -9000,7 +7444,7 @@ }, { "kind": "OBJECT", - "name": "NetworkHttpItem", + "name": "NetworkTopNFlowItem", "description": "", "fields": [ { @@ -9012,63 +7456,66 @@ "deprecationReason": null }, { - "name": "domains", + "name": "source", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, + "type": { "kind": "OBJECT", "name": "TopNFlowItemSource", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "lastHost", + "name": "destination", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "type": { "kind": "OBJECT", "name": "TopNFlowItemDestination", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "lastSourceIp", + "name": "network", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "type": { "kind": "OBJECT", "name": "TopNetworkTablesEcsField", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "TopNFlowItemSource", + "description": "", + "fields": [ + { + "name": "autonomous_system", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "AutonomousSystemItem", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "methods", + "name": "domain", "description": "", "args": [], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "path", + "name": "ip", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "String", "ofType": null }, @@ -9076,7 +7523,15 @@ "deprecationReason": null }, { - "name": "requestCount", + "name": "location", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "flows", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -9084,22 +7539,10 @@ "deprecationReason": null }, { - "name": "statuses", + "name": "destination_ips", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -9111,43 +7554,78 @@ }, { "kind": "OBJECT", - "name": "OverviewNetworkData", + "name": "AutonomousSystemItem", "description": "", "fields": [ { - "name": "auditbeatSocket", + "name": "name", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "filebeatCisco", + "name": "number", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "TopNFlowItemDestination", + "description": "", + "fields": [ + { + "name": "autonomous_system", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "AutonomousSystemItem", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null }, { - "name": "filebeatNetflow", + "name": "domain", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "filebeatPanw", + "name": "ip", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "location", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "GeoItem", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "filebeatSuricata", + "name": "flows", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -9155,42 +7633,165 @@ "deprecationReason": null }, { - "name": "filebeatZeek", + "name": "source_ips", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NetworkDnsSortField", + "description": "", + "fields": null, + "inputFields": [ + { + "name": "field", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "ENUM", "name": "NetworkDnsFields", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "direction", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "NetworkDnsFields", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "dnsName", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "queryCount", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "uniqueDomains", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "dnsBytesIn", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "dnsBytesOut", + "description": "", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NetworkDnsData", + "description": "", + "fields": [ + { + "name": "edges", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "NetworkDnsEdges", "ofType": null } + } + } + }, + "isDeprecated": false, + "deprecationReason": null }, { - "name": "packetbeatDNS", + "name": "totalCount", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "packetbeatFlow", + "name": "pageInfo", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "packetbeatTLS", + "name": "inspect", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "inspect", + "name": "histogram", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "MatrixOverOrdinalHistogramData", + "ofType": null + } + } + }, "isDeprecated": false, "deprecationReason": null } @@ -9202,59 +7803,54 @@ }, { "kind": "OBJECT", - "name": "OverviewHostData", + "name": "NetworkDnsEdges", "description": "", "fields": [ { - "name": "auditbeatAuditd", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatFIM", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatLogin", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "auditbeatPackage", + "name": "node", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "NetworkDnsItem", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "auditbeatProcess", + "name": "cursor", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NetworkDnsItem", + "description": "", + "fields": [ { - "name": "auditbeatUser", + "name": "_id", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "endgameDns", + "name": "dnsBytesIn", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -9262,7 +7858,7 @@ "deprecationReason": null }, { - "name": "endgameFile", + "name": "dnsBytesOut", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -9270,15 +7866,15 @@ "deprecationReason": null }, { - "name": "endgameImageLoad", + "name": "dnsName", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "endgameNetwork", + "name": "queryCount", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, @@ -9286,58 +7882,112 @@ "deprecationReason": null }, { - "name": "endgameProcess", + "name": "uniqueDomains", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "MatrixOverOrdinalHistogramData", + "description": "", + "fields": [ { - "name": "endgameRegistry", + "name": "x", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "endgameSecurity", + "name": "y", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "filebeatSystemModule", + "name": "g", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NetworkDsOverTimeData", + "description": "", + "fields": [ { - "name": "winlogbeatSecurity", + "name": "inspect", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "winlogbeatMWSysmonOperational", + "name": "matrixHistogramData", "description": "", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "MatrixOverTimeHistogramData", + "ofType": null + } + } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "inspect", + "name": "totalCount", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, "isDeprecated": false, "deprecationReason": null } @@ -9347,9 +7997,30 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "NetworkHttpSortField", + "description": "", + "fields": null, + "inputFields": [ + { + "name": "direction", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", - "name": "UncommonProcessesData", + "name": "NetworkHttpData", "description": "", "fields": [ { @@ -9365,7 +8036,7 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "UncommonProcessesEdges", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "NetworkHttpEdges", "ofType": null } } } }, @@ -9412,7 +8083,7 @@ }, { "kind": "OBJECT", - "name": "UncommonProcessesEdges", + "name": "NetworkHttpEdges", "description": "", "fields": [ { @@ -9422,72 +8093,116 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "UncommonProcessItem", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "NetworkHttpItem", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "cursor", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NetworkHttpItem", + "description": "", + "fields": [ + { + "name": "_id", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "domains", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "cursor", + "name": "lastHost", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lastSourceIp", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "UncommonProcessItem", - "description": "", - "fields": [ + }, { - "name": "_id", + "name": "methods", "description": "", "args": [], "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "instances", + "name": "path", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "process", + "name": "requestCount", "description": "", "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ProcessEcsFields", "ofType": null } - }, + "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "hosts", + "name": "statuses", "description": "", "args": [], "type": { @@ -9499,20 +8214,12 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null } + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } } } }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "user", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "UserEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -9700,6 +8407,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "indexNames", + "description": "", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "notes", "description": "", @@ -11167,6 +9890,20 @@ }, "defaultValue": null }, + { + "name": "indexNames", + "description": "", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, + "defaultValue": null + }, { "name": "title", "description": "", @@ -12448,6 +11185,16 @@ ], "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "ToStringArrayNoNullable", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "EcsEdges", @@ -12782,6 +11529,163 @@ ], "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "ToIFieldSubTypeNonNullable", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IndexField", + "description": "A descriptor of a field in an index", + "fields": [ + { + "name": "category", + "description": "Where the field belong", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "example", + "description": "Example of field's value", + "args": [], + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "indexes", + "description": "whether the field's belong to an alias index", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "The name of the field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "The type of the field's values as recognized by Kibana", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "searchable", + "description": "Whether the field's values can be efficiently searched for", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "aggregatable", + "description": "Whether the field's values can be aggregated", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": "Description of the field", + "args": [], + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "format", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "esTypes", + "description": "the elastic type as mapped in the index", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArrayNoNullable", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "subType", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToIFieldSubTypeNonNullable", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "FlowTarget", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { "name": "client", "description": "", "isDeprecated": false, "deprecationReason": null }, + { + "name": "destination", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "server", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null } + ], + "possibleTypes": null + }, { "kind": "ENUM", "name": "FlowDirection", diff --git a/x-pack/plugins/security_solution/public/graphql/types.ts b/x-pack/plugins/security_solution/public/graphql/types.ts index 4d3837f434b053..1083583cb133c2 100644 --- a/x-pack/plugins/security_solution/public/graphql/types.ts +++ b/x-pack/plugins/security_solution/public/graphql/types.ts @@ -73,12 +73,6 @@ export interface HostsSortField { direction: Direction; } -export interface UsersSortField { - field: UsersFields; - - direction: Direction; -} - export interface NetworkTopTablesSortField { field: NetworkTopTablesFields; @@ -132,6 +126,8 @@ export interface TimelineInput { kqlQuery?: Maybe; + indexNames?: Maybe; + title?: Maybe; templateTimelineId?: Maybe; @@ -307,18 +303,6 @@ export enum HostPolicyResponseActionStatus { warning = 'warning', } -export enum UsersFields { - name = 'name', - count = 'count', -} - -export enum FlowTarget { - client = 'client', - destination = 'destination', - server = 'server', - source = 'source', -} - export enum HistogramType { authentications = 'authentications', anomalies = 'anomalies', @@ -408,15 +392,18 @@ export enum NetworkHttpFields { statuses = 'statuses', } +export enum FlowTarget { + client = 'client', + destination = 'destination', + server = 'server', + source = 'source', +} + export enum FlowDirection { uniDirectional = 'uniDirectional', biDirectional = 'biDirectional', } -export type ToStringArrayNoNullable = any; - -export type ToIFieldSubTypeNonNullable = any; - export type ToStringArray = string[]; export type Date = string; @@ -431,6 +418,10 @@ export type ToAny = any; export type EsValue = any; +export type ToStringArrayNoNullable = any; + +export type ToIFieldSubTypeNonNullable = any; + // ==================================================== // Scalars // ==================================================== @@ -533,10 +524,6 @@ export interface Source { HostFirstLastSeen: FirstLastSeenHost; - IpOverview?: Maybe; - - Users: UsersData; - KpiNetwork?: Maybe; KpiHosts: KpiHostsData; @@ -554,12 +541,6 @@ export interface Source { NetworkDnsHistogram: NetworkDsOverTimeData; NetworkHttp: NetworkHttpData; - - OverviewNetwork?: Maybe; - - OverviewHost?: Maybe; - /** 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?: Maybe; } @@ -591,33 +572,7 @@ export interface SourceStatus { /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ indicesExist: boolean; /** The list of fields defined in the index mappings */ - indexFields: IndexField[]; -} - -/** A descriptor of a field in an index */ -export interface IndexField { - /** Where the field belong */ - category: string; - /** Example of field's value */ - example?: Maybe; - /** whether the field's belong to an alias index */ - indexes: (Maybe)[]; - /** 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; - /** Description of the field */ - description?: Maybe; - - format?: Maybe; - /** the elastic type as mapped in the index */ - esTypes?: Maybe; - - subType?: Maybe; + indexFields: string[]; } export interface AuthenticationsData { @@ -1492,76 +1447,6 @@ export interface FirstLastSeenHost { lastSeen?: Maybe; } -export interface IpOverviewData { - client?: Maybe; - - destination?: Maybe; - - host: HostEcsFields; - - server?: Maybe; - - source?: Maybe; - - inspect?: Maybe; -} - -export interface Overview { - firstSeen?: Maybe; - - lastSeen?: Maybe; - - autonomousSystem: AutonomousSystem; - - geo: GeoEcsFields; -} - -export interface AutonomousSystem { - number?: Maybe; - - organization?: Maybe; -} - -export interface AutonomousSystemOrganization { - name?: Maybe; -} - -export interface UsersData { - edges: UsersEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UsersEdges { - node: UsersNode; - - cursor: CursorType; -} - -export interface UsersNode { - _id?: Maybe; - - timestamp?: Maybe; - - user?: Maybe; -} - -export interface UsersItem { - name?: Maybe; - - id?: Maybe; - - groupId?: Maybe; - - groupName?: Maybe; - - count?: Maybe; -} - export interface KpiNetworkData { networkEvents?: Maybe; @@ -1858,92 +1743,6 @@ export interface NetworkHttpItem { statuses: string[]; } -export interface OverviewNetworkData { - auditbeatSocket?: Maybe; - - filebeatCisco?: Maybe; - - filebeatNetflow?: Maybe; - - filebeatPanw?: Maybe; - - filebeatSuricata?: Maybe; - - filebeatZeek?: Maybe; - - packetbeatDNS?: Maybe; - - packetbeatFlow?: Maybe; - - packetbeatTLS?: Maybe; - - inspect?: Maybe; -} - -export interface OverviewHostData { - auditbeatAuditd?: Maybe; - - auditbeatFIM?: Maybe; - - auditbeatLogin?: Maybe; - - auditbeatPackage?: Maybe; - - auditbeatProcess?: Maybe; - - auditbeatUser?: Maybe; - - endgameDns?: Maybe; - - endgameFile?: Maybe; - - endgameImageLoad?: Maybe; - - endgameNetwork?: Maybe; - - endgameProcess?: Maybe; - - endgameRegistry?: Maybe; - - endgameSecurity?: Maybe; - - filebeatSystemModule?: Maybe; - - winlogbeatSecurity?: Maybe; - - winlogbeatMWSysmonOperational?: Maybe; - - inspect?: Maybe; -} - -export interface UncommonProcessesData { - edges: UncommonProcessesEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UncommonProcessesEdges { - node: UncommonProcessItem; - - cursor: CursorType; -} - -export interface UncommonProcessItem { - _id: string; - - instances: number; - - process: ProcessEcsFields; - - hosts: HostEcsFields[]; - - user?: Maybe; -} - export interface SayMyName { /** The id of the source */ appName: string; @@ -1976,6 +1775,8 @@ export interface TimelineResult { kqlQuery?: Maybe; + indexNames?: Maybe; + notes?: Maybe; noteIds?: Maybe; @@ -2248,6 +2049,32 @@ export interface HostFields { type?: Maybe; } +/** A descriptor of a field in an index */ +export interface IndexField { + /** Where the field belong */ + category: string; + /** Example of field's value */ + example?: Maybe; + /** whether the field's belong to an alias index */ + indexes: (Maybe)[]; + /** 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; + /** Description of the field */ + description?: Maybe; + + format?: Maybe; + /** the elastic type as mapped in the index */ + esTypes?: Maybe; + + subType?: Maybe; +} + // ==================================================== // Arguments // ==================================================== @@ -2370,34 +2197,6 @@ export interface HostFirstLastSeenSourceArgs { docValueFields: DocValueFieldsInput[]; } -export interface IpOverviewSourceArgs { - id?: Maybe; - - filterQuery?: Maybe; - - ip: string; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; -} -export interface UsersSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: UsersSortField; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} export interface KpiNetworkSourceArgs { id?: Maybe; @@ -2513,33 +2312,6 @@ export interface NetworkHttpSourceArgs { defaultIndex: string[]; } -export interface OverviewNetworkSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface OverviewHostSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface UncommonProcessesSourceArgs { - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} export interface IndicesExistSourceStatusArgs { defaultIndex: string[]; } @@ -2676,10 +2448,15 @@ export namespace GetMatrixHistogramQuery { }; } -export namespace SourceQuery { +export namespace GetAuthenticationsQuery { export type Variables = { - sourceId?: Maybe; + sourceId: string; + timerange: TimerangeInput; + pagination: PaginationInputPaginated; + filterQuery?: Maybe; defaultIndex: string[]; + inspect: boolean; + docValueFields: DocValueFieldsInput[]; }; export type Query = { @@ -2693,91 +2470,31 @@ export namespace SourceQuery { id: string; - status: Status; + Authentications: Authentications; }; - export type Status = { - __typename?: 'SourceStatus'; + export type Authentications = { + __typename?: 'AuthenticationsData'; - indicesExist: boolean; + totalCount: number; - indexFields: IndexFields[]; - }; + edges: Edges[]; - export type IndexFields = { - __typename?: 'IndexField'; + pageInfo: PageInfo; - category: string; + inspect: Maybe; + }; - description: Maybe; + export type Edges = { + __typename?: 'AuthenticationsEdges'; - example: Maybe; + node: Node; - indexes: (Maybe)[]; + cursor: Cursor; + }; - name: string; - - searchable: boolean; - - type: string; - - aggregatable: boolean; - - format: Maybe; - - esTypes: Maybe; - - subType: Maybe; - }; -} - -export namespace GetAuthenticationsQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - docValueFields: DocValueFieldsInput[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Authentications: Authentications; - }; - - export type Authentications = { - __typename?: 'AuthenticationsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'AuthenticationsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'AuthenticationItem'; + export type Node = { + __typename?: 'AuthenticationItem'; _id: string; @@ -3241,290 +2958,6 @@ export namespace GetKpiHostsQuery { }; } -export namespace GetUncommonProcessesQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - 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; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'UncommonProcessesEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'UncommonProcessItem'; - - _id: string; - - instances: number; - - process: Process; - - user: Maybe; - - hosts: Hosts[]; - }; - - export type Process = { - __typename?: 'ProcessEcsFields'; - - args: Maybe; - - name: Maybe; - }; - - export type User = { - __typename?: 'UserEcsFields'; - - id: Maybe; - - name: Maybe; - }; - - export type Hosts = { - __typename?: 'HostEcsFields'; - - name: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetIpOverviewQuery { - export type Variables = { - sourceId: string; - filterQuery?: Maybe; - ip: string; - defaultIndex: string[]; - inspect: boolean; - docValueFields: DocValueFieldsInput[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - IpOverview: Maybe; - }; - - export type IpOverview = { - __typename?: 'IpOverviewData'; - - source: Maybe<_Source>; - - destination: Maybe; - - host: Host; - - inspect: Maybe; - }; - - export type _Source = { - __typename?: 'Overview'; - - firstSeen: Maybe; - - lastSeen: Maybe; - - autonomousSystem: AutonomousSystem; - - geo: Geo; - }; - - export type AutonomousSystem = { - __typename?: 'AutonomousSystem'; - - number: Maybe; - - organization: Maybe; - }; - - export type Organization = { - __typename?: 'AutonomousSystemOrganization'; - - name: Maybe; - }; - - export type Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - city_name: Maybe; - - country_iso_code: Maybe; - - country_name: Maybe; - - location: Maybe; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type Location = { - __typename?: 'Location'; - - lat: Maybe; - - lon: Maybe; - }; - - export type Destination = { - __typename?: 'Overview'; - - firstSeen: Maybe; - - lastSeen: Maybe; - - autonomousSystem: _AutonomousSystem; - - geo: _Geo; - }; - - export type _AutonomousSystem = { - __typename?: 'AutonomousSystem'; - - number: Maybe; - - organization: Maybe<_Organization>; - }; - - export type _Organization = { - __typename?: 'AutonomousSystemOrganization'; - - name: Maybe; - }; - - export type _Geo = { - __typename?: 'GeoEcsFields'; - - continent_name: Maybe; - - city_name: Maybe; - - country_iso_code: Maybe; - - country_name: Maybe; - - location: Maybe<_Location>; - - region_iso_code: Maybe; - - region_name: Maybe; - }; - - export type _Location = { - __typename?: 'Location'; - - lat: Maybe; - - lon: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - architecture: Maybe; - - id: Maybe; - - ip: Maybe; - - mac: Maybe; - - name: Maybe; - - os: Maybe; - - type: Maybe; - }; - - export type Os = { - __typename?: 'OsEcsFields'; - - family: Maybe; - - name: Maybe; - - platform: Maybe; - - version: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - export namespace GetKpiNetworkQuery { export type Variables = { sourceId: string; @@ -4060,224 +3493,6 @@ export namespace GetNetworkTopNFlowQuery { }; } -export namespace GetUsersQuery { - export type Variables = { - sourceId: string; - filterQuery?: Maybe; - flowTarget: FlowTarget; - ip: string; - pagination: PaginationInputPaginated; - sort: UsersSortField; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Users: Users; - }; - - export type Users = { - __typename?: 'UsersData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'UsersEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'UsersNode'; - - user: Maybe; - }; - - export type User = { - __typename?: 'UsersItem'; - - name: Maybe; - - id: Maybe; - - groupId: Maybe; - - groupName: Maybe; - - count: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetOverviewHostQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - OverviewHost: Maybe; - }; - - export type OverviewHost = { - __typename?: 'OverviewHostData'; - - auditbeatAuditd: Maybe; - - auditbeatFIM: Maybe; - - auditbeatLogin: Maybe; - - auditbeatPackage: Maybe; - - auditbeatProcess: Maybe; - - auditbeatUser: Maybe; - - endgameDns: Maybe; - - endgameFile: Maybe; - - endgameImageLoad: Maybe; - - endgameNetwork: Maybe; - - endgameProcess: Maybe; - - endgameRegistry: Maybe; - - endgameSecurity: Maybe; - - filebeatSystemModule: Maybe; - - winlogbeatSecurity: Maybe; - - winlogbeatMWSysmonOperational: Maybe; - - inspect: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - -export namespace GetOverviewNetworkQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - OverviewNetwork: Maybe; - }; - - export type OverviewNetwork = { - __typename?: 'OverviewNetworkData'; - - auditbeatSocket: Maybe; - - filebeatCisco: Maybe; - - filebeatNetflow: Maybe; - - filebeatPanw: Maybe; - - filebeatSuricata: Maybe; - - filebeatZeek: Maybe; - - packetbeatDNS: Maybe; - - packetbeatFlow: Maybe; - - packetbeatTLS: Maybe; - - inspect: Maybe; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - export namespace GetAllTimeline { export type Variables = { pageInfo: PageInfoTimeline; @@ -5413,6 +4628,8 @@ export namespace GetOneTimeline { kqlQuery: Maybe; + indexNames: Maybe; + notes: Maybe; noteIds: Maybe; @@ -5745,6 +4962,8 @@ export namespace PersistTimelineMutation { kqlQuery: Maybe; + indexNames: Maybe; + title: Maybe; dateRange: Maybe; diff --git a/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.test.tsx b/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.test.tsx index 606b43c6508fb9..4f64cca45d1625 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.test.tsx @@ -40,7 +40,12 @@ describe('FirstLastSeen Component', () => { useFirstLastSeenHostMock.mockReturnValue([true, MOCKED_RESPONSE]); const { container } = render( - + ); expect(container.innerHTML).toBe( @@ -52,7 +57,12 @@ describe('FirstLastSeen Component', () => { useFirstLastSeenHostMock.mockReturnValue([false, MOCKED_RESPONSE]); const { container } = render( - + ); @@ -69,7 +79,12 @@ describe('FirstLastSeen Component', () => { useFirstLastSeenHostMock.mockReturnValue([false, MOCKED_RESPONSE]); const { container } = render( - + ); await act(() => @@ -91,7 +106,12 @@ describe('FirstLastSeen Component', () => { ]); const { container } = render( - + ); @@ -114,7 +134,12 @@ describe('FirstLastSeen Component', () => { ]); const { container } = render( - + ); @@ -137,7 +162,12 @@ describe('FirstLastSeen Component', () => { ]); const { container } = render( - + ); await act(() => @@ -157,7 +187,12 @@ describe('FirstLastSeen Component', () => { ]); const { container } = render( - + ); await act(() => diff --git a/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.tsx index a1b72fb39069ca..ee415560cf9dec 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/first_last_seen_host/index.tsx @@ -10,6 +10,7 @@ import React, { useMemo } from 'react'; import { useFirstLastSeenHost } from '../../containers/hosts/first_last_seen'; import { getEmptyTagValue } from '../../../common/components/empty_value'; import { FormattedRelativePreferenceDate } from '../../../common/components/formatted_date'; +import { DocValueFields } from '../../../../common/search_strategy'; export enum FirstLastSeenHostType { FIRST_SEEN = 'first-seen', @@ -17,47 +18,53 @@ export enum FirstLastSeenHostType { } interface FirstLastSeenHostProps { + docValueFields: DocValueFields[]; hostName: string; + indexNames: string[]; type: FirstLastSeenHostType; } -export const FirstLastSeenHost = React.memo(({ hostName, type }) => { - const [loading, { firstSeen, lastSeen, errorMessage }] = useFirstLastSeenHost({ - hostName, - }); - const valueSeen = useMemo( - () => (type === FirstLastSeenHostType.FIRST_SEEN ? firstSeen : lastSeen), - [firstSeen, lastSeen, type] - ); +export const FirstLastSeenHost = React.memo( + ({ docValueFields, hostName, type, indexNames }) => { + const [loading, { firstSeen, lastSeen, errorMessage }] = useFirstLastSeenHost({ + docValueFields, + hostName, + indexNames, + }); + const valueSeen = useMemo( + () => (type === FirstLastSeenHostType.FIRST_SEEN ? firstSeen : lastSeen), + [firstSeen, lastSeen, type] + ); + + if (errorMessage != null) { + return ( + + + + ); + } - if (errorMessage != null) { return ( - - - + <> + {loading && } + {!loading && valueSeen != null && new Date(valueSeen).toString() === 'Invalid Date' + ? valueSeen + : !loading && + valueSeen != null && ( + + + + )} + {!loading && valueSeen == null && getEmptyTagValue()} + ); } - - return ( - <> - {loading && } - {!loading && valueSeen != null && new Date(valueSeen).toString() === 'Invalid Date' - ? valueSeen - : !loading && - valueSeen != null && ( - - - - )} - {!loading && valueSeen == null && getEmptyTagValue()} - - ); -}); +); FirstLastSeenHost.displayName = 'FirstLastSeenHost'; diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap index 3143e680913b2c..1d70f4f72ac8bd 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap @@ -68,97 +68,6 @@ exports[`Hosts Table rendering it renders the default Hosts table 1`] = ` } fakeTotalCount={50} id="hostsQuery" - indexPattern={ - Object { - "fields": Array [ - Object { - "aggregatable": true, - "name": "@timestamp", - "searchable": true, - "type": "date", - }, - Object { - "aggregatable": true, - "name": "@version", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.ephemeral_id", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.hostname", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.id", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test1", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test2", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test3", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test4", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test5", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test6", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test7", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "agent.test8", - "searchable": true, - "type": "string", - }, - Object { - "aggregatable": true, - "name": "host.name", - "searchable": true, - "type": "string", - }, - ], - "title": "filebeat-*,auditbeat-*,packetbeat-*", - } - } isInspect={false} loadPage={[MockFunction]} loading={false} diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.test.tsx b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.test.tsx index c4a391687843c1..29e4dc48ae3c75 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.test.tsx @@ -12,7 +12,6 @@ import { MockedProvider } from 'react-apollo/test-utils'; import '../../../common/mock/match_media'; import { apolloClientObservable, - mockIndexPattern, mockGlobalState, TestProviders, SUB_PLUGINS_REDUCER, @@ -69,7 +68,6 @@ describe('Hosts Table', () => { data={mockData.Hosts.edges} id="hostsQuery" isInspect={false} - indexPattern={mockIndexPattern} fakeTotalCount={getOr(50, 'fakeTotalCount', mockData.Hosts.pageInfo)} loading={false} loadPage={loadPage} @@ -92,7 +90,6 @@ describe('Hosts Table', () => { void; @@ -77,7 +75,6 @@ const HostsTableComponent = React.memo( direction, fakeTotalCount, id, - indexPattern, isInspect, limit, loading, diff --git a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/authentications/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/authentications/index.tsx index 09496168274701..84003e5dea5e98 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/authentications/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/authentications/index.tsx @@ -42,6 +42,7 @@ export const fieldsMapping: Readonly = [ const HostsKpiAuthenticationsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -50,6 +51,7 @@ const HostsKpiAuthenticationsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useHostsKpiAuthentications({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/hosts/index.tsx index b1c4d6331e4504..908ff717e2711b 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/hosts/index.tsx @@ -31,6 +31,7 @@ export const fieldsMapping: Readonly = [ const HostsKpiHostsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -39,6 +40,7 @@ const HostsKpiHostsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useHostsKpiHosts({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx index fff4c64900a8bb..6174e174db5a69 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx @@ -13,12 +13,13 @@ import { HostsKpiUniqueIps } from './unique_ips'; import { HostsKpiProps } from './types'; export const HostsKpiComponent = React.memo( - ({ filterQuery, from, to, setQuery, skip, narrowDateRange }) => ( + ({ filterQuery, from, indexNames, to, setQuery, skip, narrowDateRange }) => ( ( ( ( HostsKpiComponent.displayName = 'HostsKpiComponent'; export const HostsDetailsKpiComponent = React.memo( - ({ filterQuery, from, to, setQuery, skip, narrowDateRange }) => ( + ({ filterQuery, from, indexNames, to, setQuery, skip, narrowDateRange }) => ( ( = [ const HostsKpiUniqueIpsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -50,6 +51,7 @@ const HostsKpiUniqueIpsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useHostsKpiUniqueIps({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx index 5ace3439a2de69..41f443f14cafe8 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx @@ -30,18 +30,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = shallow( @@ -54,18 +50,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -79,18 +71,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -105,18 +93,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -131,18 +115,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -157,18 +137,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -183,18 +159,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -208,18 +180,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( @@ -233,18 +201,14 @@ describe('Uncommon Process Table Component', () => { const wrapper = mount( diff --git a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx index 31d7fb10edb1c3..c7025bb489ae4e 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx @@ -9,7 +9,10 @@ import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; -import { UncommonProcessesEdges, UncommonProcessItem } from '../../../graphql/types'; +import { + HostsUncommonProcessesEdges, + HostsUncommonProcessItem, +} from '../../../../common/search_strategy'; import { State } from '../../../common/store'; import { hostsActions, hostsModel, hostsSelectors } from '../../store'; import { defaultToEmptyTag, getEmptyValue } from '../../../common/components/empty_value'; @@ -21,7 +24,7 @@ import { getRowItemDraggables } from '../../../common/components/tables/helpers' import { HostsType } from '../../store/model'; const tableType = hostsModel.HostsTableType.uncommonProcesses; interface OwnProps { - data: UncommonProcessesEdges[]; + data: HostsUncommonProcessesEdges[]; fakeTotalCount: number; id: string; isInspect: boolean; @@ -33,12 +36,12 @@ interface OwnProps { } export type UncommonProcessTableColumns = [ - Columns, - Columns, - Columns, - Columns, - Columns, - Columns + Columns, + Columns, + Columns, + Columns, + Columns, + Columns ]; type UncommonProcessTableProps = OwnProps & PropsFromRedux; @@ -212,7 +215,7 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ }, ]; -export const getHostNames = (node: UncommonProcessItem): string[] => { +export const getHostNames = (node: HostsUncommonProcessItem): string[] => { if (node.hosts != null) { return node.hosts .filter((host) => host.name != null && host.name[0] != null) diff --git a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/mock.ts b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/mock.ts index 52b835278634b0..56853c1bfaae1d 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/mock.ts +++ b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/mock.ts @@ -4,116 +4,115 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UncommonProcessesData } from '../../../graphql/types'; +import { HostsUncommonProcessesStrategyResponse } from '../../../../common/search_strategy'; -export const mockData: { UncommonProcess: UncommonProcessesData } = { - UncommonProcess: { - totalCount: 5, - edges: [ - { - node: { - _id: 'cPsuhGcB0WOhS6qyTKC0', - process: { - title: ['Hello World'], - name: ['elrond.elstc.co'], - }, - hosts: [], - instances: 93, - user: { - id: ['0'], - name: ['root'], - }, +export const mockData: HostsUncommonProcessesStrategyResponse = { + totalCount: 5, + edges: [ + { + node: { + _id: 'cPsuhGcB0WOhS6qyTKC0', + process: { + title: ['Hello World'], + name: ['elrond.elstc.co'], }, - cursor: { - value: '98966fa2013c396155c460d35c0902be', + hosts: [], + instances: 93, + user: { + id: ['0'], + name: ['root'], }, }, - { - node: { - _id: 'cPsuhGcB0WOhS6qyTKC0', - process: { - title: ['Hello World'], - name: ['elrond.elstc.co'], - }, - hosts: [{ id: ['host-id-1'], name: ['hello-world'] }], - instances: 93, - user: { - id: ['0'], - name: ['root'], - }, + cursor: { + value: '98966fa2013c396155c460d35c0902be', + }, + }, + { + node: { + _id: 'cPsuhGcB0WOhS6qyTKC0', + process: { + title: ['Hello World'], + name: ['elrond.elstc.co'], }, - cursor: { - value: '98966fa2013c396155c460d35c0902be', + hosts: [{ id: ['host-id-1'], name: ['hello-world'] }], + instances: 93, + user: { + id: ['0'], + name: ['root'], }, }, - { - node: { - _id: 'KwQDiWcB0WOhS6qyXmrW', - process: { - title: ['Hello World'], - name: ['siem-kibana'], - }, - hosts: [ - { id: ['host-id-1'], name: ['hello-world'] }, - { id: ['host-id-2'], name: ['hello-world-2'] }, - ], - instances: 97, - user: { - id: ['1'], - name: ['Evan'], - }, + cursor: { + value: '98966fa2013c396155c460d35c0902be', + }, + }, + { + node: { + _id: 'KwQDiWcB0WOhS6qyXmrW', + process: { + title: ['Hello World'], + name: ['siem-kibana'], }, - cursor: { - value: 'aa7ca589f1b8220002f2fc61c64cfbf1', + hosts: [ + { id: ['host-id-1'], name: ['hello-world'] }, + { id: ['host-id-2'], name: ['hello-world-2'] }, + ], + instances: 97, + user: { + id: ['1'], + name: ['Evan'], }, }, - { - node: { - _id: 'KwQDiWcB0WOhS6qyXmrW', - process: { - title: ['Hello World'], - name: ['siem-kibana'], - }, - hosts: [{ ip: ['127.0.0.1'] }], - instances: 97, - user: { - id: ['1'], - name: ['Evan'], - }, + cursor: { + value: 'aa7ca589f1b8220002f2fc61c64cfbf1', + }, + }, + { + node: { + _id: 'KwQDiWcB0WOhS6qyXmrW', + process: { + title: ['Hello World'], + name: ['siem-kibana'], }, - cursor: { - value: 'aa7ca589f1b8220002f2fc61c64cfbf1', + hosts: [{ ip: ['127.0.0.1'] }], + instances: 97, + user: { + id: ['1'], + name: ['Evan'], }, }, - { - node: { - _id: 'KwQDiWcB0WOhS6qyXmrW', - process: { - title: ['Hello World'], - name: ['siem-kibana'], - }, - hosts: [ - { ip: ['127.0.0.1'] }, - { id: ['host-id-1'], name: ['hello-world'] }, - { ip: ['127.0.0.1'] }, - { id: ['host-id-2'], name: ['hello-world-2'] }, - { ip: ['127.0.0.1'] }, - ], - instances: 97, - user: { - id: ['1'], - name: ['Evan'], - }, + cursor: { + value: 'aa7ca589f1b8220002f2fc61c64cfbf1', + }, + }, + { + node: { + _id: 'KwQDiWcB0WOhS6qyXmrW', + process: { + title: ['Hello World'], + name: ['siem-kibana'], }, - cursor: { - value: 'aa7ca589f1b8220002f2fc61c64cfbf1', + hosts: [ + { ip: ['127.0.0.1'] }, + { id: ['host-id-1'], name: ['hello-world'] }, + { ip: ['127.0.0.1'] }, + { id: ['host-id-2'], name: ['hello-world-2'] }, + { ip: ['127.0.0.1'] }, + ], + instances: 97, + user: { + id: ['1'], + name: ['Evan'], }, }, - ], - pageInfo: { - activePage: 1, - fakeTotalCount: 50, - showMorePagesIndicator: true, + cursor: { + value: 'aa7ca589f1b8220002f2fc61c64cfbf1', + }, }, + ], + pageInfo: { + activePage: 1, + fakeTotalCount: 50, + showMorePagesIndicator: true, }, + rawResponse: {} as HostsUncommonProcessesStrategyResponse['rawResponse'], }; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx index 7bf4f7a833fb82..b1563e85c93ddf 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx @@ -15,7 +15,6 @@ import { isErrorResponse, } from '../../../../../../../src/plugins/data/common'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { HostsQueries } from '../../../../common/search_strategy/security_solution'; import { HostAuthenticationsRequestOptions, @@ -56,6 +55,7 @@ interface UseAuthentications { docValueFields?: DocValueFields[]; filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; startDate: string; type: hostsModel.HostsType; skip: boolean; @@ -65,6 +65,7 @@ export const useAuthentications = ({ docValueFields, filterQuery, endDate, + indexNames, startDate, type, skip, @@ -74,15 +75,14 @@ export const useAuthentications = ({ (state: State) => getAuthenticationsSelector(state, type), shallowEqual ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [authenticationsRequest, setAuthenticationsRequest] = useState< HostAuthenticationsRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], factoryQueryType: HostsQueries.authentications, filterQuery: createFilter(filterQuery), @@ -186,7 +186,7 @@ export const useAuthentications = ({ setAuthenticationsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), @@ -201,7 +201,7 @@ export const useAuthentications = ({ } return prevRequest; }); - }, [activePage, defaultIndex, docValueFields, endDate, filterQuery, limit, skip, startDate]); + }, [activePage, docValueFields, endDate, filterQuery, indexNames, limit, skip, startDate]); useEffect(() => { authenticationsSearch(authenticationsRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx index f68c340a477236..5b69e20398a35a 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx @@ -10,7 +10,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { useKibana } from '../../../../common/lib/kibana'; import { @@ -41,9 +40,10 @@ export interface HostDetailsArgs { } interface UseHostDetails { - id?: string; - hostName: string; endDate: string; + hostName: string; + id?: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -51,17 +51,17 @@ interface UseHostDetails { export const useHostDetails = ({ endDate, hostName, + indexNames, + id = ID, skip = false, startDate, - id = ID, }: UseHostDetails): [boolean, HostDetailsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [hostDetailsRequest, setHostDetailsRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, hostName, factoryQueryType: HostsQueries.details, timerange: { @@ -142,7 +142,7 @@ export const useHostDetails = ({ setHostDetailsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, hostName, timerange: { interval: '12h', @@ -155,7 +155,7 @@ export const useHostDetails = ({ } return prevRequest; }); - }, [defaultIndex, endDate, hostName, startDate, skip]); + }, [endDate, hostName, indexNames, startDate, skip]); useEffect(() => { hostDetailsSearch(hostDetailsRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx index 12a82c7980b61b..0236270d186188 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx @@ -10,11 +10,9 @@ import { Query } from 'react-apollo'; import { connect } from 'react-redux'; import { compose } from 'redux'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel, inputsSelectors, State } from '../../../../common/store'; import { getDefaultFetchPolicy } from '../../../../common/containers/helpers'; import { QueryTemplate, QueryTemplateProps } from '../../../../common/containers/query_template'; -import { withKibana, WithKibanaProps } from '../../../../common/lib/kibana'; import { HostOverviewQuery } from './host_overview.gql_query'; import { GetHostOverviewQuery, HostItem } from '../../../../graphql/types'; @@ -42,7 +40,7 @@ export interface OwnProps extends QueryTemplateProps { endDate: string; } -type HostsOverViewProps = OwnProps & HostOverviewReduxProps & WithKibanaProps; +type HostsOverViewProps = OwnProps & HostOverviewReduxProps; class HostOverviewByNameComponentQuery extends QueryTemplate< HostsOverViewProps, @@ -52,10 +50,10 @@ class HostOverviewByNameComponentQuery extends QueryTemplate< public render() { const { id = ID, + indexNames, isInspected, children, hostName, - kibana, skip, sourceId, startDate, @@ -75,7 +73,7 @@ class HostOverviewByNameComponentQuery extends QueryTemplate< from: startDate, to: endDate, }, - defaultIndex: kibana.services.uiSettings.get(DEFAULT_INDEX_KEY), + defaultIndex: indexNames, inspect: isInspected, }} > @@ -108,6 +106,5 @@ const makeMapStateToProps = () => { }; export const HostOverviewByNameQuery = compose>( - connect(makeMapStateToProps), - withKibana + connect(makeMapStateToProps) )(HostOverviewByNameComponentQuery); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx index a6376642dfa29e..cc944a59571f19 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx @@ -7,17 +7,15 @@ import deepEqual from 'fast-deep-equal'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; - import { useKibana } from '../../../../common/lib/kibana'; import { HostsQueries, HostFirstLastSeenRequestOptions, HostFirstLastSeenStrategyResponse, } from '../../../../../common/search_strategy/security_solution'; -import { useWithSource } from '../../../../common/containers/source'; import * as i18n from './translations'; +import { DocValueFields } from '../../../../../common/search_strategy'; import { AbortError, isCompleteResponse, @@ -33,21 +31,23 @@ export interface FirstLastSeenHostArgs { lastSeen?: string | null; } interface UseHostFirstLastSeen { + docValueFields: DocValueFields[]; hostName: string; + indexNames: string[]; } export const useFirstLastSeenHost = ({ + docValueFields, hostName, + indexNames, }: UseHostFirstLastSeen): [boolean, FirstLastSeenHostArgs] => { - const { docValueFields } = useWithSource('default'); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [firstLastSeenHostRequest, setFirstLastSeenHostRequest] = useState< HostFirstLastSeenRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], factoryQueryType: HostsQueries.firstLastSeen, hostName, @@ -124,7 +124,7 @@ export const useFirstLastSeenHost = ({ setFirstLastSeenHostRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], hostName, }; @@ -133,7 +133,7 @@ export const useFirstLastSeenHost = ({ } return prevRequest; }); - }, [defaultIndex, docValueFields, hostName]); + }, [indexNames, docValueFields, hostName]); useEffect(() => { firstLastSeenHostSearch(firstLastSeenHostRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx index 2eb926a9733c3d..6ca0272e58d7d6 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx @@ -9,7 +9,6 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel, State } from '../../../common/store'; import { createFilter } from '../../../common/containers/helpers'; import { useKibana } from '../../../common/lib/kibana'; @@ -54,6 +53,7 @@ interface UseAllHost { docValueFields?: DocValueFields[]; filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; type: hostsModel.HostsType; @@ -63,6 +63,7 @@ export const useAllHost = ({ docValueFields, filterQuery, endDate, + indexNames, skip = false, startDate, type, @@ -71,13 +72,12 @@ export const useAllHost = ({ const { activePage, direction, limit, sortField } = useSelector((state: State) => getHostsSelector(state, type) ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [hostsRequest, setHostRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], factoryQueryType: HostsQueries.hosts, filterQuery: createFilter(filterQuery), @@ -181,7 +181,7 @@ export const useAllHost = ({ setHostRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), @@ -202,11 +202,11 @@ export const useAllHost = ({ }); }, [ activePage, - defaultIndex, direction, docValueFields, endDate, filterQuery, + indexNames, limit, skip, startDate, diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_host_details/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_host_details/index.tsx index 1551e7d7067146..26e4eaf9ea82e0 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_host_details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_host_details/index.tsx @@ -9,10 +9,8 @@ import React from 'react'; import { Query } from 'react-apollo'; import { connect, ConnectedProps } from 'react-redux'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { KpiHostDetailsData, GetKpiHostDetailsQuery } from '../../../graphql/types'; import { inputsModel, inputsSelectors, State } from '../../../common/store'; -import { useUiSetting } from '../../../common/lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../../../common/containers/helpers'; import { QueryTemplateProps } from '../../../common/containers/query_template'; @@ -33,7 +31,17 @@ export interface QueryKpiHostDetailsProps extends QueryTemplateProps { } const KpiHostDetailsComponentQuery = React.memo( - ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( + ({ + id = ID, + children, + endDate, + filterQuery, + indexNames, + isInspected, + skip, + sourceId, + startDate, + }) => ( query={kpiHostDetailsQuery} fetchPolicy={getDefaultFetchPolicy()} @@ -47,7 +55,7 @@ const KpiHostDetailsComponentQuery = React.memo(DEFAULT_INDEX_KEY), + defaultIndex: indexNames ?? [], inspect: isInspected, }} > diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx index 0d90b73e0a5843..404231be1e6cdb 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -37,6 +36,7 @@ export interface HostsKpiAuthenticationsArgs interface UseHostsKpiAuthentications { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -44,18 +44,18 @@ interface UseHostsKpiAuthentications { export const useHostsKpiAuthentications = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseHostsKpiAuthentications): [boolean, HostsKpiAuthenticationsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [hostsKpiAuthenticationsRequest, setHostsKpiAuthenticationsRequest] = useState< HostsKpiAuthenticationsRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: HostsKpiQueries.kpiAuthentications, filterQuery: createFilter(filterQuery), id: ID, @@ -147,7 +147,7 @@ export const useHostsKpiAuthentications = ({ setHostsKpiAuthenticationsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -160,7 +160,7 @@ export const useHostsKpiAuthentications = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { hostsKpiAuthenticationsSearch(hostsKpiAuthenticationsRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx index 190ce1aa7eae1c..bb918a9214f409 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -36,6 +35,7 @@ export interface HostsKpiHostsArgs extends Omit { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [hostsKpiHostsRequest, setHostsKpiHostsRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: HostsKpiQueries.kpiHosts, filterQuery: createFilter(filterQuery), id: ID, @@ -135,7 +135,7 @@ export const useHostsKpiHosts = ({ setHostsKpiHostsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -148,7 +148,7 @@ export const useHostsKpiHosts = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { hostsKpiHostsSearch(hostsKpiHostsRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx index ac5cc12807f007..b8e93eef8dc914 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -37,6 +36,7 @@ export interface HostsKpiUniqueIpsArgs interface UseHostsKpiUniqueIps { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -44,18 +44,18 @@ interface UseHostsKpiUniqueIps { export const useHostsKpiUniqueIps = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseHostsKpiUniqueIps): [boolean, HostsKpiUniqueIpsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [hostsKpiUniqueIpsRequest, setHostsKpiUniqueIpsRequest] = useState< HostsKpiUniqueIpsRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: HostsKpiQueries.kpiUniqueIps, filterQuery: createFilter(filterQuery), id: ID, @@ -144,7 +144,7 @@ export const useHostsKpiUniqueIps = ({ setHostsKpiUniqueIpsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -157,7 +157,7 @@ export const useHostsKpiUniqueIps = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { hostsKpiUniqueIpsSearch(hostsKpiUniqueIpsRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.gql_query.ts b/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.gql_query.ts deleted file mode 100644 index d984de020faa1e..00000000000000 --- a/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.gql_query.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const uncommonProcessesQuery = gql` - query GetUncommonProcessesQuery( - $sourceId: ID! - $timerange: TimerangeInput! - $pagination: PaginationInputPaginated! - $filterQuery: String - $defaultIndex: [String!]! - $inspect: Boolean! - ) { - source(id: $sourceId) { - id - UncommonProcesses( - timerange: $timerange - pagination: $pagination - filterQuery: $filterQuery - defaultIndex: $defaultIndex - ) { - totalCount - edges { - node { - _id - instances - process { - args - name - } - user { - id - name - } - hosts { - name - } - } - cursor { - value - } - } - pageInfo { - activePage - fakeTotalCount - showMorePagesIndicator - } - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx index ae4ea83f887253..4036837024025a 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx @@ -15,20 +15,20 @@ import { isErrorResponse, } from '../../../../../../../src/plugins/data/common'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; -import { PageInfoPaginated, UncommonProcessesEdges } from '../../../graphql/types'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import { createFilter } from '../../../common/containers/helpers'; - import { hostsModel, hostsSelectors } from '../../store'; import { - HostUncommonProcessesRequestOptions, - HostUncommonProcessesStrategyResponse, -} from '../../../../common/search_strategy/security_solution/hosts/uncommon_processes'; -import { HostsQueries } from '../../../../common/search_strategy/security_solution/hosts'; -import { DocValueFields, SortField } from '../../../../common/search_strategy'; + DocValueFields, + SortField, + PageInfoPaginated, + HostsUncommonProcessesEdges, + HostsQueries, + HostsUncommonProcessesRequestOptions, + HostsUncommonProcessesStrategyResponse, +} from '../../../../common/search_strategy'; import * as i18n from './translations'; import { ESTermQuery } from '../../../../common/typed_json'; @@ -45,13 +45,14 @@ export interface UncommonProcessesArgs { pageInfo: PageInfoPaginated; refetch: inputsModel.Refetch; totalCount: number; - uncommonProcesses: UncommonProcessesEdges[]; + uncommonProcesses: HostsUncommonProcessesEdges[]; } interface UseUncommonProcesses { docValueFields?: DocValueFields[]; filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; type: hostsModel.HostsType; @@ -61,6 +62,7 @@ export const useUncommonProcesses = ({ docValueFields, filterQuery, endDate, + indexNames, skip = false, startDate, type, @@ -69,15 +71,14 @@ export const useUncommonProcesses = ({ const { activePage, limit } = useSelector((state: State) => getUncommonProcessesSelector(state, type) ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [uncommonProcessesRequest, setUncommonProcessesRequest] = useState< - HostUncommonProcessesRequestOptions + HostsUncommonProcessesRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], factoryQueryType: HostsQueries.uncommonProcesses, filterQuery: createFilter(filterQuery), @@ -123,14 +124,14 @@ export const useUncommonProcesses = ({ ); const uncommonProcessesSearch = useCallback( - (request: HostUncommonProcessesRequestOptions) => { + (request: HostsUncommonProcessesRequestOptions) => { let didCancel = false; const asyncSearch = async () => { abortCtrl.current = new AbortController(); setLoading(true); const searchSubscription$ = data.search - .search( + .search( request, { strategy: 'securitySolutionSearchStrategy', @@ -185,7 +186,7 @@ export const useUncommonProcesses = ({ setUncommonProcessesRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), @@ -201,7 +202,7 @@ export const useUncommonProcesses = ({ } return prevRequest; }); - }, [activePage, defaultIndex, docValueFields, endDate, filterQuery, limit, skip, startDate]); + }, [activePage, indexNames, docValueFields, endDate, filterQuery, limit, skip, startDate]); useEffect(() => { uncommonProcessesSearch(uncommonProcessesRequest); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx index 11a268c7b64ad4..708c8b2b40b35e 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx @@ -84,6 +84,7 @@ describe('body', () => { setQuery={jest.fn()} setAbsoluteRangeDatePicker={(jest.fn() as unknown) as SetAbsoluteRangeDatePicker} hostDetailsPagePath={hostDetailsPagePath} + indexNames={[]} indexPattern={mockIndexPattern} type={type} pageFilters={mockHostDetailsPageFilters} diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx index 4d4eead0e778aa..284e6e27cf6154 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx @@ -28,12 +28,13 @@ import { export const HostDetailsTabs = React.memo( ({ + detailName, docValueFields, - pageFilters, filterQuery, - detailName, - setAbsoluteRangeDatePicker, + indexNames, indexPattern, + pageFilters, + setAbsoluteRangeDatePicker, hostDetailsPagePath, }) => { const { from, to, isInitializing, deleteQuery, setQuery } = useGlobalTime(); @@ -73,6 +74,7 @@ export const HostDetailsTabs = React.memo( startDate: from, type, indexPattern, + indexNames, hostName: detailName, narrowDateRange, updateDateRange, diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx index 57e1b128ce64de..55b2b529000be1 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx @@ -28,7 +28,6 @@ import { SiemSearchBar } from '../../../common/components/search_bar'; import { WrapperPage } from '../../../common/components/wrapper_page'; import { HostOverviewByNameQuery } from '../../containers/hosts/details'; import { useGlobalTime } from '../../../common/containers/use_global_time'; -import { useWithSource } from '../../../common/containers/source'; import { LastEventIndexKey } from '../../../graphql/types'; import { useKibana } from '../../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../../common/lib/keury'; @@ -51,6 +50,7 @@ import { timelineSelectors } from '../../../timelines/store/timeline'; import { TimelineModel } from '../../../timelines/store/timeline/model'; import { TimelineId } from '../../../../common/types/timeline'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; const HostOverviewManage = manageQuery(HostOverview); @@ -89,7 +89,7 @@ const HostDetailsComponent = React.memo( }, [setAbsoluteRangeDatePicker] ); - const { docValueFields, indicesExist, indexPattern } = useWithSource(); + const { docValueFields, indicesExist, indexPattern, selectedPatterns } = useSourcererScope(); const filterQuery = convertToBuildEsQuery({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), indexPattern, @@ -111,12 +111,18 @@ const HostDetailsComponent = React.memo( + } title={detailName} /> ( > {({ isLoadingAnomaliesData, anomaliesData }) => ( ( data={hostOverview as HostItem} anomaliesData={anomaliesData} isLoadingAnomaliesData={isLoadingAnomaliesData} + indexNames={selectedPatterns} loading={loading} startDate={from} endDate={to} @@ -161,6 +169,7 @@ const HostDetailsComponent = React.memo( ( ; export type HostDetailsTabsProps = HostBodyComponentDispatchProps & HostsQueryProps & { docValueFields?: DocValueFields[]; + indexNames: string[]; pageFilters?: Filter[]; filterQuery: string; indexPattern: IIndexPattern; diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx index 566f8f23efd39f..b341647afdfbc4 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx @@ -10,7 +10,6 @@ import { Router } from 'react-router-dom'; import { Filter } from '../../../../../../src/plugins/data/common/es_query'; import '../../common/mock/match_media'; -import { useWithSource } from '../../common/containers/source'; import { apolloClientObservable, TestProviders, @@ -25,8 +24,9 @@ import { State, createStore } from '../../common/store'; import { HostsComponentProps } from './types'; import { Hosts } from './hosts'; import { HostsTabs } from './hosts_tabs'; +import { useSourcererScope } from '../../common/containers/sourcerer'; -jest.mock('../../common/containers/source'); +jest.mock('../../common/containers/sourcerer'); // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar and QueryBar @@ -58,14 +58,14 @@ const mockHistory = { createHref: jest.fn(), listen: jest.fn(), }; - +const mockUseSourcererScope = useSourcererScope as jest.Mock; describe('Hosts - rendering', () => { const hostProps: HostsComponentProps = { hostsPagePath: '', }; test('it renders the Setup Instructions text when no index is available', async () => { - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ indicesExist: false, }); @@ -80,7 +80,7 @@ describe('Hosts - rendering', () => { }); test('it DOES NOT render the Setup Instructions text when an index is available', async () => { - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ indicesExist: true, indexPattern: {}, }); @@ -95,7 +95,7 @@ describe('Hosts - rendering', () => { }); test('it should render tab navigation', async () => { - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ indicesExist: true, indexPattern: {}, }); @@ -142,7 +142,7 @@ describe('Hosts - rendering', () => { }, }, ]; - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ indicesExist: true, indexPattern: { fields: [], title: 'title' }, }); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx index 4b8e3cc6987ac8..ea8cf11e7595a9 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx @@ -22,7 +22,6 @@ import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; import { useFullScreen } from '../../common/containers/use_full_screen'; import { useGlobalTime } from '../../common/containers/use_global_time'; -import { useWithSource } from '../../common/containers/source'; import { TimelineId } from '../../../common/types/timeline'; import { LastEventIndexKey } from '../../graphql/types'; import { useKibana } from '../../common/lib/kibana'; @@ -46,6 +45,7 @@ import { showGlobalFilters } from '../../timelines/components/timeline/helpers'; import { timelineSelectors } from '../../timelines/store/timeline'; import { timelineDefaults } from '../../timelines/store/timeline/defaults'; import { TimelineModel } from '../../timelines/store/timeline/model'; +import { useSourcererScope } from '../../common/containers/sourcerer'; export const HostsComponent = React.memo( ({ filters, graphEventId, query, setAbsoluteRangeDatePicker, hostsPagePath }) => { @@ -74,7 +74,7 @@ export const HostsComponent = React.memo( }, [setAbsoluteRangeDatePicker] ); - const { docValueFields, indicesExist, indexPattern } = useWithSource(); + const { docValueFields, indicesExist, indexPattern, selectedPatterns } = useSourcererScope(); const filterQuery = convertToBuildEsQuery({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), indexPattern, @@ -101,12 +101,19 @@ export const HostsComponent = React.memo( } + subtitle={ + + } title={i18n.PAGE_TITLE} /> ( to={to} filterQuery={tabsFilterQuery} isInitializing={isInitializing} + indexNames={selectedPatterns} setAbsoluteRangeDatePicker={setAbsoluteRangeDatePicker} setQuery={setQuery} from={from} type={hostsModel.HostsType.page} - indexPattern={indexPattern} hostsPagePath={hostsPagePath} /> diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts_tabs.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts_tabs.tsx index 8e2ea06fd20cbb..17dd20bac2d0d7 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts_tabs.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts_tabs.tsx @@ -28,24 +28,24 @@ export const HostsTabs = memo( deleteQuery, docValueFields, filterQuery, - setAbsoluteRangeDatePicker, - to, from, - setQuery, + indexNames, isInitializing, - type, - indexPattern, hostsPagePath, + setAbsoluteRangeDatePicker, + setQuery, + to, + type, }) => { const tabProps = { deleteQuery, endDate: to, filterQuery, + indexNames, skip: isInitializing, setQuery, startDate: from, type, - indexPattern, narrowDateRange: useCallback( (score: Anomaly, interval: string) => { const fromTo = scoreIntervalToDateTime(score, interval); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx b/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx index d3fc68874ce912..efce312fd85f2c 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/authentications_query_tab_body.tsx @@ -66,6 +66,7 @@ const AuthenticationsQueryTabBodyComponent: React.FC docValueFields, endDate, filterQuery, + indexNames, skip, setQuery, startDate, @@ -74,7 +75,15 @@ const AuthenticationsQueryTabBodyComponent: React.FC const [ loading, { authentications, totalCount, pageInfo, loadPage, id, inspect, isInspected, refetch }, - ] = useAuthentications({ docValueFields, endDate, filterQuery, skip, startDate, type }); + ] = useAuthentications({ + docValueFields, + endDate, + filterQuery, + indexNames, + skip, + startDate, + type, + }); useEffect(() => { return () => { @@ -90,6 +99,7 @@ const AuthenticationsQueryTabBodyComponent: React.FC endDate={endDate} filterQuery={filterQuery} id={ID} + indexNames={indexNames} setQuery={setQuery} startDate={startDate} {...histogramConfigs} diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx b/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx index be8412caf77326..e30071ec04f0cf 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx @@ -20,6 +20,7 @@ import { useFullScreen } from '../../../common/containers/use_full_screen'; import * as i18n from '../translations'; import { MatrixHistogramType } from '../../../../common/search_strategy/security_solution'; import { useManageTimeline } from '../../../timelines/components/manage_timeline'; +import { SourcererScopeName } from '../../../common/store/sourcerer/model'; const EVENTS_HISTOGRAM_ID = 'eventsHistogramQuery'; @@ -54,6 +55,7 @@ const EventsQueryTabBodyComponent: React.FC = ({ deleteQuery, endDate, filterQuery, + indexNames, pageFilters, setQuery, startDate, @@ -85,6 +87,7 @@ const EventsQueryTabBodyComponent: React.FC = ({ setQuery={setQuery} startDate={startDate} id={EVENTS_HISTOGRAM_ID} + indexNames={indexNames} {...histogramConfigs} /> )} @@ -92,6 +95,7 @@ const EventsQueryTabBodyComponent: React.FC = ({ defaultModel={eventsDefaultModel} end={endDate} id={TimelineId.hostsPageEvents} + scopeId={SourcererScopeName.default} start={startDate} pageFilters={pageFilters} /> diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/hosts_query_tab_body.tsx b/x-pack/plugins/security_solution/public/hosts/pages/navigation/hosts_query_tab_body.tsx index f8dcf9635c053e..deda4b618fa644 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/hosts_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/hosts_query_tab_body.tsx @@ -18,7 +18,7 @@ export const HostsQueryTabBody = ({ docValueFields, endDate, filterQuery, - indexPattern, + indexNames, skip, setQuery, startDate, @@ -27,7 +27,7 @@ export const HostsQueryTabBody = ({ const [ loading, { hosts, totalCount, pageInfo, loadPage, id, inspect, isInspected, refetch }, - ] = useAllHost({ docValueFields, endDate, filterQuery, skip, startDate, type }); + ] = useAllHost({ docValueFields, endDate, filterQuery, indexNames, skip, startDate, type }); return ( - + {actions} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx index 235f1506371163..40c982cfc071bf 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx @@ -203,6 +203,7 @@ export const PolicyDetails = React.memo(() => { )} + +
+
+ +
+
+
+ +
+
+ +
+
+
{ reactTestingLibrary.act(() => { history.push('/trusted_apps'); }); + window.scrollTo = jest.fn(); }); test.skip('rendering', () => { diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/network/components/kpi_network/__snapshots__/index.test.tsx.snap index a03d7c2317517d..c512bd99a79165 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/__snapshots__/index.test.tsx.snap @@ -4,6 +4,7 @@ exports[`NetworkKpiComponent rendering it renders the default widget 1`] = ` = [ const NetworkKpiDnsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -36,6 +37,7 @@ const NetworkKpiDnsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiDns({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/kpi_network/index.test.tsx index 9c6b2fe3c8ca46..25a9fe03f9205f 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/index.test.tsx @@ -22,12 +22,13 @@ import { NetworkKpiComponent } from '.'; describe('NetworkKpiComponent', () => { const state: State = mockGlobalState; const props = { + filterQuery: '', from: '2019-06-15T06:00:00.000Z', - to: '2019-06-18T06:00:00.000Z', + indexNames: [], narrowDateRange: jest.fn(), - filterQuery: '', setQuery: jest.fn(), skip: true, + to: '2019-06-18T06:00:00.000Z', }; const { storage } = createSecuritySolutionStorageMock(); diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/index.tsx b/x-pack/plugins/security_solution/public/network/components/kpi_network/index.tsx index 95534e1a61988b..1a04d1cc2c0eb8 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/index.tsx @@ -15,7 +15,7 @@ import { NetworkKpiUniquePrivateIps } from './unique_private_ips'; import { NetworkKpiProps } from './types'; export const NetworkKpiComponent = React.memo( - ({ filterQuery, from, to, setQuery, skip, narrowDateRange }) => ( + ({ filterQuery, from, indexNames, to, setQuery, skip, narrowDateRange }) => ( @@ -23,6 +23,7 @@ export const NetworkKpiComponent = React.memo( ( ( ( ( = [ const NetworkKpiNetworkEventsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -41,6 +42,7 @@ const NetworkKpiNetworkEventsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiNetworkEvents({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/network/components/kpi_network/tls_handshakes/index.tsx index 575d4256e83956..500314446bc12a 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/tls_handshakes/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/tls_handshakes/index.tsx @@ -28,6 +28,7 @@ export const fieldsMapping: Readonly = [ const NetworkKpiTlsHandshakesComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -36,6 +37,7 @@ const NetworkKpiTlsHandshakesComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiTlsHandshakes({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/types.ts b/x-pack/plugins/security_solution/public/network/components/kpi_network/types.ts index d3a0ac5a6c5dd5..860e6e228bbaa4 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/types.ts +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/types.ts @@ -10,6 +10,7 @@ import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; export interface NetworkKpiProps { filterQuery: string; from: string; + indexNames: string[]; to: string; narrowDateRange: UpdateDateRange; setQuery: GlobalTimeArgs['setQuery']; diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_flows/index.tsx index d22d4454952f9c..65624ba4813785 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_flows/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_flows/index.tsx @@ -28,6 +28,7 @@ export const fieldsMapping: Readonly = [ const NetworkKpiUniqueFlowsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -36,6 +37,7 @@ const NetworkKpiUniqueFlowsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiUniqueFlows({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_private_ips/index.tsx index a7dfb38219c070..a8a179b97f51a2 100644 --- a/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_private_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/kpi_network/unique_private_ips/index.tsx @@ -47,6 +47,7 @@ export const fieldsMapping: Readonly = [ const NetworkKpiUniquePrivateIpsComponent: React.FC = ({ filterQuery, from, + indexNames, to, narrowDateRange, setQuery, @@ -55,6 +56,7 @@ const NetworkKpiUniquePrivateIpsComponent: React.FC = ({ const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiUniquePrivateIps({ filterQuery, endDate: to, + indexNames, startDate: from, skip, }); diff --git a/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx b/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx index b7f78873423351..afef7fe7949393 100644 --- a/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FlowTarget, UsersItem } from '../../../graphql/types'; +import { FlowTarget, NetworkUsersItem } from '../../../../common/search_strategy'; import { defaultToEmptyTag } from '../../../common/components/empty_value'; import { Columns } from '../../../common/components/paginated_table'; @@ -15,11 +15,11 @@ import { } from '../../../common/components/tables/helpers'; export type UsersColumns = [ - Columns, - Columns, - Columns, - Columns, - Columns + Columns, + Columns, + Columns, + Columns, + Columns ]; export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersColumns => [ diff --git a/x-pack/plugins/security_solution/public/network/components/users_table/mock.ts b/x-pack/plugins/security_solution/public/network/components/users_table/mock.ts index 50bef1867aa3b4..9180ee328f988f 100644 --- a/x-pack/plugins/security_solution/public/network/components/users_table/mock.ts +++ b/x-pack/plugins/security_solution/public/network/components/users_table/mock.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UsersData } from '../../../graphql/types'; +import { NetworkUsersStrategyResponse } from '../../../../common/search_strategy'; -export const mockUsersData: UsersData = { +export const mockUsersData: NetworkUsersStrategyResponse = { edges: [ { node: { @@ -63,4 +63,5 @@ export const mockUsersData: UsersData = { fakeTotalCount: 3, showMorePagesIndicator: true, }, + rawResponse: {} as NetworkUsersStrategyResponse['rawResponse'], }; diff --git a/x-pack/plugins/security_solution/public/network/containers/details/index.gql_query.ts b/x-pack/plugins/security_solution/public/network/containers/details/index.gql_query.ts deleted file mode 100644 index 6ebb60ccb4ea6b..00000000000000 --- a/x-pack/plugins/security_solution/public/network/containers/details/index.gql_query.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const ipOverviewQuery = gql` - query GetIpOverviewQuery( - $sourceId: ID! - $filterQuery: String - $ip: String! - $defaultIndex: [String!]! - $inspect: Boolean! - $docValueFields: [docValueFieldsInput!]! - ) { - source(id: $sourceId) { - id - IpOverview( - filterQuery: $filterQuery - ip: $ip - defaultIndex: $defaultIndex - docValueFields: $docValueFields - ) { - source { - firstSeen - lastSeen - autonomousSystem { - number - organization { - name - } - } - geo { - continent_name - city_name - country_iso_code - country_name - location { - lat - lon - } - region_iso_code - region_name - } - } - destination { - firstSeen - lastSeen - autonomousSystem { - number - organization { - name - } - } - geo { - continent_name - city_name - country_iso_code - country_name - location { - lat - lon - } - region_iso_code - region_name - } - } - host { - architecture - id - ip - mac - name - os { - family - name - platform - version - } - type - } - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/network/containers/details/index.tsx b/x-pack/plugins/security_solution/public/network/containers/details/index.tsx index f6ea86bd552f44..217241bdadcbb3 100644 --- a/x-pack/plugins/security_solution/public/network/containers/details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/details/index.tsx @@ -9,7 +9,6 @@ import { useState, useEffect, useCallback, useRef } from 'react'; import deepEqual from 'fast-deep-equal'; import { ESTermQuery } from '../../../../common/typed_json'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; @@ -42,6 +41,7 @@ interface UseNetworkDetails { id?: string; docValueFields: DocValueFields[]; ip: string; + indexNames: string[]; filterQuery?: ESTermQuery | string; skip: boolean; } @@ -49,18 +49,18 @@ interface UseNetworkDetails { export const useNetworkDetails = ({ docValueFields, filterQuery, + indexNames, id = ID, skip, ip, }: UseNetworkDetails): [boolean, NetworkDetailsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkDetailsRequest, setNetworkDetailsRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, docValueFields: docValueFields ?? [], factoryQueryType: NetworkQueries.details, filterQuery: createFilter(filterQuery), @@ -137,7 +137,7 @@ export const useNetworkDetails = ({ setNetworkDetailsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, ip, docValueFields: docValueFields ?? [], filterQuery: createFilter(filterQuery), @@ -147,7 +147,7 @@ export const useNetworkDetails = ({ } return prevRequest; }); - }, [defaultIndex, filterQuery, skip, ip, docValueFields]); + }, [indexNames, filterQuery, skip, ip, docValueFields]); useEffect(() => { networkDetailsSearch(networkDetailsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx index 2afbff3138c6b6..dc60bb0a82ba8f 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -41,6 +40,7 @@ export interface NetworkKpiDnsArgs { interface UseNetworkKpiDns { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -48,16 +48,16 @@ interface UseNetworkKpiDns { export const useNetworkKpiDns = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseNetworkKpiDns): [boolean, NetworkKpiDnsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkKpiDnsRequest, setNetworkKpiDnsRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkKpiQueries.dns, filterQuery: createFilter(filterQuery), id: ID, @@ -138,7 +138,7 @@ export const useNetworkKpiDns = ({ setNetworkKpiDnsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -151,7 +151,7 @@ export const useNetworkKpiDns = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { networkKpiDnsSearch(networkKpiDnsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx index 26b57ef36b09d0..a1727d5bb4331b 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -41,6 +40,7 @@ export interface NetworkKpiNetworkEventsArgs { interface UseNetworkKpiNetworkEvents { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -48,18 +48,18 @@ interface UseNetworkKpiNetworkEvents { export const useNetworkKpiNetworkEvents = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseNetworkKpiNetworkEvents): [boolean, NetworkKpiNetworkEventsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkKpiNetworkEventsRequest, setNetworkKpiNetworkEventsRequest] = useState< NetworkKpiNetworkEventsRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkKpiQueries.networkEvents, filterQuery: createFilter(filterQuery), id: ID, @@ -145,7 +145,7 @@ export const useNetworkKpiNetworkEvents = ({ setNetworkKpiNetworkEventsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -158,7 +158,7 @@ export const useNetworkKpiNetworkEvents = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { networkKpiNetworkEventsSearch(networkKpiNetworkEventsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx index c97c1e43e699ac..bcbe485e821636 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -41,6 +40,7 @@ export interface NetworkKpiTlsHandshakesArgs { interface UseNetworkKpiTlsHandshakes { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -48,18 +48,18 @@ interface UseNetworkKpiTlsHandshakes { export const useNetworkKpiTlsHandshakes = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseNetworkKpiTlsHandshakes): [boolean, NetworkKpiTlsHandshakesArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkKpiTlsHandshakesRequest, setNetworkKpiTlsHandshakesRequest] = useState< NetworkKpiTlsHandshakesRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkKpiQueries.tlsHandshakes, filterQuery: createFilter(filterQuery), id: ID, @@ -145,7 +145,7 @@ export const useNetworkKpiTlsHandshakes = ({ setNetworkKpiTlsHandshakesRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -158,7 +158,7 @@ export const useNetworkKpiTlsHandshakes = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { networkKpiTlsHandshakesSearch(networkKpiTlsHandshakesRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx index 4e8b4ad38b711c..a4fdefc93fe75c 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -41,6 +40,7 @@ export interface NetworkKpiUniqueFlowsArgs { interface UseNetworkKpiUniqueFlows { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -48,18 +48,18 @@ interface UseNetworkKpiUniqueFlows { export const useNetworkKpiUniqueFlows = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseNetworkKpiUniqueFlows): [boolean, NetworkKpiUniqueFlowsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkKpiUniqueFlowsRequest, setNetworkKpiUniqueFlowsRequest] = useState< NetworkKpiUniqueFlowsRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkKpiQueries.uniqueFlows, filterQuery: createFilter(filterQuery), id: ID, @@ -145,7 +145,7 @@ export const useNetworkKpiUniqueFlows = ({ setNetworkKpiUniqueFlowsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -158,7 +158,7 @@ export const useNetworkKpiUniqueFlows = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { networkKpiUniqueFlowsSearch(networkKpiUniqueFlowsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx index b518f952121293..5e9d829077f237 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx @@ -8,7 +8,6 @@ import deepEqual from 'fast-deep-equal'; import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { DEFAULT_INDEX_KEY } from '../../../../../common/constants'; import { inputsModel } from '../../../../common/store'; import { createFilter } from '../../../../common/containers/helpers'; import { useKibana } from '../../../../common/lib/kibana'; @@ -45,6 +44,7 @@ export interface NetworkKpiUniquePrivateIpsArgs { interface UseNetworkKpiUniquePrivateIps { filterQuery?: ESTermQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -52,18 +52,18 @@ interface UseNetworkKpiUniquePrivateIps { export const useNetworkKpiUniquePrivateIps = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseNetworkKpiUniquePrivateIps): [boolean, NetworkKpiUniquePrivateIpsArgs] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkKpiUniquePrivateIpsRequest, setNetworkKpiUniquePrivateIpsRequest] = useState< NetworkKpiUniquePrivateIpsRequestOptions >({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkKpiQueries.uniquePrivateIps, filterQuery: createFilter(filterQuery), id: ID, @@ -156,7 +156,7 @@ export const useNetworkKpiUniquePrivateIps = ({ setNetworkKpiUniquePrivateIpsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -169,7 +169,7 @@ export const useNetworkKpiUniquePrivateIps = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { networkKpiUniquePrivateIpsSearch(networkKpiUniquePrivateIpsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx index 209f8da0d8fae1..334373c4a551a7 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx @@ -10,7 +10,6 @@ import { shallowEqual, useSelector } from 'react-redux'; import deepEqual from 'fast-deep-equal'; import { ESTermQuery } from '../../../../common/typed_json'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; @@ -51,6 +50,7 @@ export interface NetworkDnsArgs { interface UseNetworkDns { id?: string; + indexNames: string[]; type: networkModel.NetworkType; filterQuery?: ESTermQuery | string; endDate: string; @@ -62,6 +62,7 @@ export const useNetworkDns = ({ endDate, filterQuery, id = ID, + indexNames, skip, startDate, type, @@ -71,14 +72,13 @@ export const useNetworkDns = ({ (state: State) => getNetworkDnsSelector(state), shallowEqual ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkDnsRequest, setNetworkDnsRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkQueries.dns, filterQuery: createFilter(filterQuery), isPtrIncluded, @@ -182,7 +182,7 @@ export const useNetworkDns = ({ setNetworkDnsRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, isPtrIncluded, filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), @@ -198,7 +198,7 @@ export const useNetworkDns = ({ } return prevRequest; }); - }, [activePage, defaultIndex, endDate, filterQuery, limit, startDate, sort, skip, isPtrIncluded]); + }, [activePage, indexNames, endDate, filterQuery, limit, startDate, sort, skip, isPtrIncluded]); useEffect(() => { networkDnsSearch(networkDnsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx index 9244d571bb67ba..221b693818c503 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx @@ -10,7 +10,6 @@ import { shallowEqual, useSelector } from 'react-redux'; import deepEqual from 'fast-deep-equal'; import { ESTermQuery } from '../../../../common/typed_json'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; @@ -49,6 +48,7 @@ export interface NetworkHttpArgs { interface UseNetworkHttp { id?: string; ip?: string; + indexNames: string[]; type: networkModel.NetworkType; filterQuery?: ESTermQuery | string; endDate: string; @@ -60,6 +60,7 @@ export const useNetworkHttp = ({ endDate, filterQuery, id = ID, + indexNames, ip, skip, startDate, @@ -70,14 +71,13 @@ export const useNetworkHttp = ({ (state: State) => getHttpSelector(state, type), shallowEqual ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkHttpRequest, setHostRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkQueries.http, filterQuery: createFilter(filterQuery), ip, @@ -181,7 +181,7 @@ export const useNetworkHttp = ({ setHostRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), sort: sort as SortField, @@ -196,7 +196,7 @@ export const useNetworkHttp = ({ } return prevRequest; }); - }, [activePage, defaultIndex, endDate, filterQuery, limit, startDate, sort, skip]); + }, [activePage, indexNames, endDate, filterQuery, limit, startDate, sort, skip]); useEffect(() => { networkHttpSearch(networkHttpRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx index 8138d30f2c510b..6b52966342e973 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx @@ -10,7 +10,6 @@ import { shallowEqual, useSelector } from 'react-redux'; import deepEqual from 'fast-deep-equal'; import { ESTermQuery } from '../../../../common/typed_json'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; @@ -49,6 +48,7 @@ export interface NetworkTopCountriesArgs { interface UseNetworkTopCountries { flowTarget: FlowTargetSourceDest; ip?: string; + indexNames: string[]; type: networkModel.NetworkType; filterQuery?: ESTermQuery | string; endDate: string; @@ -60,6 +60,7 @@ export const useNetworkTopCountries = ({ endDate, filterQuery, flowTarget, + indexNames, skip, startDate, type, @@ -69,14 +70,13 @@ export const useNetworkTopCountries = ({ (state: State) => getTopCountriesSelector(state, type, flowTarget), shallowEqual ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkTopCountriesRequest, setHostRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkQueries.topCountries, filterQuery: createFilter(filterQuery), flowTarget, @@ -180,7 +180,7 @@ export const useNetworkTopCountries = ({ setHostRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), sort, @@ -195,7 +195,7 @@ export const useNetworkTopCountries = ({ } return prevRequest; }); - }, [activePage, defaultIndex, endDate, filterQuery, limit, startDate, sort, skip]); + }, [activePage, indexNames, endDate, filterQuery, limit, startDate, sort, skip]); useEffect(() => { networkTopCountriesSearch(networkTopCountriesRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx index 76c2ae2871a386..d6dd14b3259f04 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx @@ -10,7 +10,6 @@ import { shallowEqual, useSelector } from 'react-redux'; import deepEqual from 'fast-deep-equal'; import { ESTermQuery } from '../../../../common/typed_json'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; @@ -49,6 +48,7 @@ export interface NetworkTopNFlowArgs { interface UseNetworkTopNFlow { flowTarget: FlowTargetSourceDest; ip?: string; + indexNames: string[]; type: networkModel.NetworkType; filterQuery?: ESTermQuery | string; endDate: string; @@ -60,6 +60,7 @@ export const useNetworkTopNFlow = ({ endDate, filterQuery, flowTarget, + indexNames, skip, startDate, type, @@ -69,14 +70,13 @@ export const useNetworkTopNFlow = ({ (state: State) => getTopNFlowSelector(state, type, flowTarget), shallowEqual ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkTopNFlowRequest, setTopNFlowRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkQueries.topNFlow, filterQuery: createFilter(filterQuery), flowTarget, @@ -178,7 +178,7 @@ export const useNetworkTopNFlow = ({ setTopNFlowRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), timerange: { @@ -193,7 +193,7 @@ export const useNetworkTopNFlow = ({ } return prevRequest; }); - }, [activePage, defaultIndex, endDate, filterQuery, limit, startDate, sort, skip]); + }, [activePage, indexNames, endDate, filterQuery, limit, startDate, sort, skip]); useEffect(() => { networkTopNFlowSearch(networkTopNFlowRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx b/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx index 4c9658aa9b42ca..f40675a1255ff8 100644 --- a/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx @@ -10,7 +10,6 @@ import { shallowEqual, useSelector } from 'react-redux'; import deepEqual from 'fast-deep-equal'; import { ESTermQuery } from '../../../../common/typed_json'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; @@ -46,6 +45,7 @@ export interface NetworkTlsArgs { interface UseNetworkTls { flowTarget: FlowTargetSourceDest; + indexNames: string[]; ip: string; type: networkModel.NetworkType; filterQuery?: ESTermQuery | string; @@ -60,6 +60,7 @@ export const useNetworkTls = ({ filterQuery, flowTarget, id = ID, + indexNames, ip, skip, startDate, @@ -70,14 +71,13 @@ export const useNetworkTls = ({ (state: State) => getTlsSelector(state, type, flowTarget), shallowEqual ); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [networkTlsRequest, setHostRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkQueries.tls, filterQuery: createFilter(filterQuery), flowTarget, @@ -178,7 +178,7 @@ export const useNetworkTls = ({ setHostRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), pagination: generateTablePaginationOptions(activePage, limit), timerange: { @@ -193,7 +193,7 @@ export const useNetworkTls = ({ } return prevRequest; }); - }, [activePage, defaultIndex, endDate, filterQuery, limit, startDate, sort, skip]); + }, [activePage, indexNames, endDate, filterQuery, limit, startDate, sort, skip]); useEffect(() => { networkTlsSearch(networkTlsRequest); diff --git a/x-pack/plugins/security_solution/public/network/containers/users/index.gql_query.ts b/x-pack/plugins/security_solution/public/network/containers/users/index.gql_query.ts deleted file mode 100644 index 3fc1cdfd160dba..00000000000000 --- a/x-pack/plugins/security_solution/public/network/containers/users/index.gql_query.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const usersQuery = gql` - query GetUsersQuery( - $sourceId: ID! - $filterQuery: String - $flowTarget: FlowTarget! - $ip: String! - $pagination: PaginationInputPaginated! - $sort: UsersSortField! - $timerange: TimerangeInput! - $defaultIndex: [String!]! - $inspect: Boolean! - ) { - source(id: $sourceId) { - id - Users( - filterQuery: $filterQuery - flowTarget: $flowTarget - ip: $ip - pagination: $pagination - sort: $sort - timerange: $timerange - defaultIndex: $defaultIndex - ) { - totalCount - edges { - node { - user { - name - id - groupId - groupName - count - } - } - cursor { - value - } - } - pageInfo { - activePage - fakeTotalCount - showMorePagesIndicator - } - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx b/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx index beae3e4f72aaa5..430b5702be1bc2 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx @@ -9,7 +9,7 @@ import { Router, useParams } from 'react-router-dom'; import '../../../common/mock/match_media'; -import { useWithSource } from '../../../common/containers/source'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; import { FlowTarget } from '../../../graphql/types'; import { apolloClientObservable, @@ -40,7 +40,7 @@ jest.mock('../../containers/details', () => ({ useNetworkDetails: jest.fn().mockReturnValue([true, { networkDetails: {} }]), })); jest.mock('../../../common/lib/kibana'); -jest.mock('../../../common/containers/source'); +jest.mock('../../../common/containers/sourcerer'); jest.mock('../../../common/containers/use_global_time', () => ({ useGlobalTime: jest.fn().mockReturnValue({ from: '2020-07-07T08:20:18.966Z', @@ -81,7 +81,7 @@ const getMockHistory = (ip: string) => ({ describe('Network Details', () => { const mount = useMountAppended(); beforeAll(() => { - (useWithSource as jest.Mock).mockReturnValue({ + (useSourcererScope as jest.Mock).mockReturnValue({ indicesExist: false, indexPattern: {}, }); @@ -137,7 +137,7 @@ describe('Network Details', () => { test('it renders ipv6 headline', async () => { const ip = 'fe80--24ce-f7ff-fede-a571'; - (useWithSource as jest.Mock).mockReturnValue({ + (useSourcererScope as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, }); diff --git a/x-pack/plugins/security_solution/public/network/pages/details/index.tsx b/x-pack/plugins/security_solution/public/network/pages/details/index.tsx index 085cddf53ff65e..eaeb31c020473c 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/index.tsx @@ -24,7 +24,6 @@ import { IpOverview } from '../../components/details'; import { SiemSearchBar } from '../../../common/components/search_bar'; import { WrapperPage } from '../../../common/components/wrapper_page'; import { useNetworkDetails } from '../../containers/details'; -import { useWithSource } from '../../../common/containers/source'; import { FlowTargetSourceDest, LastEventIndexKey } from '../../../graphql/types'; import { useKibana } from '../../../common/lib/kibana'; import { decodeIpv6 } from '../../../common/lib/helpers'; @@ -44,6 +43,7 @@ import { AnomaliesQueryTabBody } from '../../../common/containers/anomalies/anom import { esQuery } from '../../../../../../../src/plugins/data/public'; import { networkModel } from '../../store'; import { SecurityPageName } from '../../../app/types'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; export { getBreadcrumbs } from './utils'; const NetworkDetailsManage = manageQuery(IpOverview); @@ -83,7 +83,7 @@ const NetworkDetailsComponent: React.FC = () => { dispatch(setNetworkDetailsTablesActivePageToZero()); }, [detailName, dispatch]); - const { docValueFields, indicesExist, indexPattern } = useWithSource(); + const { docValueFields, indicesExist, indexPattern, selectedPatterns } = useSourcererScope(); const ip = decodeIpv6(detailName); const filterQuery = convertToBuildEsQuery({ config: esQuery.getEsQueryConfig(uiSettings), @@ -96,6 +96,7 @@ const NetworkDetailsComponent: React.FC = () => { docValueFields, skip: isInitializing, filterQuery, + indexNames: selectedPatterns, ip, }); @@ -124,7 +125,14 @@ const NetworkDetailsComponent: React.FC = () => { border data-test-subj="network-details-headline" draggableArguments={headerDraggableArguments} - subtitle={} + subtitle={ + + } title={ip} > @@ -155,6 +163,7 @@ const NetworkDetailsComponent: React.FC = () => { endDate={to} filterQuery={filterQuery} flowTarget={FlowTargetSourceDest.source} + indexNames={selectedPatterns} ip={ip} skip={isInitializing} startDate={from} @@ -169,6 +178,7 @@ const NetworkDetailsComponent: React.FC = () => { endDate={to} flowTarget={FlowTargetSourceDest.destination} filterQuery={filterQuery} + indexNames={selectedPatterns} ip={ip} skip={isInitializing} startDate={from} @@ -187,6 +197,7 @@ const NetworkDetailsComponent: React.FC = () => { endDate={to} filterQuery={filterQuery} flowTarget={FlowTargetSourceDest.source} + indexNames={selectedPatterns} ip={ip} skip={isInitializing} startDate={from} @@ -201,6 +212,7 @@ const NetworkDetailsComponent: React.FC = () => { endDate={to} flowTarget={FlowTargetSourceDest.destination} filterQuery={filterQuery} + indexNames={selectedPatterns} ip={ip} skip={isInitializing} startDate={from} @@ -217,6 +229,7 @@ const NetworkDetailsComponent: React.FC = () => { endDate={to} filterQuery={filterQuery} flowTarget={flowTarget} + indexNames={selectedPatterns} ip={ip} skip={isInitializing} startDate={from} @@ -229,6 +242,7 @@ const NetworkDetailsComponent: React.FC = () => { { endDate={to} filterQuery={filterQuery} flowTarget={(flowTarget as unknown) as FlowTargetSourceDest} + indexNames={selectedPatterns} ip={ip} setQuery={setQuery} skip={isInitializing} @@ -257,6 +272,7 @@ const NetworkDetailsComponent: React.FC = () => { startDate={from} endDate={to} skip={isInitializing} + indexNames={selectedPatterns} ip={ip} type={type} flowTarget={flowTarget} diff --git a/x-pack/plugins/security_solution/public/network/pages/details/network_http_query_table.tsx b/x-pack/plugins/security_solution/public/network/pages/details/network_http_query_table.tsx index 1b1b2b5f4f46e2..0a885193904863 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/network_http_query_table.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/network_http_query_table.tsx @@ -28,6 +28,7 @@ export const NetworkHttpQueryTable = ({ ] = useNetworkHttp({ endDate, filterQuery, + indexNames: [], ip, skip, startDate, diff --git a/x-pack/plugins/security_solution/public/network/pages/details/network_top_countries_query_table.tsx b/x-pack/plugins/security_solution/public/network/pages/details/network_top_countries_query_table.tsx index 42ddd3a6bb4a43..8a7d499a8ef5fa 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/network_top_countries_query_table.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/network_top_countries_query_table.tsx @@ -31,6 +31,7 @@ export const NetworkTopCountriesQueryTable = ({ endDate, flowTarget, filterQuery, + indexNames: [], ip, skip, startDate, diff --git a/x-pack/plugins/security_solution/public/network/pages/details/network_top_n_flow_query_table.tsx b/x-pack/plugins/security_solution/public/network/pages/details/network_top_n_flow_query_table.tsx index 821452201b78b0..d56d6d4f6b3ee5 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/network_top_n_flow_query_table.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/network_top_n_flow_query_table.tsx @@ -18,6 +18,7 @@ export const NetworkTopNFlowQueryTable = ({ filterQuery, flowTarget, ip, + indexNames, setQuery, skip, startDate, @@ -30,6 +31,7 @@ export const NetworkTopNFlowQueryTable = ({ endDate, filterQuery, flowTarget, + indexNames, ip, skip, startDate, diff --git a/x-pack/plugins/security_solution/public/network/pages/details/tls_query_table.tsx b/x-pack/plugins/security_solution/public/network/pages/details/tls_query_table.tsx index 5184fccecf07a5..b8c53cdf10fee8 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/tls_query_table.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/tls_query_table.tsx @@ -30,6 +30,7 @@ export const TlsQueryTable = ({ endDate, filterQuery, flowTarget, + indexNames: [], ip, skip, startDate, diff --git a/x-pack/plugins/security_solution/public/network/pages/details/types.ts b/x-pack/plugins/security_solution/public/network/pages/details/types.ts index 960df0d5e36b9b..3b5a7fab3c6e73 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/types.ts +++ b/x-pack/plugins/security_solution/public/network/pages/details/types.ts @@ -22,6 +22,7 @@ export interface OwnProps { endDate: string; filterQuery: string | ESTermQuery; ip: string; + indexNames: string[]; skip: boolean; setQuery: GlobalTimeArgs['setQuery']; } diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/countries_query_tab_body.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/countries_query_tab_body.tsx index 1e57ca42257e78..1c61760d9845f0 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/countries_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/countries_query_tab_body.tsx @@ -19,6 +19,7 @@ const NetworkTopCountriesTableManage = manageQuery(NetworkTopCountriesTable); export const CountriesQueryTabBody = ({ endDate, filterQuery, + indexNames, skip, startDate, setQuery, @@ -32,6 +33,7 @@ export const CountriesQueryTabBody = ({ endDate, flowTarget, filterQuery, + indexNames, skip, startDate, type: networkModel.NetworkType.page, diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx index 5adb78edbec8e5..a8bae2509e0d6e 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx @@ -45,6 +45,7 @@ const DnsQueryTabBodyComponent: React.FC = ({ deleteQuery, endDate, filterQuery, + indexNames, skip, startDate, setQuery, @@ -64,6 +65,7 @@ const DnsQueryTabBodyComponent: React.FC = ({ ] = useNetworkDns({ endDate, filterQuery, + indexNames, skip, startDate, type, @@ -88,6 +90,7 @@ const DnsQueryTabBodyComponent: React.FC = ({ endDate={endDate} filterQuery={filterQuery} id={HISTOGRAM_ID} + indexNames={indexNames} setQuery={setQuery} showLegend={true} startDate={startDate} diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/http_query_tab_body.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/http_query_tab_body.tsx index 3caff05734c1e4..85d6b6daabd6c4 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/http_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/http_query_tab_body.tsx @@ -19,6 +19,7 @@ const NetworkHttpTableManage = manageQuery(NetworkHttpTable); export const HttpQueryTabBody = ({ endDate, filterQuery, + indexNames, skip, startDate, setQuery, @@ -29,6 +30,7 @@ export const HttpQueryTabBody = ({ ] = useNetworkHttp({ endDate, filterQuery, + indexNames, skip, startDate, type: networkModel.NetworkType.page, diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/ips_query_tab_body.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/ips_query_tab_body.tsx index c83bf6ff809012..465b3347ce707f 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/ips_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/ips_query_tab_body.tsx @@ -19,6 +19,7 @@ const NetworkTopNFlowTableManage = manageQuery(NetworkTopNFlowTable); export const IPsQueryTabBody = ({ endDate, filterQuery, + indexNames, skip, startDate, setQuery, @@ -31,6 +32,7 @@ export const IPsQueryTabBody = ({ endDate, flowTarget, filterQuery, + indexNames, skip, startDate, type: networkModel.NetworkType.page, diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/network_routes.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/network_routes.tsx index 2da56a30df7c75..7af474728c824b 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/network_routes.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/network_routes.tsx @@ -33,6 +33,7 @@ export const NetworkRoutes = React.memo( isInitializing, from, indexPattern, + indexNames, setQuery, setAbsoluteRangeDatePicker, }) => { @@ -83,6 +84,7 @@ export const NetworkRoutes = React.memo( const commonProps = { startDate: from, endDate: to, + indexNames, skip: isInitializing, type, narrowDateRange, diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/tls_query_tab_body.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/tls_query_tab_body.tsx index 279891cc181e3d..702a9e696220f7 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/tls_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/tls_query_tab_body.tsx @@ -16,6 +16,7 @@ const TlsQueryTabBodyComponent: React.FC = ({ endDate, filterQuery, flowTarget, + indexNames, ip = '', setQuery, skip, @@ -29,6 +30,7 @@ const TlsQueryTabBodyComponent: React.FC = ({ endDate, filterQuery, flowTarget, + indexNames, ip, skip, startDate, diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts b/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts index 2ef04d3371c0b9..ed04fd01a7b891 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts @@ -22,6 +22,7 @@ interface QueryTabBodyProps extends Pick ({ +const mockProps = { networkPagePath: '', to, from, @@ -69,40 +69,42 @@ const getMockProps = () => ({ setQuery: jest.fn(), capabilitiesFetched: true, hasMlUserPermissions: true, -}); - +}; +const mockUseSourcererScope = useSourcererScope as jest.Mock; describe('rendering - rendering', () => { - test('it renders the Setup Instructions text when no index is available', async () => { - (useWithSource as jest.Mock).mockReturnValue({ + test('it renders the Setup Instructions text when no index is available', () => { + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: false, }); const wrapper = mount( - + ); expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); }); - test('it DOES NOT render the Setup Instructions text when an index is available', async () => { - (useWithSource as jest.Mock).mockReturnValue({ + test('it DOES NOT render the Setup Instructions text when an index is available', () => { + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: true, indexPattern: {}, }); const wrapper = mount( - + ); expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(false); }); - test('it should add the new filters after init', async () => { + test('it should add the new filters after init', () => { const newFilters: Filter[] = [ { query: { @@ -134,7 +136,8 @@ describe('rendering - rendering', () => { }, }, ]; - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: true, indexPattern: { fields: [], title: 'title' }, }); @@ -150,7 +153,7 @@ describe('rendering - rendering', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/network/pages/network.tsx b/x-pack/plugins/security_solution/public/network/pages/network.tsx index 8aed6385ea24d6..6aea771e49499f 100644 --- a/x-pack/plugins/security_solution/public/network/pages/network.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/network.tsx @@ -24,7 +24,6 @@ import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; import { useFullScreen } from '../../common/containers/use_full_screen'; import { useGlobalTime } from '../../common/containers/use_global_time'; -import { useWithSource } from '../../common/containers/source'; import { LastEventIndexKey } from '../../graphql/types'; import { useKibana } from '../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../common/lib/keury'; @@ -44,8 +43,7 @@ import { timelineSelectors } from '../../timelines/store/timeline'; import { TimelineId } from '../../../common/types/timeline'; import { timelineDefaults } from '../../timelines/store/timeline/defaults'; import { TimelineModel } from '../../timelines/store/timeline/model'; - -const sourceId = 'default'; +import { useSourcererScope } from '../../common/containers/sourcerer'; const NetworkComponent = React.memo( ({ @@ -84,7 +82,7 @@ const NetworkComponent = React.memo( [setAbsoluteRangeDatePicker] ); - const { indicesExist, indexPattern } = useWithSource(sourceId); + const { docValueFields, indicesExist, indexPattern, selectedPatterns } = useSourcererScope(); const filterQuery = convertToBuildEsQuery({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), indexPattern, @@ -111,7 +109,13 @@ const NetworkComponent = React.memo( } + subtitle={ + + } title={i18n.PAGE_TITLE} /> @@ -127,11 +131,12 @@ const NetworkComponent = React.memo( @@ -150,6 +155,7 @@ const NetworkComponent = React.memo( from={from} isInitializing={isInitializing} indexPattern={indexPattern} + indexNames={selectedPatterns} setQuery={setQuery} setAbsoluteRangeDatePicker={setAbsoluteRangeDatePicker} type={networkModel.NetworkType.page} diff --git a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.test.tsx index e365ac38d31df3..6f1b7e95e763dc 100644 --- a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.test.tsx @@ -29,7 +29,15 @@ const to = '2019-03-31T06:00:00.000Z'; describe('Alerts by category', () => { let wrapper: ReactWrapper; - + const testProps = { + deleteQuery: jest.fn(), + filters: [], + from, + indexNames: [], + indexPattern: mockIndexPattern, + setQuery: jest.fn(), + to, + }; describe('before loading data', () => { beforeAll(async () => { (useMatrixHistogram as jest.Mock).mockReturnValue([ @@ -44,14 +52,7 @@ describe('Alerts by category', () => { wrapper = mount( - + ); @@ -119,14 +120,7 @@ describe('Alerts by category', () => { wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx index 1a2238c763bdad..4d3b2dbf3f11f6 100644 --- a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx @@ -43,6 +43,7 @@ interface Props extends Pick = ({ from, hideHeaderChildren = false, indexPattern, + indexNames, query = DEFAULT_QUERY, setQuery, to, @@ -117,6 +119,7 @@ const AlertsByCategoryComponent: React.FC = ({ })} headerChildren={hideHeaderChildren ? null : alertsCountViewAlertsButton} id={ID} + indexNames={indexNames} setQuery={setQuery} startDate={from} {...alertsByCategoryHistogramConfigs} diff --git a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx index f2d6b503260825..44cb7a65dbc5e9 100644 --- a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx @@ -20,11 +20,16 @@ describe('EventCounts', () => { const from = '2020-01-20T20:49:57.080Z'; const to = '2020-01-21T20:49:57.080Z'; + const testProps = { + from, + indexNames: [], + indexPattern: mockIndexPattern, + setQuery: jest.fn(), + to, + }; + test('it filters the `Host events` widget with a `host.name` `exists` filter', () => { - const wrapper = mount( - , - { wrappingComponent: TestProviders } - ); + const wrapper = mount(, { wrappingComponent: TestProviders }); expect( (wrapper.find('Memo(OverviewHostComponent)').first().props() as OverviewHostProps).filterQuery @@ -32,10 +37,7 @@ describe('EventCounts', () => { }); test('it filters the `Network events` widget with a `source.ip` or `destination.ip` `exists` filter', () => { - const wrapper = mount( - , - { wrappingComponent: TestProviders } - ); + const wrapper = mount(, { wrappingComponent: TestProviders }); expect( (wrapper.find('Memo(OverviewNetworkComponent)').first().props() as OverviewNetworkProps) diff --git a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx index 23f5998f44111e..6e47de68221c79 100644 --- a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx @@ -31,6 +31,7 @@ const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; interface Props extends Pick { filters?: Filter[]; + indexNames: string[]; indexPattern: IIndexPattern; query?: Query; } @@ -38,6 +39,7 @@ interface Props extends Pick { const EventCountsComponent: React.FC = ({ filters = NO_FILTERS, from, + indexNames, indexPattern, query = DEFAULT_QUERY, setQuery, @@ -56,6 +58,7 @@ const EventCountsComponent: React.FC = ({ queries: [query], filters: [...filters, ...filterHostData], })} + indexNames={indexNames} startDate={from} setQuery={setQuery} /> @@ -72,6 +75,7 @@ const EventCountsComponent: React.FC = ({ queries: [query], filters: [...filters, ...filterNetworkData], })} + indexNames={indexNames} startDate={from} setQuery={setQuery} /> diff --git a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index 7025afde963f14..1fa3d8f4ef27aa 100644 --- a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -47,7 +47,7 @@ interface Props extends Pick = ({ from, headerChildren, indexPattern, - indexToAdd, + indexNames, onlyField, query = DEFAULT_QUERY, setAbsoluteRangeDatePickerTarget, @@ -164,7 +164,7 @@ const EventsByDatasetComponent: React.FC = ({ filterQuery={filterQuery} headerChildren={headerContent} id={uniqueQueryId} - indexToAdd={indexToAdd} + indexNames={indexNames} setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget} setQuery={setQuery} showSpacer={showSpacer} diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap index c9c34682519e28..47d45ab740dcf2 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap @@ -192,8 +192,10 @@ exports[`Host Summary Component rendering it renders the default Host Summary 1` }, } } + docValueFields={Array []} endDate="2019-06-18T06:00:00.000Z" id="hostOverview" + indexNames={Array []} isLoadingAnomaliesData={false} loading={false} narrowDateRange={[MockFunction]} diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx index 6bd0390d014a37..69bd053d707b92 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx @@ -20,8 +20,10 @@ describe('Host Summary Component', () => { ( ({ anomaliesData, data, + docValueFields, endDate, id, isLoadingAnomaliesData, + indexNames, loading, narrowDateRange, startDate, @@ -91,7 +95,9 @@ export const HostOverview = React.memo( description: data.host != null && data.host.name && data.host.name.length ? ( ) : ( @@ -103,7 +109,9 @@ export const HostOverview = React.memo( description: data.host != null && data.host.name && data.host.name.length ? ( ) : ( @@ -111,7 +119,7 @@ export const HostOverview = React.memo( ), }, ], - [data] + [data, docValueFields, indexNames] ); const firstColumn = useMemo( () => diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.test.tsx index b932add7afc2c7..8f0e9a56254ec6 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.test.tsx @@ -27,7 +27,12 @@ jest.mock('../../../common/components/link_to'); const startDate = '2020-01-20T20:49:57.080Z'; const endDate = '2020-01-21T20:49:57.080Z'; - +const testProps = { + endDate, + indexNames: [], + setQuery: jest.fn(), + startDate, +}; const MOCKED_RESPONSE = { overviewHost: { auditbeatAuditd: 1, @@ -79,7 +84,7 @@ describe('OverviewHost', () => { test('it renders the expected widget title', () => { const wrapper = mount( - + ); @@ -92,7 +97,7 @@ describe('OverviewHost', () => { useHostOverviewMock.mockReturnValueOnce([true, { overviewHost: {} }]); const wrapper = mount( - + ); @@ -102,7 +107,7 @@ describe('OverviewHost', () => { test('it renders the expected event count in the subtitle after loading events', async () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx index 3f35d0abbaa856..f92f004bd2448b 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx @@ -22,11 +22,11 @@ import { InspectButtonContainer } from '../../../common/components/inspect'; import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { SecurityPageName } from '../../../app/types'; import { LinkButton } from '../../../common/components/links'; -import { Sourcerer } from '../../../common/components/sourcerer'; export interface OwnProps { startDate: GlobalTimeArgs['from']; endDate: GlobalTimeArgs['to']; + indexNames: string[]; filterQuery?: ESQuery | string; setQuery: GlobalTimeArgs['setQuery']; } @@ -37,6 +37,7 @@ export type OverviewHostProps = OwnProps; const OverviewHostComponent: React.FC = ({ endDate, filterQuery, + indexNames, startDate, setQuery, }) => { @@ -47,6 +48,7 @@ const OverviewHostComponent: React.FC = ({ const [loading, { overviewHost, id, inspect, refetch }] = useHostOverview({ endDate, filterQuery, + indexNames, startDate, }); @@ -109,10 +111,7 @@ const OverviewHostComponent: React.FC = ({ /> } > - <> - - {hostPageButton} - + <>{hostPageButton} { describe('rendering', () => { test('it renders the default OverviewHostStats', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); }); @@ -22,7 +22,7 @@ describe('Overview Host Stat Data', () => { test('it does NOT show loading indicator when loading is false', () => { const wrapper = mount( - + ); @@ -42,7 +42,7 @@ describe('Overview Host Stat Data', () => { test('it shows loading indicator when loading is true', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx index 92250ed3c549b7..ef595476d8a941 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx @@ -9,16 +9,18 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import styled from 'styled-components'; -import { OverviewHostData } from '../../../graphql/types'; +import { HostsOverviewStrategyResponse } from '../../../../common/search_strategy'; import { FormattedStat, StatGroup } from '../types'; import { StatValue } from '../stat_value'; interface OverviewHostProps { - data: OverviewHostData; + data: HostsOverviewStrategyResponse['overviewHost']; loading: boolean; } -export const getOverviewHostStats = (data: OverviewHostData): FormattedStat[] => [ +export const getOverviewHostStats = ( + data: HostsOverviewStrategyResponse['overviewHost'] +): FormattedStat[] => [ { count: data.auditbeatAuditd ?? 0, title: ( diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/mock.ts b/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/mock.ts index 63b3a484c1eaa9..986d02faac37a1 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/mock.ts +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/mock.ts @@ -4,25 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import { OverviewHostData } from '../../../graphql/types'; +import { HostsOverviewStrategyResponse } from '../../../../common/search_strategy'; -export const mockData: { OverviewHost: OverviewHostData } = { - OverviewHost: { - auditbeatAuditd: 73847, - auditbeatFIM: 107307, - auditbeatLogin: 60015, - auditbeatPackage: 2003, - auditbeatProcess: 1200, - auditbeatUser: 1979, - endgameDns: 39123, - endgameFile: 39456, - endgameImageLoad: 39789, - endgameNetwork: 39101112, - endgameProcess: 39131415, - endgameRegistry: 39161718, - endgameSecurity: 39202122, - filebeatSystemModule: 568, - winlogbeatSecurity: 195929, - winlogbeatMWSysmonOperational: 101070, - }, +export const mockData: HostsOverviewStrategyResponse['overviewHost'] = { + auditbeatAuditd: 73847, + auditbeatFIM: 107307, + auditbeatLogin: 60015, + auditbeatPackage: 2003, + auditbeatProcess: 1200, + auditbeatUser: 1979, + endgameDns: 39123, + endgameFile: 39456, + endgameImageLoad: 39789, + endgameNetwork: 39101112, + endgameProcess: 39131415, + endgameRegistry: 39161718, + endgameSecurity: 39202122, + filebeatSystemModule: 568, + winlogbeatSecurity: 195929, + winlogbeatMWSysmonOperational: 101070, }; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.test.tsx index f67287ea4b9e2d..c4c0b2e5e255e2 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.test.tsx @@ -43,6 +43,12 @@ jest.mock('../../../common/lib/kibana', () => { const startDate = '2020-01-20T20:49:57.080Z'; const endDate = '2020-01-21T20:49:57.080Z'; +const defaultProps = { + endDate, + startDate, + setQuery: jest.fn(), + indexNames: [], +}; const MOCKED_RESPONSE = { overviewNetwork: { @@ -88,7 +94,7 @@ describe('OverviewNetwork', () => { test('it renders the expected widget title', () => { const wrapper = mount( - + ); @@ -101,7 +107,7 @@ describe('OverviewNetwork', () => { useNetworkOverviewMock.mockReturnValueOnce([true, { overviewNetwork: {} }]); const wrapper = mount( - + ); @@ -111,7 +117,7 @@ describe('OverviewNetwork', () => { test('it renders the expected event count in the subtitle after loading events', async () => { const wrapper = mount( - + ); @@ -123,7 +129,7 @@ describe('OverviewNetwork', () => { it('it renders View Network', () => { const wrapper = mount( - + ); @@ -133,7 +139,7 @@ describe('OverviewNetwork', () => { it('when click on View Network we call navigateToApp to make sure to navigate to right page', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx index 089bed3c678087..178a752d1286f1 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx @@ -30,6 +30,7 @@ export interface OverviewNetworkProps { startDate: GlobalTimeArgs['from']; endDate: GlobalTimeArgs['to']; filterQuery?: ESQuery | string; + indexNames: string[]; setQuery: GlobalTimeArgs['setQuery']; } @@ -38,6 +39,7 @@ const OverviewNetworkStatsManage = manageQuery(OverviewNetworkStats); const OverviewNetworkComponent: React.FC = ({ endDate, filterQuery, + indexNames, startDate, setQuery, }) => { @@ -48,6 +50,7 @@ const OverviewNetworkComponent: React.FC = ({ const [loading, { overviewNetwork, id, inspect, refetch }] = useNetworkOverview({ endDate, filterQuery, + indexNames, startDate, }); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.test.tsx index 0add7c1a020472..2f801ae1f3623f 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.test.tsx @@ -14,9 +14,7 @@ import { TestProviders } from '../../../common/mock/test_providers'; describe('Overview Network Stat Data', () => { describe('rendering', () => { test('it renders the default OverviewNetworkStats', () => { - const wrapper = shallow( - - ); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); }); @@ -24,7 +22,7 @@ describe('Overview Network Stat Data', () => { test('it does NOT show loading indicator when loading is false', () => { const wrapper = mount( - + ); @@ -45,7 +43,7 @@ describe('Overview Network Stat Data', () => { test('it shows the loading indicator when loading is true', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx index d3e16af7115ac1..c6ad56b7243d42 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx @@ -9,16 +9,18 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import styled from 'styled-components'; -import { OverviewNetworkData } from '../../../graphql/types'; +import { NetworkOverviewStrategyResponse } from '../../../../common/search_strategy'; import { FormattedStat, StatGroup } from '../types'; import { StatValue } from '../stat_value'; interface OverviewNetworkProps { - data: OverviewNetworkData; + data: NetworkOverviewStrategyResponse['overviewNetwork']; loading: boolean; } -export const getOverviewNetworkStats = (data: OverviewNetworkData): FormattedStat[] => [ +export const getOverviewNetworkStats = ( + data: NetworkOverviewStrategyResponse['overviewNetwork'] +): FormattedStat[] => [ { count: data.auditbeatSocket ?? 0, title: ( diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/mock.ts b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/mock.ts index f55d6a1577ccd8..1eb337f1ea4549 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/mock.ts +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/mock.ts @@ -4,18 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { OverviewNetworkData } from '../../../graphql/types'; +import { NetworkOverviewStrategyResponse } from '../../../../common/search_strategy'; -export const mockData: { OverviewNetwork: OverviewNetworkData } = { - OverviewNetwork: { - auditbeatSocket: 12, - filebeatCisco: 999, - filebeatNetflow: 7777, - filebeatPanw: 66, - filebeatSuricata: 60015, - filebeatZeek: 2003, - packetbeatDNS: 10277307, - packetbeatFlow: 16, - packetbeatTLS: 3400000, - }, +export const mockData: NetworkOverviewStrategyResponse['overviewNetwork'] = { + auditbeatSocket: 12, + filebeatCisco: 999, + filebeatNetflow: 7777, + filebeatPanw: 66, + filebeatSuricata: 60015, + filebeatZeek: 2003, + packetbeatDNS: 10277307, + packetbeatFlow: 16, + packetbeatTLS: 3400000, }; diff --git a/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx index 446679ae26d9ec..8a0d2f4f162020 100644 --- a/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx @@ -33,7 +33,7 @@ describe('RecentCases', () => { wrapper.find(`[data-test-subj="no-cases-create-case"]`).first().simulate('click'); expect(navigateToApp).toHaveBeenCalledWith('securitySolution:case', { path: - "/create?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "/create?sourcerer=(default:!('apm-*-transaction*','auditbeat-*','endgame-*','filebeat-*','logs-*','packetbeat-*','winlogbeat-*'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", }); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.gql_query.ts b/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.gql_query.ts deleted file mode 100644 index 6f17bf6915aa45..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.gql_query.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const overviewHostQuery = gql` - query GetOverviewHostQuery( - $sourceId: ID! - $timerange: TimerangeInput! - $filterQuery: String - $defaultIndex: [String!]! - $inspect: Boolean! - ) { - source(id: $sourceId) { - id - OverviewHost(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) { - auditbeatAuditd - auditbeatFIM - auditbeatLogin - auditbeatPackage - auditbeatProcess - auditbeatUser - endgameDns - endgameFile - endgameImageLoad - endgameNetwork - endgameProcess - endgameRegistry - endgameSecurity - filebeatSystemModule - winlogbeatSecurity - winlogbeatMWSysmonOperational - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx b/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx index 75ab85fe0c4297..946cd33088a45a 100644 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx @@ -5,21 +5,18 @@ */ import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import deepEqual from 'fast-deep-equal'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { HostsQueries, HostOverviewRequestOptions, - HostOverviewStrategyResponse, + HostsOverviewStrategyResponse, } from '../../../../common/search_strategy/security_solution'; import { useKibana } from '../../../common/lib/kibana'; import { inputsModel } from '../../../common/store/inputs'; import { createFilter } from '../../../common/containers/helpers'; import { ESQuery } from '../../../../common/typed_json'; -import { useManageSource } from '../../../common/containers/sourcerer'; -import { SOURCERER_FEATURE_FLAG_ON } from '../../../common/containers/sourcerer/constants'; import { AbortError, isCompleteResponse, @@ -35,13 +32,14 @@ export interface HostOverviewArgs { id: string; inspect: InspectResponse; isInspected: boolean; - overviewHost: HostOverviewStrategyResponse['overviewHost']; + overviewHost: HostsOverviewStrategyResponse['overviewHost']; refetch: inputsModel.Refetch; } interface UseHostOverview { filterQuery?: ESQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -49,23 +47,16 @@ interface UseHostOverview { export const useHostOverview = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseHostOverview): [boolean, HostOverviewArgs] => { - const { data, notifications, uiSettings } = useKibana().services; - const { activeSourceGroupId, getManageSourceGroupById } = useManageSource(); - const { indexPatterns } = useMemo(() => getManageSourceGroupById(activeSourceGroupId), [ - getManageSourceGroupById, - activeSourceGroupId, - ]); - const uiDefaultIndexPatterns = uiSettings.get(DEFAULT_INDEX_KEY); - const defaultIndex = SOURCERER_FEATURE_FLAG_ON ? indexPatterns : uiDefaultIndexPatterns; - + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); const [loading, setLoading] = useState(false); const [overviewHostRequest, setHostRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: HostsQueries.overview, filterQuery: createFilter(filterQuery), timerange: { @@ -94,7 +85,7 @@ export const useHostOverview = ({ setLoading(true); const searchSubscription$ = data.search - .search(request, { + .search(request, { strategy: 'securitySolutionSearchStrategy', abortSignal: abortCtrl.current.signal, }) @@ -145,7 +136,7 @@ export const useHostOverview = ({ setHostRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -158,7 +149,7 @@ export const useHostOverview = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { overviewHostSearch(overviewHostRequest); diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.gql_query.ts b/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.gql_query.ts deleted file mode 100644 index d40ab900b91a76..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.gql_query.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const overviewNetworkQuery = gql` - query GetOverviewNetworkQuery( - $sourceId: ID! - $timerange: TimerangeInput! - $filterQuery: String - $defaultIndex: [String!]! - $inspect: Boolean! - ) { - source(id: $sourceId) { - id - OverviewNetwork( - timerange: $timerange - filterQuery: $filterQuery - defaultIndex: $defaultIndex - ) { - auditbeatSocket - filebeatCisco - filebeatNetflow - filebeatPanw - filebeatSuricata - filebeatZeek - packetbeatDNS - packetbeatFlow - packetbeatTLS - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx b/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx index ae1fe942d8403a..588fb1f08ef6f8 100644 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx @@ -8,7 +8,6 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import deepEqual from 'fast-deep-equal'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { NetworkQueries, NetworkOverviewRequestOptions, @@ -40,6 +39,7 @@ export interface NetworkOverviewArgs { interface UseNetworkOverview { filterQuery?: ESQuery | string; endDate: string; + indexNames: string[]; skip?: boolean; startDate: string; } @@ -47,16 +47,16 @@ interface UseNetworkOverview { export const useNetworkOverview = ({ filterQuery, endDate, + indexNames, skip = false, startDate, }: UseNetworkOverview): [boolean, NetworkOverviewArgs] => { - const { data, notifications, uiSettings } = useKibana().services; - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); const [loading, setLoading] = useState(false); const [overviewNetworkRequest, setNetworkRequest] = useState({ - defaultIndex, + defaultIndex: indexNames, factoryQueryType: NetworkQueries.overview, filterQuery: createFilter(filterQuery), timerange: { @@ -136,7 +136,7 @@ export const useNetworkOverview = ({ setNetworkRequest((prevRequest) => { const myRequest = { ...prevRequest, - defaultIndex, + defaultIndex: indexNames, filterQuery: createFilter(filterQuery), timerange: { interval: '12h', @@ -149,7 +149,7 @@ export const useNetworkOverview = ({ } return prevRequest; }); - }, [defaultIndex, endDate, filterQuery, skip, startDate]); + }, [indexNames, endDate, filterQuery, skip, startDate]); useEffect(() => { overviewNetworkSearch(overviewNetworkRequest); diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx index 74225c4e4f8232..222b9e008ddd77 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx @@ -10,16 +10,18 @@ import { MemoryRouter } from 'react-router-dom'; import '../../common/mock/match_media'; import { TestProviders } from '../../common/mock'; -import { useWithSource } from '../../common/containers/source'; import { useMessagesStorage, UseMessagesStorage, } from '../../common/containers/local_storage/use_messages_storage'; import { Overview } from './index'; import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled'; +import { useSourcererScope } from '../../common/containers/sourcerer'; +import { useFetchIndex } from '../../common/containers/source'; jest.mock('../../common/lib/kibana'); jest.mock('../../common/containers/source'); +jest.mock('../../common/containers/sourcerer'); jest.mock('../../common/containers/use_global_time', () => ({ useGlobalTime: jest.fn().mockReturnValue({ from: '2020-07-07T08:20:18.966Z', @@ -49,65 +51,29 @@ const endpointNoticeMessage = (hasMessageValue: boolean) => { clearAllMessages: () => undefined, }; }; - +const mockUseSourcererScope = useSourcererScope as jest.Mock; +const mockUseIngestEnabledCheck = useIngestEnabledCheck as jest.Mock; +const mockUseFetchIndex = useFetchIndex as jest.Mock; +const mockUseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; describe('Overview', () => { + beforeEach(() => { + mockUseFetchIndex.mockReturnValue([ + false, + { + indexExists: true, + }, + ]); + }); describe('rendering', () => { - describe('when no index is available', () => { - beforeEach(() => { - (useWithSource as jest.Mock).mockReturnValue({ - indicesExist: false, - }); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock< - UseMessagesStorage - >; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); - }); - - it('renders the Setup Instructions text', () => { - const wrapper = mount( - - - - - - ); - expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); - }); - - it('does not show Endpoint get ready button when ingest is not enabled', () => { - const wrapper = mount( - - - - - - ); - expect(wrapper.find('[data-test-subj="empty-page-endpoint-action"]').exists()).toBe(false); - }); - - it('shows Endpoint get ready button when ingest is enabled', () => { - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); - const wrapper = mount( - - - - - - ); - expect(wrapper.find('[data-test-subj="empty-page-endpoint-action"]').exists()).toBe(true); - }); - }); - - it('it DOES NOT render the Getting started text when an index is available', () => { - (useWithSource as jest.Mock).mockReturnValue({ + test('it DOES NOT render the Getting started text when an index is available', () => { + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: true, indexPattern: {}, }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: true }); const wrapper = mount( @@ -122,19 +88,20 @@ describe('Overview', () => { }); test('it DOES render the Endpoint banner when the endpoint index is NOT available AND storage is NOT set', () => { - (useWithSource as jest.Mock).mockReturnValueOnce({ + mockUseFetchIndex.mockReturnValue([ + false, + { + indexExists: false, + }, + ]); + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: true, indexPattern: {}, }); - (useWithSource as jest.Mock).mockReturnValueOnce({ - indicesExist: false, - indexPattern: {}, - }); - - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: true }); const wrapper = mount( @@ -149,19 +116,20 @@ describe('Overview', () => { }); test('it does NOT render the Endpoint banner when the endpoint index is NOT available but storage is set', () => { - (useWithSource as jest.Mock).mockReturnValueOnce({ + mockUseFetchIndex.mockReturnValue([ + false, + { + indexExists: false, + }, + ]); + mockUseSourcererScope.mockReturnValueOnce({ + selectedPatterns: [], indicesExist: true, indexPattern: {}, }); - (useWithSource as jest.Mock).mockReturnValueOnce({ - indicesExist: false, - indexPattern: {}, - }); - - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(true)); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(true)); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: true }); const wrapper = mount( @@ -176,14 +144,14 @@ describe('Overview', () => { }); test('it does NOT render the Endpoint banner when the endpoint index is available AND storage is set', () => { - (useWithSource as jest.Mock).mockReturnValue({ - indicesExist: true, + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], + indexExists: true, indexPattern: {}, }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(true)); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(true)); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: true }); const wrapper = mount( @@ -198,14 +166,14 @@ describe('Overview', () => { }); test('it does NOT render the Endpoint banner when an index IS available but storage is NOT set', () => { - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: true, indexPattern: {}, }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: true }); const wrapper = mount( @@ -214,19 +182,20 @@ describe('Overview', () => { ); + wrapper.update(); expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(false); wrapper.unmount(); }); test('it does NOT render the Endpoint banner when Ingest is NOT available', () => { - (useWithSource as jest.Mock).mockReturnValue({ + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], indicesExist: true, indexPattern: {}, }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(true)); - (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(true)); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: false }); const wrapper = mount( @@ -239,5 +208,50 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(false); wrapper.unmount(); }); + + describe('when no index is available', () => { + beforeEach(() => { + mockUseSourcererScope.mockReturnValue({ + selectedPatterns: [], + indicesExist: false, + }); + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: false }); + mockUseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); + }); + + it('renders the Setup Instructions text', () => { + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); + }); + + it('does not show Endpoint get ready button when ingest is not enabled', () => { + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page-endpoint-action"]').exists()).toBe(false); + }); + + it('shows Endpoint get ready button when ingest is enabled', () => { + mockUseIngestEnabledCheck.mockReturnValue({ allEnabled: true }); + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page-endpoint-action"]').exists()).toBe(true); + }); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx index 520fd6c4597055..5a3b4ec3846869 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx @@ -15,7 +15,7 @@ import { FiltersGlobal } from '../../common/components/filters_global'; import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; import { useGlobalTime } from '../../common/containers/use_global_time'; -import { useWithSource } from '../../common/containers/source'; +import { useFetchIndex } from '../../common/containers/source'; import { EventsByDataset } from '../components/events_by_dataset'; import { EventCounts } from '../components/event_counts'; @@ -30,6 +30,9 @@ import { EndpointNotice } from '../components/endpoint_notice'; import { useMessagesStorage } from '../../common/containers/local_storage/use_messages_storage'; import { ENDPOINT_METADATA_INDEX } from '../../../common/constants'; import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled'; +import { useSourcererScope } from '../../common/containers/sourcerer'; +import { Sourcerer } from '../../common/components/sourcerer'; +import { SourcererScopeName } from '../../common/store/sourcerer/model'; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; const NO_FILTERS: Filter[] = []; @@ -43,17 +46,13 @@ const OverviewComponent: React.FC = ({ query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, }) => { + const { from, deleteQuery, setQuery, to } = useGlobalTime(); + const { indicesExist, indexPattern, selectedPatterns } = useSourcererScope(); + const endpointMetadataIndex = useMemo(() => { return [ENDPOINT_METADATA_INDEX]; }, []); - - const { from, deleteQuery, setQuery, to } = useGlobalTime(); - const { indicesExist, indexPattern } = useWithSource(); - const { indicesExist: metadataIndexExists } = useWithSource( - 'default', - endpointMetadataIndex, - true - ); + const [, { indexExists: metadataIndexExists }] = useFetchIndex(endpointMetadataIndex, true); const { addMessage, hasMessage } = useMessagesStorage(); const hasDismissEndpointNoticeMessage: boolean = useMemo( () => hasMessage('management', 'dismissEndpointNotice'), @@ -81,6 +80,7 @@ const OverviewComponent: React.FC = ({ )} + @@ -107,6 +107,7 @@ const OverviewComponent: React.FC = ({ filters={filters} from={from} indexPattern={indexPattern} + indexNames={selectedPatterns} query={query} setQuery={setQuery} to={to} @@ -119,6 +120,7 @@ const OverviewComponent: React.FC = ({ filters={filters} from={from} indexPattern={indexPattern} + indexNames={selectedPatterns} query={query} setQuery={setQuery} to={to} @@ -129,6 +131,7 @@ const OverviewComponent: React.FC = ({ { - const docLinks = useKibana().services.docLinks; - + const { docLinks, http } = useKibana().services; + const basePath = http.basePath.get(); return ( @@ -39,7 +39,7 @@ export const Summary = React.memo(() => { ), data: ( - + { private kibanaVersion: string; @@ -385,15 +390,32 @@ export class Plugin implements IPlugin( + { indices: defaultIndicesName, onlyCheckIfIndicesExist: false }, + { + strategy: 'securitySolutionIndexFields', + } + ) + .toPromise(), + ]); - const { - detectionsSubPlugin, - hostsSubPlugin, - networkSubPlugin, - timelinesSubPlugin, - managementSubPlugin, - } = await this.downloadSubPlugins(); const { apolloClient } = composeLibs(coreStart); const appLibs: AppObservableLibs = { apolloClient, kibana: coreStart }; const libs$ = new BehaviorSubject(appLibs); @@ -417,12 +439,18 @@ export class Plugin implements IPlugin` &.euiBreadcrumbs { background-color: ${(props) => props.background}; @@ -38,20 +50,32 @@ export const ThemedBreadcrumbs = styled(EuiBreadcrumbs)<{ background: string; te } `; +/** + * Used in the links to nodes on the node list panel. + */ export const StyledButtonTextContainer = styled.div` align-items: center; display: flex; flex-direction: row; `; +/** + * Used in the node list panel to call out the event that is represented by the databaseDocumentID. + */ export const StyledAnalyzedEvent = styled.div` color: ${(props) => props.color}; font-size: 10.5px; font-weight: 700; `; +/** + * Used to style the node name in the node list panel view. + */ export const StyledLabelTitle = styled.div``; +/** + * Used by the node list view. Wraps the title of the node and the 'Analyzed event' marker. + */ export const StyledLabelContainer = styled.div` display: inline-block; flex: 3; diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/button/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/button/index.tsx index c0a59fd07e348f..954ae0b6a0d40e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/button/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/button/index.tsx @@ -10,12 +10,13 @@ import { rgba } from 'polished'; import React, { useMemo } from 'react'; import styled from 'styled-components'; -import { useWithSource } from '../../../../common/containers/source'; import { IS_DRAGGING_CLASS_NAME } from '../../../../common/components/drag_and_drop/helpers'; import { DataProvider } from '../../timeline/data_providers/data_provider'; import { flattenIntoAndGroups } from '../../timeline/data_providers/helpers'; import { DataProviders } from '../../timeline/data_providers'; import * as i18n from './translations'; +import { useSourcererScope } from '../../../../common/containers/sourcerer'; +import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; export const FLYOUT_BUTTON_CLASS_NAME = 'timeline-flyout-button'; @@ -85,7 +86,7 @@ interface FlyoutButtonProps { export const FlyoutButton = React.memo( ({ onOpen, show, dataProviders, timelineId }) => { const badgeCount = useMemo(() => getBadgeCount(dataProviders), [dataProviders]); - const { browserFields } = useWithSource(); + const { browserFields } = useSourcererScope(SourcererScopeName.timeline); if (!show) { return null; diff --git a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.test.tsx index fe0f0c8f8b91f5..3814bc01bd9b1f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.test.tsx @@ -33,33 +33,33 @@ describe('useTimelineManager', () => { expect(isStringifiedComparisonEqual(uninitializedTimeline, timelineDefaults)).toBeTruthy(); }); }); - - it('getIndexToAddById', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useTimelineManager() - ); - await waitForNextUpdate(); - const data = result.current.getIndexToAddById(testId); - expect(data).toEqual(timelineDefaults.indexToAdd); - }); - }); - - it('setIndexToAdd', async () => { - await act(async () => { - const indexToAddArgs = { id: testId, indexToAdd: ['example'] }; - const { result, waitForNextUpdate } = renderHook(() => - useTimelineManager() - ); - await waitForNextUpdate(); - result.current.initializeTimeline({ - id: testId, - }); - result.current.setIndexToAdd(indexToAddArgs); - const data = result.current.getIndexToAddById(testId); - expect(data).toEqual(indexToAddArgs.indexToAdd); - }); - }); + // TO DO sourcerer + // it('getIndexToAddById', async () => { + // await act(async () => { + // const { result, waitForNextUpdate } = renderHook(() => + // useTimelineManager() + // ); + // await waitForNextUpdate(); + // const data = result.current.getIndexToAddById(testId); + // expect(data).toEqual(timelineDefaults.indexToAdd); + // }); + // }); + // + // it('setIndexToAdd', async () => { + // await act(async () => { + // const indexToAddArgs = { id: testId, indexToAdd: ['example'] }; + // const { result, waitForNextUpdate } = renderHook(() => + // useTimelineManager() + // ); + // await waitForNextUpdate(); + // result.current.initializeTimeline({ + // id: testId, + // }); + // result.current.setIndexToAdd(indexToAddArgs); + // const data = result.current.getIndexToAddById(testId); + // expect(data).toEqual(indexToAddArgs.indexToAdd); + // }); + // }); it('setIsTimelineLoading', async () => { await act(async () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx index f82158fe65c11b..4e1e877ec5b882 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx @@ -20,7 +20,6 @@ interface ManageTimelineInit { filterManager?: FilterManager; footerText?: string; id: string; - indexToAdd?: string[] | null; loadingText?: string; selectAll?: boolean; queryFields?: string[]; @@ -34,7 +33,6 @@ interface ManageTimeline { filterManager?: FilterManager; footerText: string; id: string; - indexToAdd: string[] | null; isLoading: boolean; loadingText: string; queryFields: string[]; @@ -58,11 +56,6 @@ type ActionManageTimeline = id: string; payload: boolean; } - | { - type: 'SET_INDEX_TO_ADD'; - id: string; - payload: string[]; - } | { type: 'SET_SELECT_ALL'; id: string; @@ -70,7 +63,6 @@ type ActionManageTimeline = }; export const getTimelineDefaults = (id: string) => ({ - indexToAdd: null, defaultModel: timelineDefaultModel, loadingText: i18n.LOADING_EVENTS, footerText: i18nF.TOTAL_COUNT_OF_EVENTS, @@ -96,14 +88,6 @@ const reducerManageTimeline = ( ...action.payload, }, } as ManageTimelineById; - case 'SET_INDEX_TO_ADD': - return { - ...state, - [action.id]: { - ...state[action.id], - indexToAdd: action.payload, - }, - } as ManageTimelineById; case 'SET_SELECT_ALL': return { ...state, @@ -127,12 +111,10 @@ const reducerManageTimeline = ( }; export interface UseTimelineManager { - getIndexToAddById: (id: string) => string[] | null; getManageTimelineById: (id: string) => ManageTimeline; getTimelineFilterManager: (id: string) => FilterManager | undefined; initializeTimeline: (newTimeline: ManageTimelineInit) => void; isManagedTimeline: (id: string) => boolean; - setIndexToAdd: (indexToAddArgs: { id: string; indexToAdd: string[] }) => void; setIsTimelineLoading: (isLoadingArgs: { id: string; isLoading: boolean }) => void; setSelectAll: (selectAllArgs: { id: string; selectAll: boolean }) => void; } @@ -163,14 +145,6 @@ export const useTimelineManager = ( [] ); - const setIndexToAdd = useCallback(({ id, indexToAdd }: { id: string; indexToAdd: string[] }) => { - dispatch({ - type: 'SET_INDEX_TO_ADD', - id, - payload: indexToAdd, - }); - }, []); - const setSelectAll = useCallback(({ id, selectAll }: { id: string; selectAll: boolean }) => { dispatch({ type: 'SET_SELECT_ALL', @@ -193,36 +167,23 @@ export const useTimelineManager = ( }, [initializeTimeline, state] ); - const getIndexToAddById = useCallback( - (id: string): string[] | null => { - if (state[id] != null) { - return state[id].indexToAdd; - } - return getTimelineDefaults(id).indexToAdd; - }, - [state] - ); const isManagedTimeline = useCallback((id: string): boolean => state[id] != null, [state]); return { - getIndexToAddById, getManageTimelineById, getTimelineFilterManager, initializeTimeline, isManagedTimeline, - setIndexToAdd, setIsTimelineLoading, setSelectAll, }; }; const init = { - getIndexToAddById: (id: string) => null, getManageTimelineById: (id: string) => getTimelineDefaults(id), getTimelineFilterManager: () => undefined, initializeTimeline: () => noop, isManagedTimeline: () => false, - setIndexToAdd: () => undefined, setIsTimelineLoading: () => noop, setSelectAll: () => noop, }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts index ed44fc14e3efae..c89114ec771387 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts @@ -273,6 +273,7 @@ describe('helpers', () => { highlightedDropAndProviderId: '', historyIds: [], id: 'savedObject-1', + indexNames: [], isFavorite: false, isLive: false, isSelectAllChecked: false, @@ -371,6 +372,7 @@ describe('helpers', () => { highlightedDropAndProviderId: '', historyIds: [], id: 'savedObject-1', + indexNames: [], isFavorite: false, isLive: false, isSelectAllChecked: false, @@ -469,6 +471,7 @@ describe('helpers', () => { highlightedDropAndProviderId: '', historyIds: [], id: 'savedObject-1', + indexNames: [], isFavorite: false, isLive: false, isSelectAllChecked: false, @@ -564,6 +567,7 @@ describe('helpers', () => { filters: [], highlightedDropAndProviderId: '', historyIds: [], + indexNames: [], id: 'savedObject-1', isFavorite: false, isLive: false, @@ -699,6 +703,7 @@ describe('helpers', () => { filters: [], highlightedDropAndProviderId: '', historyIds: [], + indexNames: [], isFavorite: false, isLive: false, isSelectAllChecked: false, @@ -865,6 +870,7 @@ describe('helpers', () => { ], highlightedDropAndProviderId: '', historyIds: [], + indexNames: [], isFavorite: false, isLive: false, isSelectAllChecked: false, diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts index b6b6148340a4a9..c89740f667b29b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts @@ -56,6 +56,8 @@ import { OpenTimelineResult, UpdateTimeline, DispatchUpdateTimeline } from './ty import { createNote } from '../notes/helpers'; import { IS_OPERATOR } from '../timeline/data_providers/data_provider'; import { normalizeTimeRange } from '../../../common/components/url_state/normalize_time_range'; +import { sourcererActions } from '../../../common/store/sourcerer'; +import { SourcererScopeName } from '../../../common/store/sourcerer/model'; export const OPEN_TIMELINE_CLASS_NAME = 'open-timeline'; @@ -375,6 +377,13 @@ export const dispatchUpdateTimeline = (dispatch: Dispatch): DispatchUpdateTimeli to, ruleNote, }: UpdateTimeline): (() => void) => () => { + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: SourcererScopeName.timeline, + selectedPatterns: timeline.indexNames, + eventType: timeline.eventType, + }) + ); dispatch(dispatchSetTimelineRangeDatePicker({ from, to })); dispatch(dispatchAddTimeline({ id, timeline, savedTimeline: duplicate })); if ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx index f681043a9047d9..dc824a8eb6272d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx @@ -5,12 +5,12 @@ */ import ApolloClient from 'apollo-client'; -import React, { useEffect, useState, useCallback } from 'react'; -import { connect, ConnectedProps } from 'react-redux'; +import React, { useEffect, useState, useCallback, useMemo } from 'react'; +import { connect, ConnectedProps, shallowEqual, useSelector } from 'react-redux'; import { Dispatch } from 'redux'; import { DeleteTimelineMutation, SortFieldTimeline, Direction } from '../../../graphql/types'; -import { State } from '../../../common/store'; +import { sourcererSelectors, State } from '../../../common/store'; import { TimelineId } from '../../../../common/types/timeline'; import { ColumnHeaderOptions, TimelineModel } from '../../../timelines/store/timeline/model'; import { timelineSelectors } from '../../../timelines/store/timeline'; @@ -110,6 +110,15 @@ export const StatefulOpenTimelineComponent = React.memo( /** The requested field to sort on */ const [sortField, setSortField] = useState(DEFAULT_SORT_FIELD); + const existingIndexNamesSelector = useMemo( + () => sourcererSelectors.getAllExistingIndexNamesSelector(), + [] + ); + const existingIndexNames = useSelector( + existingIndexNamesSelector, + shallowEqual + ); + const { customTemplateTimelineCount, defaultTimelineCount, @@ -193,7 +202,12 @@ export const StatefulOpenTimelineComponent = React.memo( const deleteTimelines: DeleteTimelines = useCallback( async (timelineIds: string[]) => { if (timelineIds.includes(timeline.savedObjectId || '')) { - createNewTimeline({ id: TimelineId.active, columns: defaultHeaders, show: false }); + createNewTimeline({ + id: TimelineId.active, + columns: defaultHeaders, + indexNames: existingIndexNames, + show: false, + }); } await apolloClient.mutate< @@ -206,7 +220,7 @@ export const StatefulOpenTimelineComponent = React.memo( }); refetch(); }, - [apolloClient, createNewTimeline, refetch, timeline] + [apolloClient, createNewTimeline, existingIndexNames, refetch, timeline] ); const onDeleteOneTimeline: OnDeleteOneTimeline = useCallback( @@ -382,12 +396,14 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ createNewTimeline: ({ id, columns, + indexNames, show, }: { id: string; columns: ColumnHeaderOptions[]; + indexNames: string[]; show?: boolean; - }) => dispatch(dispatchCreateNewTimeline({ id, columns, show })), + }) => dispatch(dispatchCreateNewTimeline({ id, columns, indexNames, show })), updateIsLoading: ({ id, isLoading }: { id: string; isLoading: boolean }) => dispatch(dispatchUpdateIsLoading({ id, isLoading })), updateTimeline: dispatchUpdateTimeline(dispatch), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap index d76ddace40a5a4..18a648f2abfaab 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap @@ -806,9 +806,15 @@ In other use cases the message field can be used to concatenate different values } docValueFields={Array []} end="2018-03-24T03:33:52.253Z" - eventType="raw" filters={Array []} - id="foo" + id="test" + indexNames={ + Array [ + "filebeat-*", + "auditbeat-*", + "packetbeat-*", + ] + } indexPattern={ Object { "fields": Array [ @@ -900,9 +906,7 @@ In other use cases the message field can be used to concatenate different values "title": "filebeat-*,auditbeat-*,packetbeat-*", } } - indexToAdd={Array []} isLive={false} - isLoadingSource={false} isSaving={false} itemsPerPage={5} itemsPerPageOptions={ @@ -914,7 +918,7 @@ In other use cases the message field can be used to concatenate different values } kqlMode="search" kqlQueryExpression="" - loadingIndexName={false} + loadingSourcerer={false} onChangeItemsPerPage={[MockFunction]} onClose={[MockFunction]} onDataProviderEdited={[MockFunction]} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx index 824a37f72ba59c..cf9fbfaf19326d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/helpers.tsx @@ -11,12 +11,15 @@ import { useDispatch } from 'react-redux'; import { Ecs } from '../../../../../common/ecs'; import { TimelineItem, TimelineNonEcsData } from '../../../../../common/search_strategy'; import { updateTimelineGraphEventId } from '../../../store/timeline/actions'; -import { EventType } from '../../../store/timeline/model'; +import { + TimelineEventsType, + TimelineTypeLiteral, + TimelineType, +} from '../../../../../common/types/timeline'; import { OnPinEvent, OnUnPinEvent } from '../events'; import { ActionIconItem } from './actions/action_icon_item'; import * as i18n from './translations'; -import { TimelineTypeLiteral, TimelineType } from '../../../../../common/types/timeline'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const omitTypenameAndEmpty = (k: string, v: any): any | undefined => @@ -101,7 +104,7 @@ export const getEventIdToDataMapping = ( }, {}); /** Return eventType raw or signal */ -export const getEventType = (event: Ecs): Omit => { +export const getEventType = (event: Ecs): Omit => { if (!isEmpty(event.signal?.rule?.id)) { return 'signal'; } diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx index 58c87c086df6e2..fc0bcb134158cb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx @@ -10,7 +10,7 @@ import { inputsModel } from '../../../../common/store'; import { BrowserFields, DocValueFields } from '../../../../common/containers/source'; import { TimelineItem, TimelineNonEcsData } from '../../../../../common/search_strategy'; import { Note } from '../../../../common/lib/note'; -import { ColumnHeaderOptions, EventType } from '../../../../timelines/store/timeline/model'; +import { ColumnHeaderOptions } from '../../../../timelines/store/timeline/model'; import { AddNoteToEvent, UpdateNote } from '../../notes/helpers'; import { OnColumnRemoved, @@ -31,7 +31,7 @@ import { RowRenderer } from './renderers/row_renderer'; import { Sort } from './sort'; import { GraphOverlay } from '../../graph_overlay'; import { DEFAULT_ICON_BUTTON_WIDTH } from '../helpers'; -import { TimelineId, TimelineType } from '../../../../../common/types/timeline'; +import { TimelineEventsType, TimelineId, TimelineType } from '../../../../../common/types/timeline'; export interface BodyProps { addNoteToEvent: AddNoteToEvent; @@ -45,7 +45,7 @@ export interface BodyProps { isEventViewer?: boolean; isSelectAllChecked: boolean; eventIdToNoteIds: Readonly>; - eventType?: EventType; + eventType?: TimelineEventsType; loadingEventIds: Readonly; onColumnRemoved: OnColumnRemoved; onColumnResized: OnColumnResized; @@ -68,7 +68,7 @@ export interface BodyProps { updateNote: UpdateNote; } -export const hasAdditionalActions = (id: string, eventType?: EventType): boolean => +export const hasAdditionalActions = (id: string, eventType?: TimelineEventsType): boolean => id === TimelineId.detectionsPage || id === TimelineId.detectionsRulesDetailsPage || ((id === TimelineId.active && eventType && ['all', 'signal', 'alert'].includes(eventType)) ?? diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.test.tsx index 61b4c2b23c2673..d8a9f7528ddae8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.test.tsx @@ -112,7 +112,7 @@ describe('helpers', () => { }) ).toEqual({ updatedDestinationGroup: [sourceGroup[moveProviderFromSourceIndex]], - updatedSourceGroup: sourceGroup.filter((_, i) => i !== moveProviderFromSourceIndex), + updatedSourcererScope: sourceGroup.filter((_, i) => i !== moveProviderFromSourceIndex), }); }) ); @@ -138,7 +138,7 @@ describe('helpers', () => { : [...acc, sourceGroup[moveProviderFromSourceIndex], p], [] ), - updatedSourceGroup: sourceGroup.filter((_, i) => i !== moveProviderFromSourceIndex), + updatedSourcererScope: sourceGroup.filter((_, i) => i !== moveProviderFromSourceIndex), }); }) ) @@ -171,7 +171,7 @@ describe('helpers', () => { p.id !== sourceGroup[moveProviderFromSourceIndex].id || i === moveProviderToDestinationIndex ), - updatedSourceGroup: sourceGroup.filter((_, i) => i !== moveProviderFromSourceIndex), + updatedSourcererScope: sourceGroup.filter((_, i) => i !== moveProviderFromSourceIndex), }); }) ) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.tsx index 923ef86c0bbc0b..00c7f0705f3ce1 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/helpers.tsx @@ -42,7 +42,7 @@ export const move = ({ sourceGroup: DataProvidersAnd[]; }): { updatedDestinationGroup: DataProvidersAnd[]; - updatedSourceGroup: DataProvidersAnd[]; + updatedSourcererScope: DataProvidersAnd[]; } => { const sourceClone = [...sourceGroup]; const destinationClone = [...destinationGroup]; @@ -56,7 +56,7 @@ export const move = ({ return { updatedDestinationGroup: deDuplicatedDestinationGroup, - updatedSourceGroup: sourceClone, + updatedSourcererScope: sourceClone, }; }; @@ -169,7 +169,7 @@ export const moveProvidersBetweenGroups = ({ const moveProviderFromSourceIndex = source.index; const moveProviderToDestinationIndex = destination.index; - const { updatedDestinationGroup, updatedSourceGroup } = move({ + const { updatedDestinationGroup, updatedSourcererScope } = move({ destinationGroup, moveProviderFromSourceIndex, moveProviderToDestinationIndex, @@ -180,7 +180,7 @@ export const moveProvidersBetweenGroups = ({ (acc, group, i) => [ ...acc, i === sourceGroupIndex - ? [...updatedSourceGroup] + ? [...updatedSourcererScope] : i === destinationGroupIndex ? [...updatedDestinationGroup] : [...group], diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx index f1bfdd5d33606d..d2737de7e75dcf 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx @@ -6,49 +6,32 @@ import { mount } from 'enzyme'; import React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; -import { act } from 'react-dom/test-utils'; import useResizeObserver from 'use-resize-observer/polyfilled'; import '../../../common/mock/match_media'; +import { mockBrowserFields, mockDocValueFields } from '../../../common/containers/source/mock'; + import { - useSignalIndex, - ReturnSignalIndex, -} from '../../../detections/containers/detection_engine/alerts/use_signal_index'; -import { mocksSource } from '../../../common/containers/source/mock'; -// we don't have the types for waitFor just yet, so using "as waitFor" until when we do -import { wait as waitFor } from '@testing-library/react'; -import { defaultHeaders, mockTimelineData, TestProviders } from '../../../common/mock'; -import { Direction } from '../../../graphql/types'; -import { timelineActions } from '../../store/timeline'; + mockIndexNames, + mockIndexPattern, + mockTimelineData, + TestProviders, +} from '../../../common/mock'; -import { Sort } from './body/sort'; -import { mockDataProviders } from './data_providers/mock/mock_data_providers'; -import { StatefulTimeline, Props as StatefulTimelineProps } from './index'; -import { Timeline } from './timeline'; -import { TimelineType, TimelineStatus } from '../../../../common/types/timeline'; +import { StatefulTimeline, OwnProps as StatefulTimelineOwnProps } from './index'; import { useTimelineEvents } from '../../containers/index'; jest.mock('../../containers/index', () => ({ useTimelineEvents: jest.fn(), })); -jest.mock('../../../common/lib/kibana', () => { - const originalModule = jest.requireActual('../../../common/lib/kibana'); - return { - ...originalModule, - useGetUserSavedObjectPermissions: jest.fn(), - }; -}); - +jest.mock('../../../common/lib/kibana'); jest.mock('../../../common/components/url_state/normalize_time_range.ts'); const mockUseResizeObserver: jest.Mock = useResizeObserver as jest.Mock; jest.mock('use-resize-observer/polyfilled'); mockUseResizeObserver.mockImplementation(() => ({})); -const mockUseSignalIndex: jest.Mock = useSignalIndex as jest.Mock; -jest.mock('../../../detections/containers/detection_engine/alerts/use_signal_index'); jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -58,105 +41,37 @@ jest.mock('react-router-dom', () => { }; }); jest.mock('../flyout/header_with_close_button'); +jest.mock('../../../common/containers/sourcerer', () => { + const originalModule = jest.requireActual('../../../common/containers/sourcerer'); + + return { + ...originalModule, + useSourcererScope: jest.fn().mockReturnValue({ + browserFields: mockBrowserFields, + docValueFields: mockDocValueFields, + loading: false, + indexPattern: mockIndexPattern, + selectedPatterns: mockIndexNames, + }), + }; +}); describe('StatefulTimeline', () => { - let props = {} as StatefulTimelineProps; - const sort: Sort = { - columnId: '@timestamp', - sortDirection: Direction.desc, + const props: StatefulTimelineOwnProps = { + id: 'id', + onClose: jest.fn(), + usersViewing: [], }; - const startDate = '2018-03-23T18:49:23.132Z'; - const endDate = '2018-03-24T03:33:52.253Z'; - - const mocks = mocksSource; beforeEach(() => { (useTimelineEvents as jest.Mock).mockReturnValue([false, { events: mockTimelineData }]); - props = { - addProvider: timelineActions.addProvider, - columns: defaultHeaders, - createTimeline: timelineActions.createTimeline, - dataProviders: mockDataProviders, - eventType: 'raw', - end: endDate, - filters: [], - graphEventId: undefined, - id: 'foo', - isLive: false, - isSaving: false, - isTimelineExists: false, - itemsPerPage: 5, - itemsPerPageOptions: [5, 10, 20], - kqlMode: 'search', - kqlQueryExpression: '', - onClose: jest.fn(), - onDataProviderEdited: timelineActions.dataProviderEdited, - removeColumn: timelineActions.removeColumn, - removeProvider: timelineActions.removeProvider, - show: true, - showCallOutUnauthorizedMsg: false, - sort, - start: startDate, - status: TimelineStatus.active, - timelineType: TimelineType.default, - updateColumns: timelineActions.updateColumns, - updateDataProviderEnabled: timelineActions.updateDataProviderEnabled, - updateDataProviderExcluded: timelineActions.updateDataProviderExcluded, - updateDataProviderKqlQuery: timelineActions.updateDataProviderKqlQuery, - updateDataProviderType: timelineActions.updateDataProviderType, - updateHighlightedDropAndProviderId: timelineActions.updateHighlightedDropAndProviderId, - updateItemsPerPage: timelineActions.updateItemsPerPage, - updateItemsPerPageOptions: timelineActions.updateItemsPerPageOptions, - updateSort: timelineActions.updateSort, - upsertColumn: timelineActions.upsertColumn, - usersViewing: ['elastic'], - }; }); - describe('indexToAdd', () => { - test('Make sure that indexToAdd return an unknown index if signalIndex does not exist', async () => { - mockUseSignalIndex.mockImplementation(() => ({ - loading: false, - signalIndexExists: false, - signalIndexName: undefined, - })); - const wrapper = mount( - - - - - - ); - await act(async () => { - await waitFor(() => { - wrapper.update(); - const timeline = wrapper.find(Timeline); - expect(timeline.props().indexToAdd).toEqual([ - 'no-alert-index-049FC71A-4C2C-446F-9901-37XMC5024C51', - ]); - }); - }); - }); - - test('Make sure that indexToAdd return siem signal index if signalIndex exist', async () => { - mockUseSignalIndex.mockImplementation(() => ({ - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-siem-signals-index', - })); - const wrapper = mount( - - - - - - ); - await act(async () => { - await waitFor(() => { - wrapper.update(); - const timeline = wrapper.find(Timeline); - expect(timeline.props().indexToAdd).toEqual(['mock-siem-signals-index']); - }); - }); - }); + test('renders ', () => { + const wrapper = mount( + + + + ); + expect(wrapper.find('[data-test-subj="timeline"]')).toBeTruthy(); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx index c170c93ee60832..ccdb0793bc03f0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx @@ -5,13 +5,10 @@ */ import { isEmpty } from 'lodash/fp'; -import React, { useEffect, useCallback, useMemo } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import deepEqual from 'fast-deep-equal'; -import { NO_ALERT_INDEX } from '../../../../common/constants'; -import { useWithSource } from '../../../common/containers/source'; -import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index'; import { inputsModel, inputsSelectors, State } from '../../../common/store'; import { timelineActions, timelineSelectors } from '../../store/timeline'; import { ColumnHeaderOptions, TimelineModel } from '../../../timelines/store/timeline/model'; @@ -26,6 +23,8 @@ import { OnToggleDataProviderType, } from './events'; import { Timeline } from './timeline'; +import { useSourcererScope } from '../../../common/containers/sourcerer'; +import { SourcererScopeName } from '../../../common/store/sourcerer/model'; export interface OwnProps { id: string; @@ -40,7 +39,6 @@ const StatefulTimelineComponent = React.memo( columns, createTimeline, dataProviders, - eventType, end, filters, graphEventId, @@ -69,19 +67,13 @@ const StatefulTimelineComponent = React.memo( upsertColumn, usersViewing, }) => { - const { loading, signalIndexExists, signalIndexName } = useSignalIndex(); - - const indexToAdd = useMemo(() => { - if ( - eventType && - signalIndexExists && - signalIndexName != null && - ['signal', 'alert', 'all'].includes(eventType) - ) { - return [signalIndexName]; - } - return [NO_ALERT_INDEX]; // Following index does not exist so we won't show any events; - }, [eventType, signalIndexExists, signalIndexName]); + const { + browserFields, + docValueFields, + loading, + indexPattern, + selectedPatterns, + } = useSourcererScope(SourcererScopeName.timeline); const onDataProviderRemoved: OnDataProviderRemoved = useCallback( (providerId: string, andProviderId?: string) => @@ -160,22 +152,16 @@ const StatefulTimelineComponent = React.memo( }); } }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [columns, id] + [columns, id, removeColumn, upsertColumn] ); useEffect(() => { if (createTimeline != null && !isTimelineExists) { - createTimeline({ id, columns: defaultHeaders, show: false }); + createTimeline({ id, columns: defaultHeaders, indexNames: selectedPatterns, show: false }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const { docValueFields, indexPattern, browserFields, loading: isLoadingSource } = useWithSource( - 'default', - indexToAdd - ); - return ( ( dataProviders={dataProviders!} docValueFields={docValueFields} end={end} - eventType={eventType} filters={filters} graphEventId={graphEventId} id={id} indexPattern={indexPattern} - indexToAdd={indexToAdd} + indexNames={selectedPatterns} isLive={isLive} - isLoadingSource={isLoadingSource} isSaving={isSaving} itemsPerPage={itemsPerPage!} itemsPerPageOptions={itemsPerPageOptions!} kqlMode={kqlMode} kqlQueryExpression={kqlQueryExpression} - loadingIndexName={loading} + loadingSourcerer={loading} onChangeItemsPerPage={onChangeItemsPerPage} onClose={onClose} onDataProviderEdited={onDataProviderEditedLocal} @@ -215,10 +199,8 @@ const StatefulTimelineComponent = React.memo( /> ); }, - // eslint-disable-next-line complexity (prevProps, nextProps) => { return ( - prevProps.eventType === nextProps.eventType && prevProps.end === nextProps.end && prevProps.graphEventId === nextProps.graphEventId && prevProps.id === nextProps.id && diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.test.tsx index 5b3bc72fc37ca3..7da3cf940da50f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.test.tsx @@ -93,15 +93,18 @@ describe('useCreateTimelineButton', () => { wrapper.find('[data-test-subj="timeline-new"]').first().simulate('click'); expect(mockDispatch.mock.calls[0][0].type).toEqual( - 'x-pack/security_solution/local/timeline/CREATE_TIMELINE' + 'x-pack/security_solution/local/sourcerer/SET_SELECTED_INDEX_PATTERNS' ); expect(mockDispatch.mock.calls[1][0].type).toEqual( - 'x-pack/security_solution/local/inputs/ADD_GLOBAL_LINK_TO' + 'x-pack/security_solution/local/timeline/CREATE_TIMELINE' ); expect(mockDispatch.mock.calls[2][0].type).toEqual( - 'x-pack/security_solution/local/inputs/ADD_TIMELINE_LINK_TO' + 'x-pack/security_solution/local/inputs/ADD_GLOBAL_LINK_TO' ); expect(mockDispatch.mock.calls[3][0].type).toEqual( + 'x-pack/security_solution/local/inputs/ADD_TIMELINE_LINK_TO' + ); + expect(mockDispatch.mock.calls[4][0].type).toEqual( 'x-pack/security_solution/local/inputs/SET_RELATIVE_RANGE_DATE_PICKER' ); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx index 97f3b1df011ffd..3919ee21b2a907 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx @@ -3,8 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import React, { useCallback, useMemo } from 'react'; +import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { EuiButton, EuiButtonEmpty } from '@elastic/eui'; import { defaultHeaders } from '../body/column_headers/default_headers'; import { timelineActions } from '../../../store/timeline'; @@ -15,6 +15,9 @@ import { TimelineTypeLiteral, } from '../../../../../common/types/timeline'; import { inputsActions, inputsSelectors } from '../../../../common/store/inputs'; +import { sourcererActions, sourcererSelectors } from '../../../../common/store/sourcerer'; +import { State } from '../../../../common/store'; +import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; export const useCreateTimelineButton = ({ timelineId, @@ -26,6 +29,11 @@ export const useCreateTimelineButton = ({ closeGearMenu?: () => void; }) => { const dispatch = useDispatch(); + const existingIndexNamesSelector = useMemo( + () => sourcererSelectors.getAllExistingIndexNamesSelector(), + [] + ); + const existingIndexNames = useSelector(existingIndexNamesSelector, shallowEqual); const { timelineFullScreen, setTimelineFullScreen } = useFullScreen(); const globalTimeRange = useSelector(inputsSelectors.globalTimeRangeSelector); const createTimeline = useCallback( @@ -33,12 +41,19 @@ export const useCreateTimelineButton = ({ if (id === TimelineId.active && timelineFullScreen) { setTimelineFullScreen(false); } + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: SourcererScopeName.timeline, + selectedPatterns: existingIndexNames, + }) + ); dispatch( timelineActions.createTimeline({ id, columns: defaultHeaders, show, timelineType, + indexNames: existingIndexNames, }) ); dispatch(inputsActions.addGlobalLinkTo({ linkToId: 'timeline' })); @@ -59,7 +74,14 @@ export const useCreateTimelineButton = ({ ); } }, - [dispatch, globalTimeRange, setTimelineFullScreen, timelineFullScreen, timelineType] + [ + existingIndexNames, + dispatch, + globalTimeRange, + setTimelineFullScreen, + timelineFullScreen, + timelineType, + ] ); const handleButtonClick = useCallback(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx index 7ee7e12c0ef628..166705128ce022 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx @@ -24,11 +24,14 @@ import { inputsModel, inputsSelectors, } from '../../../../common/store'; +import { TimelineEventsType } from '../../../../../common/types/timeline'; import { timelineActions, timelineSelectors } from '../../../store/timeline'; -import { KqlMode, TimelineModel, EventType } from '../../../../timelines/store/timeline/model'; +import { KqlMode, TimelineModel } from '../../../../timelines/store/timeline/model'; import { timelineDefaults } from '../../../../timelines/store/timeline/defaults'; import { dispatchUpdateReduxTime } from '../../../../common/components/super_date_picker'; import { SearchOrFilter } from './search_or_filter'; +import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; +import { sourcererActions } from '../../../../common/store/sourcerer'; interface OwnProps { browserFields: BrowserFields; @@ -62,7 +65,7 @@ const StatefulSearchOrFilterComponent = React.memo( timelineId, to, toStr, - updateEventType, + updateEventTypeAndIndexesName, updateKqlMode, updateReduxTime, }) => { @@ -111,13 +114,14 @@ const StatefulSearchOrFilterComponent = React.memo( [timelineId, setSavedQueryId] ); - const handleUpdateEventType = useCallback( - (newEventType: EventType) => - updateEventType({ + const handleUpdateEventTypeAndIndexesName = useCallback( + (newEventType: TimelineEventsType, indexNames: string[]) => + updateEventTypeAndIndexesName({ id: timelineId, eventType: newEventType, + indexNames, }), - [timelineId, updateEventType] + [timelineId, updateEventTypeAndIndexesName] ); return ( @@ -143,7 +147,7 @@ const StatefulSearchOrFilterComponent = React.memo( timelineId={timelineId} to={to} toStr={toStr} - updateEventType={handleUpdateEventType} + updateEventTypeAndIndexesName={handleUpdateEventTypeAndIndexesName} updateKqlMode={updateKqlMode!} updateReduxTime={updateReduxTime} /> @@ -211,8 +215,24 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ filterQuery, }) ), - updateEventType: ({ id, eventType }: { id: string; eventType: EventType }) => - dispatch(timelineActions.updateEventType({ id, eventType })), + updateEventTypeAndIndexesName: ({ + id, + eventType, + indexNames, + }: { + id: string; + eventType: TimelineEventsType; + indexNames: string[]; + }) => { + dispatch(timelineActions.updateEventType({ id, eventType })); + dispatch(timelineActions.updateIndexNames({ id, indexNames })); + dispatch( + sourcererActions.setSelectedIndexPatterns({ + id: SourcererScopeName.timeline, + selectedPatterns: indexNames, + }) + ); + }, updateKqlMode: ({ id, kqlMode }: { id: string; kqlMode: KqlMode }) => dispatch(timelineActions.updateKqlMode({ id, kqlMode })), setKqlFilterQueryDraft: ({ diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx index fc2bd1c21abdc7..16200f4e5ef9a7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx @@ -4,17 +4,47 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiHealth, EuiSuperSelect } from '@elastic/eui'; -import React, { memo } from 'react'; +import { + EuiAccordion, + EuiButton, + EuiButtonEmpty, + EuiRadioGroup, + EuiComboBox, + EuiComboBoxOptionOption, + EuiHealth, + EuiIcon, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, + EuiPopoverTitle, + EuiSpacer, + EuiText, + EuiToolTip, +} from '@elastic/eui'; +import deepEqual from 'fast-deep-equal'; +import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; +import { useSelector } from 'react-redux'; import styled from 'styled-components'; -import { EventType } from '../../../../timelines/store/timeline/model'; +import { State } from '../../../../common/store'; +import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; +import { TimelineEventsType } from '../../../../../common/types/timeline'; +import { getSourcererScopeSelector, SourcererScopeSelector } from './selectors'; import * as i18n from './translations'; -interface EventTypeOptionItem { - value: EventType; - inputDisplay: React.ReactElement; -} +const PopoverContent = styled.div` + width: 600px; +`; + +const ResetButton = styled(EuiButtonEmpty)` + width: fit-content; +`; + +const MyEuiButton = styled(EuiButton)` + .euiHealth { + vertical-align: middle; + } +`; const AllEuiHealth = styled(EuiHealth)` margin-left: -2px; @@ -36,6 +66,18 @@ const WarningEuiHealth = styled(EuiHealth)` } `; +const AdvancedSettings = styled(EuiText)` + color: ${({ theme }) => theme.eui.euiColorPrimary}; +`; + +const ConfigHelper = styled(EuiText)` + margin-left: 4px; +`; + +const Filter = styled(EuiRadioGroup)` + margin-left: 4px; +`; + const PickEventContainer = styled.div` .euiSuperSelect { width: 170px; @@ -46,43 +88,309 @@ const PickEventContainer = styled.div` } `; -export const eventTypeOptions: EventTypeOptionItem[] = [ +const getEventTypeOptions = (isCustomDisabled: boolean = true) => [ { - value: 'all', - inputDisplay: ( + id: 'all', + label: ( {i18n.ALL_EVENT} ), }, { - value: 'raw', - inputDisplay: {i18n.RAW_EVENT}, + id: 'raw', + label: {i18n.RAW_EVENT}, }, { - value: 'alert', - inputDisplay: {i18n.DETECTION_ALERTS_EVENT}, + id: 'alert', + label: {i18n.DETECTION_ALERTS_EVENT}, + }, + { + id: 'custom', + label: <>{i18n.CUSTOM_INDEX_PATTERNS}, + disabled: isCustomDisabled, }, ]; interface PickEventTypeProps { - eventType: EventType; - onChangeEventType: (value: EventType) => void; + eventType: TimelineEventsType; + onChangeEventTypeAndIndexesName: (value: TimelineEventsType, indexNames: string[]) => void; } const PickEventTypeComponents: React.FC = ({ - eventType, - onChangeEventType, + eventType = 'all', + onChangeEventTypeAndIndexesName, }) => { + const [isPopoverOpen, setPopover] = useState(false); + const [showAdvanceSettings, setAdvanceSettings] = useState(eventType === 'custom'); + const [filterEventType, setFilterEventType] = useState(eventType); + const sourcererScopeSelector = useMemo(getSourcererScopeSelector, []); + const { configIndexPatterns, kibanaIndexPatterns, signalIndexName, sourcererScope } = useSelector< + State, + SourcererScopeSelector + >((state) => sourcererScopeSelector(state, SourcererScopeName.timeline), deepEqual); + const [selectedOptions, setSelectedOptions] = useState>>( + sourcererScope.selectedPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })) + ); + + const indexesPatternOptions = useMemo( + () => + [ + ...configIndexPatterns, + ...kibanaIndexPatterns.map((kip) => kip.title), + signalIndexName, + ].reduce>>((acc, index) => { + if (index != null && !acc.some((o) => o.label.includes(index))) { + return [...acc, { label: index, value: index }]; + } + return acc; + }, []), + [configIndexPatterns, kibanaIndexPatterns, signalIndexName] + ); + + const renderOption = useCallback( + (option) => { + const { value } = option; + if (kibanaIndexPatterns.some((kip) => kip.title === value)) { + return ( + <> + {value} + + ); + } + return <>{value}; + }, + [kibanaIndexPatterns] + ); + + const onChangeCombo = useCallback( + (newSelectedOptions: Array>) => { + const localSelectedPatterns = newSelectedOptions.map((nso) => nso.label); + if ( + localSelectedPatterns.sort().join() === + [...configIndexPatterns, signalIndexName].sort().join() + ) { + setFilterEventType('all'); + } else if (localSelectedPatterns.sort().join() === configIndexPatterns.sort().join()) { + setFilterEventType('raw'); + } else if (localSelectedPatterns.sort().join() === signalIndexName) { + setFilterEventType('alert'); + } else { + setFilterEventType('custom'); + } + + setSelectedOptions(newSelectedOptions); + }, + [configIndexPatterns, signalIndexName] + ); + + const onChangeFilter = useCallback( + (filter) => { + setFilterEventType(filter); + if (filter === 'all') { + setSelectedOptions( + [...configIndexPatterns, signalIndexName ?? ''].map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })) + ); + } else if (filter === 'raw') { + setSelectedOptions( + configIndexPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })) + ); + } else if (filter === 'alert') { + setSelectedOptions([ + { + label: signalIndexName ?? '', + value: signalIndexName ?? '', + }, + ]); + } else if (filter === 'kibana') { + setSelectedOptions( + kibanaIndexPatterns.map((kip) => ({ + label: kip.title, + value: kip.title, + })) + ); + } + }, + [configIndexPatterns, kibanaIndexPatterns, signalIndexName] + ); + + const togglePopover = useCallback( + () => setPopover((prevIsPopoverOpen) => !prevIsPopoverOpen), + [] + ); + + const closePopover = useCallback(() => setPopover(false), []); + + const handleSaveIndices = useCallback(() => { + onChangeEventTypeAndIndexesName( + filterEventType, + selectedOptions.map((so) => so.label) + ); + setPopover(false); + }, [filterEventType, onChangeEventTypeAndIndexesName, selectedOptions]); + + const resetDataSources = useCallback(() => { + setSelectedOptions( + sourcererScope.selectedPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })) + ); + setFilterEventType(eventType); + }, [eventType, sourcererScope.selectedPatterns]); + + const comboBox = useMemo( + () => ( + + ), + [onChangeCombo, indexesPatternOptions, renderOption, selectedOptions] + ); + + const filterOptions = useMemo(() => getEventTypeOptions(filterEventType !== 'custom'), [ + filterEventType, + ]); + + const filter = useMemo( + () => ( + + ), + [filterEventType, filterOptions, onChangeFilter] + ); + + const button = useMemo(() => { + const options = getEventTypeOptions(); + return ( + + {options.find((opt) => opt.id === eventType)?.label} + + ); + }, [eventType, sourcererScope.loading, togglePopover]); + + const tooltipContent = useMemo( + () => (isPopoverOpen ? null : sourcererScope.selectedPatterns.sort().join(', ')), + [isPopoverOpen, sourcererScope.selectedPatterns] + ); + + const ButtonContent = useMemo( + () => ( + + {showAdvanceSettings + ? i18n.HIDE_INDEX_PATTERNS_ADVANCED_SETTINGS + : i18n.SHOW_INDEX_PATTERNS_ADVANCED_SETTINGS} + + ), + [showAdvanceSettings] + ); + + useEffect(() => { + const newSelectedOptions = sourcererScope.selectedPatterns.map((indexSelected) => ({ + label: indexSelected, + value: indexSelected, + })); + setSelectedOptions((prevSelectedOptions) => { + if (!deepEqual(newSelectedOptions, prevSelectedOptions)) { + return newSelectedOptions; + } + return prevSelectedOptions; + }); + }, [sourcererScope.selectedPatterns]); + + useEffect(() => { + setFilterEventType((prevFilter) => (prevFilter !== eventType ? eventType : prevFilter)); + setAdvanceSettings(eventType === 'custom'); + }, [eventType]); + return ( - + + + + + <>{i18n.SELECT_INDEX_PATTERNS} + + + {filter} + + + <> + + {comboBox} + + + {!showAdvanceSettings && ( + <> + + + {i18n.CONFIGURE_INDEX_PATTERNS} + + + )} + + + + + {i18n.DATA_SOURCES_RESET} + + + + + {i18n.SAVE_INDEX_PATTERNS} + + + + + + ); }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/search_or_filter.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/search_or_filter.tsx index e04cef4ad8d934..32a516497f6070 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/search_or_filter.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/search_or_filter.tsx @@ -15,7 +15,8 @@ import { } from '../../../../../../../../src/plugins/data/public'; import { BrowserFields } from '../../../../common/containers/source'; import { KueryFilterQuery, KueryFilterQueryKind } from '../../../../common/store'; -import { KqlMode, EventType } from '../../../../timelines/store/timeline/model'; +import { TimelineEventsType } from '../../../../../common/types/timeline'; +import { KqlMode } from '../../../../timelines/store/timeline/model'; import { DispatchUpdateReduxTime } from '../../../../common/components/super_date_picker'; import { DataProvider } from '../data_providers/data_provider'; import { QueryBarTimeline } from '../query_bar'; @@ -47,7 +48,7 @@ interface Props { applyKqlFilterQuery: (expression: string, kind: KueryFilterQueryKind) => void; browserFields: BrowserFields; dataProviders: DataProvider[]; - eventType: EventType; + eventType: TimelineEventsType; filterManager: FilterManager; filterQuery: KueryFilterQuery; filterQueryDraft: KueryFilterQuery; @@ -66,7 +67,7 @@ interface Props { savedQueryId: string | null; to: string; toStr: string; - updateEventType: (eventType: EventType) => void; + updateEventTypeAndIndexesName: (eventType: TimelineEventsType, indexNames: string[]) => void; updateReduxTime: DispatchUpdateReduxTime; } @@ -114,7 +115,7 @@ export const SearchOrFilter = React.memo( setSavedQueryId, to, toStr, - updateEventType, + updateEventTypeAndIndexesName, updateKqlMode, updateReduxTime, }) => { @@ -167,7 +168,10 @@ export const SearchOrFilter = React.memo( /> - + diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/selectors.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/selectors.tsx new file mode 100644 index 00000000000000..2fdcf7a0eb0c12 --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/selectors.tsx @@ -0,0 +1,43 @@ +/* + * 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 { State } from '../../../../common/store'; +import { sourcererSelectors } from '../../../../common/store/selectors'; +import { + KibanaIndexPatterns, + ManageScope, + SourcererScopeName, +} from '../../../../common/store/sourcerer/model'; + +export interface SourcererScopeSelector { + configIndexPatterns: string[]; + kibanaIndexPatterns: KibanaIndexPatterns; + signalIndexName: string | null; + sourcererScope: ManageScope; +} + +export const getSourcererScopeSelector = () => { + const getkibanaIndexPatternsSelector = sourcererSelectors.kibanaIndexPatternsSelector(); + const getScopesSelector = sourcererSelectors.scopesSelector(); + const getConfigIndexPatternsSelector = sourcererSelectors.configIndexPatternsSelector(); + const getSignalIndexNameSelector = sourcererSelectors.signalIndexNameSelector(); + + const mapStateToProps = (state: State, scopeId: SourcererScopeName): SourcererScopeSelector => { + const kibanaIndexPatterns = getkibanaIndexPatternsSelector(state); + const scope = getScopesSelector(state)[scopeId]; + const configIndexPatterns = getConfigIndexPatternsSelector(state); + const signalIndexName = getSignalIndexNameSelector(state); + + return { + kibanaIndexPatterns, + configIndexPatterns, + signalIndexName, + sourcererScope: scope, + }; + }; + + return mapStateToProps; +}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/translations.ts b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/translations.ts index b5c78c458697c9..f595881a57d03a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/translations.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/translations.ts @@ -73,14 +73,14 @@ export const FILTER_OR_SEARCH_WITH_KQL = i18n.translate( export const ALL_EVENT = i18n.translate( 'xpack.securitySolution.timeline.searchOrFilter.eventTypeAllEvent', { - defaultMessage: 'All', + defaultMessage: 'All data sources', } ); export const RAW_EVENT = i18n.translate( 'xpack.securitySolution.timeline.searchOrFilter.eventTypeRawEvent', { - defaultMessage: 'Raw events', + defaultMessage: 'Events', } ); @@ -90,3 +90,59 @@ export const DETECTION_ALERTS_EVENT = i18n.translate( defaultMessage: 'Detection Alerts', } ); + +export const CUSTOM_INDEX_PATTERNS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.customeIndexNames', + { + defaultMessage: 'Custom', + } +); + +export const SELECT_INDEX_PATTERNS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.help', + { + defaultMessage: 'Data sources selection', + } +); + +export const CONFIGURE_INDEX_PATTERNS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.configure', + { + defaultMessage: 'View data sources associated with each of the above selections', + } +); + +export const SAVE_INDEX_PATTERNS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.save', + { + defaultMessage: 'Save', + } +); + +export const SHOW_INDEX_PATTERNS_ADVANCED_SETTINGS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.showAdvancedSettings', + { + defaultMessage: 'Show Advanced', + } +); + +export const HIDE_INDEX_PATTERNS_ADVANCED_SETTINGS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.hideAdvancedSettings', + { + defaultMessage: 'Hide Advanced', + } +); + +export const DATA_SOURCES_RESET = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.resetSettings', + { + defaultMessage: 'Reset', + } +); + +export const PICK_INDEX_PATTERNS = i18n.translate( + 'xpack.securitySolution.timeline.searchOrFilter.indexPatterns.pickIndexPatternsCombo', + { + defaultMessage: 'Pick index patterns', + } +); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx index 234814a68877d5..e898779eacce96 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx @@ -8,7 +8,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import { rgba } from 'polished'; import styled, { createGlobalStyle } from 'styled-components'; -import { EventType } from '../../../timelines/store/timeline/model'; +import { TimelineEventsType } from '../../../../common/types/timeline'; import { IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME } from '../../../common/components/drag_and_drop/helpers'; /** @@ -173,7 +173,7 @@ export const EventsTbody = styled.div.attrs(({ className = '' }) => ({ export const EventsTrGroup = styled.div.attrs(({ className = '' }) => ({ className: `siemEventsTable__trGroup ${className}`, -}))<{ className?: string; eventType: Omit; showLeftBorder: boolean }>` +}))<{ className?: string; eventType: Omit; showLeftBorder: boolean }>` border-bottom: ${({ theme }) => theme.eui.euiBorderWidthThin} solid ${({ theme }) => theme.eui.euiColorLightShade}; ${({ theme, eventType, showLeftBorder }) => diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.test.tsx index 887a6a546d2b77..bde1e7bf5829ad 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.test.tsx @@ -10,7 +10,12 @@ import useResizeObserver from 'use-resize-observer/polyfilled'; import { mockBrowserFields } from '../../../common/containers/source/mock'; import { Direction } from '../../../graphql/types'; -import { defaultHeaders, mockTimelineData, mockIndexPattern } from '../../../common/mock'; +import { + defaultHeaders, + mockTimelineData, + mockIndexPattern, + mockIndexNames, +} from '../../../common/mock'; import '../../../common/mock/match_media'; import { TestProviders } from '../../../common/mock/test_providers'; @@ -23,7 +28,7 @@ import { TimelineComponent, Props as TimelineComponentProps } from './timeline'; import { Sort } from './body/sort'; import { mockDataProviders } from './data_providers/mock/mock_data_providers'; import { useMountAppended } from '../../../common/utils/use_mount_appended'; -import { TimelineStatus, TimelineType } from '../../../../common/types/timeline'; +import { TimelineId, TimelineStatus, TimelineType } from '../../../../common/types/timeline'; import { useTimelineEvents } from '../../containers/index'; import { useTimelineEventsDetails } from '../../containers/details/index'; @@ -94,22 +99,20 @@ describe('Timeline', () => { props = { browserFields: mockBrowserFields, columns: defaultHeaders, - id: 'foo', dataProviders: mockDataProviders, docValueFields: [], end: endDate, - eventType: 'raw' as TimelineComponentProps['eventType'], filters: [], + id: TimelineId.test, + indexNames: mockIndexNames, indexPattern, - indexToAdd: [], isLive: false, - isLoadingSource: false, isSaving: false, itemsPerPage: 5, itemsPerPageOptions: [5, 10, 20], kqlMode: 'search' as TimelineComponentProps['kqlMode'], kqlQueryExpression: '', - loadingIndexName: false, + loadingSourcerer: false, onChangeItemsPerPage: jest.fn(), onClose: jest.fn(), onDataProviderEdited: jest.fn(), @@ -119,12 +122,12 @@ describe('Timeline', () => { onToggleDataProviderType: jest.fn(), show: true, showCallOutUnauthorizedMsg: false, - start: startDate, sort, + start: startDate, status: TimelineStatus.active, + timelineType: TimelineType.default, toggleColumn: jest.fn(), usersViewing: ['elastic'], - timelineType: TimelineType.default, }; }); @@ -174,7 +177,7 @@ describe('Timeline', () => { test('it does NOT render the timeline table when the source is loading', () => { const wrapper = mount( - + ); @@ -211,16 +214,6 @@ describe('Timeline', () => { expect(wrapper.find('[data-test-subj="table-pagination"]').exists()).toEqual(false); }); - test('it defaults to showing `All`', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="pick-event-type"] button').text()).toEqual('All'); - }); - it('it shows the timeline footer', () => { const wrapper = mount( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx index 434c7075a94709..d1a25e6f3e1a48 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx @@ -14,7 +14,7 @@ import { BrowserFields, DocValueFields } from '../../../common/containers/source import { Direction } from '../../../../common/search_strategy'; import { useTimelineEvents } from '../../containers/index'; import { useKibana } from '../../../common/lib/kibana'; -import { ColumnHeaderOptions, KqlMode, EventType } from '../../../timelines/store/timeline/model'; +import { ColumnHeaderOptions, KqlMode } from '../../../timelines/store/timeline/model'; import { defaultHeaders } from './body/column_headers/default_headers'; import { Sort } from './body/sort'; import { StatefulBody } from './body/stateful_body'; @@ -99,20 +99,18 @@ export interface Props { dataProviders: DataProvider[]; docValueFields: DocValueFields[]; end: string; - eventType?: EventType; filters: Filter[]; graphEventId?: string; id: string; + indexNames: string[]; indexPattern: IIndexPattern; - indexToAdd: string[]; isLive: boolean; - isLoadingSource: boolean; isSaving: boolean; itemsPerPage: number; itemsPerPageOptions: number[]; kqlMode: KqlMode; kqlQueryExpression: string; - loadingIndexName: boolean; + loadingSourcerer: boolean; onChangeItemsPerPage: OnChangeItemsPerPage; onClose: () => void; onDataProviderEdited: OnDataProviderEdited; @@ -122,12 +120,12 @@ export interface Props { onToggleDataProviderType: OnToggleDataProviderType; show: boolean; showCallOutUnauthorizedMsg: boolean; - start: string; sort: Sort; + start: string; status: TimelineStatusLiteral; + timelineType: TimelineType; toggleColumn: (column: ColumnHeaderOptions) => void; usersViewing: string[]; - timelineType: TimelineType; } /** The parent Timeline component */ @@ -137,20 +135,18 @@ export const TimelineComponent: React.FC = ({ dataProviders, docValueFields, end, - eventType, filters, graphEventId, id, indexPattern, - indexToAdd, + indexNames, isLive, - isLoadingSource, + loadingSourcerer, isSaving, itemsPerPage, itemsPerPageOptions, kqlMode, kqlQueryExpression, - loadingIndexName, onChangeItemsPerPage, onClose, onDataProviderEdited, @@ -204,11 +200,11 @@ export const TimelineComponent: React.FC = ({ const canQueryTimeline = useMemo( () => combinedQueries != null && - isLoadingSource != null && - !isLoadingSource && + loadingSourcerer != null && + !loadingSourcerer && !isEmpty(start) && !isEmpty(end), - [isLoadingSource, combinedQueries, start, end] + [loadingSourcerer, combinedQueries, start, end] ); const columnsHeader = isEmpty(columns) ? defaultHeaders : columns; const timelineQueryFields = useMemo(() => { @@ -223,16 +219,13 @@ export const TimelineComponent: React.FC = ({ [sort.columnId, sort.sortDirection] ); const [isQueryLoading, setIsQueryLoading] = useState(false); - const { initializeTimeline, setIndexToAdd, setIsTimelineLoading } = useManageTimeline(); - + const { initializeTimeline, setIsTimelineLoading } = useManageTimeline(); useEffect(() => { initializeTimeline({ filterManager, id, - indexToAdd, }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [initializeTimeline, filterManager, id]); const [ loading, @@ -240,24 +233,19 @@ export const TimelineComponent: React.FC = ({ ] = useTimelineEvents({ docValueFields, endDate: end, - eventType, id, - indexToAdd, + indexNames, fields: timelineQueryFields, limit: itemsPerPage, filterQuery: combinedQueries?.filterQuery ?? '', startDate: start, - skip: canQueryTimeline, + skip: !canQueryTimeline, sort: timelineQuerySortField, }); useEffect(() => { - setIsTimelineLoading({ id, isLoading: isQueryLoading || loadingIndexName }); - }, [loadingIndexName, id, isQueryLoading, setIsTimelineLoading]); - - useEffect(() => { - setIndexToAdd({ id, indexToAdd }); - }, [id, indexToAdd, setIndexToAdd]); + setIsTimelineLoading({ id, isLoading: isQueryLoading || loadingSourcerer }); + }, [loadingSourcerer, id, isQueryLoading, setIsTimelineLoading]); useEffect(() => { setIsQueryLoading(loading); @@ -329,7 +317,7 @@ export const TimelineComponent: React.FC = ({ height={footerHeight} id={id} isLive={isLive} - isLoading={loading || loadingIndexName} + isLoading={loading || loadingSourcerer} itemsCount={events.length} itemsPerPage={itemsPerPage} itemsPerPageOptions={itemsPerPageOptions} diff --git a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx index 23c05805a5aa4f..cd72ffb8ac8030 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx @@ -9,7 +9,6 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import deepEqual from 'fast-deep-equal'; import { inputsModel } from '../../../common/store'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { useKibana } from '../../../common/lib/kibana'; import { DocValueFields, @@ -36,10 +35,9 @@ export const useTimelineEventsDetails = ({ eventId, skip, }: UseTimelineEventsDetailsProps): [boolean, EventsArgs['detailsData']] => { - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultIndex = uiSettings.get(DEFAULT_INDEX_KEY); const [loading, setLoading] = useState(false); const [ timelineDetailsRequest, @@ -102,7 +100,6 @@ export const useTimelineEventsDetails = ({ setTimelineDetailsRequest((prevRequest) => { const myRequest = { ...(prevRequest ?? {}), - defaultIndex, docValueFields, indexName, eventId, @@ -113,7 +110,7 @@ export const useTimelineEventsDetails = ({ } return prevRequest; }); - }, [defaultIndex, docValueFields, eventId, indexName, skip]); + }, [docValueFields, eventId, indexName, skip]); useEffect(() => { if (timelineDetailsRequest) { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx index d56a601fda4a38..54db52b985c314 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx @@ -10,18 +10,11 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useDispatch } from 'react-redux'; import { ESQuery } from '../../../common/typed_json'; -import { - IIndexPattern, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../src/plugins/data/public'; - -import { DEFAULT_INDEX_KEY } from '../../../common/constants'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../src/plugins/data/public'; import { inputsModel } from '../../common/store'; import { useKibana } from '../../common/lib/kibana'; import { createFilter } from '../../common/containers/helpers'; import { DocValueFields } from '../../common/containers/query_template'; -import { EventType } from '../../timelines/store/timeline/model'; import { timelineActions } from '../../timelines/store/timeline'; import { detectionsTimelineIds, skipQueryForDetectionsPage } from './helpers'; import { getInspectResponse } from '../../helpers'; @@ -58,15 +51,12 @@ interface UseTimelineEventsProps { filterQuery?: ESQuery | string; skip?: boolean; endDate: string; - eventType?: EventType; id: string; fields: string[]; - indexPattern?: IIndexPattern; - indexToAdd?: string[]; + indexNames: string[]; limit: number; sort: SortField; startDate: string; - canQueryTimeline?: boolean; } const getTimelineEvents = (timelineEdges: TimelineEdges[]): TimelineItem[] => @@ -77,10 +67,8 @@ const ID = 'timelineEventsQuery'; export const useTimelineEvents = ({ docValueFields, endDate, - eventType = 'raw', id = ID, - indexPattern, - indexToAdd = [], + indexNames, fields, filterQuery, startDate, @@ -89,41 +77,37 @@ export const useTimelineEvents = ({ field: '@timestamp', direction: Direction.asc, }, - canQueryTimeline = true, + skip = false, }: UseTimelineEventsProps): [boolean, TimelineArgs] => { const dispatch = useDispatch(); - const { data, notifications, uiSettings } = useKibana().services; + const { data, notifications } = useKibana().services; const refetch = useRef(noop); const abortCtrl = useRef(new AbortController()); - const defaultKibanaIndex = uiSettings.get(DEFAULT_INDEX_KEY); - const defaultIndex = - indexPattern == null || (indexPattern != null && indexPattern.title === '') - ? [ - ...(['all', 'raw'].includes(eventType) ? defaultKibanaIndex : []), - ...(['all', 'alert', 'signal'].includes(eventType) ? indexToAdd : []), - ] - : indexPattern?.title.split(',') ?? []; const [loading, setLoading] = useState(false); const [activePage, setActivePage] = useState(0); - const [timelineRequest, setTimelineRequest] = useState({ - fields, - fieldRequested: fields, - filterQuery: createFilter(filterQuery), - id, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - pagination: { - activePage, - querySize: limit, - }, - sort, - defaultIndex, - docValueFields: docValueFields ?? [], - factoryQueryType: TimelineEventsQueries.all, - }); + const [timelineRequest, setTimelineRequest] = useState( + !skip + ? { + fields, + fieldRequested: fields, + filterQuery: createFilter(filterQuery), + id, + timerange: { + interval: '12h', + from: startDate, + to: endDate, + }, + pagination: { + activePage, + querySize: limit, + }, + sort, + defaultIndex: indexNames, + docValueFields: docValueFields ?? [], + factoryQueryType: TimelineEventsQueries.all, + } + : null + ); const clearSignalsState = useCallback(() => { if (id != null && detectionsTimelineIds.some((timelineId) => timelineId === id)) { @@ -158,7 +142,11 @@ export const useTimelineEvents = ({ }); const timelineSearch = useCallback( - (request: TimelineEventsAllRequestOptions) => { + (request: TimelineEventsAllRequestOptions | null) => { + if (request == null) { + return; + } + let didCancel = false; const asyncSearch = async () => { abortCtrl.current = new AbortController(); @@ -215,14 +203,19 @@ export const useTimelineEvents = ({ ); useEffect(() => { - if (!canQueryTimeline || skipQueryForDetectionsPage(id, defaultIndex)) { + if (skip || skipQueryForDetectionsPage(id, indexNames) || indexNames.length === 0) { return; } setTimelineRequest((prevRequest) => { const myRequest = { - ...prevRequest, - defaultIndex, + ...(prevRequest ?? { + fields, + fieldRequested: fields, + id, + factoryQueryType: TimelineEventsQueries.all, + }), + defaultIndex: indexNames, docValueFields: docValueFields ?? [], filterQuery: createFilter(filterQuery), pagination: { @@ -237,8 +230,8 @@ export const useTimelineEvents = ({ sort, }; if ( - canQueryTimeline && - !skipQueryForDetectionsPage(id, defaultIndex) && + !skip && + !skipQueryForDetectionsPage(id, indexNames) && !deepEqual(prevRequest, myRequest) ) { return myRequest; @@ -246,16 +239,17 @@ export const useTimelineEvents = ({ return prevRequest; }); }, [ - defaultIndex, + indexNames, docValueFields, endDate, filterQuery, startDate, - canQueryTimeline, id, activePage, limit, sort, + skip, + fields, ]); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/one/index.gql_query.ts b/x-pack/plugins/security_solution/public/timelines/containers/one/index.gql_query.ts index 5e50a7fb3313e7..b85fbc15ce3f35 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/one/index.gql_query.ts +++ b/x-pack/plugins/security_solution/public/timelines/containers/one/index.gql_query.ts @@ -107,6 +107,7 @@ export const oneTimelineQuery = gql` serializedQuery } } + indexNames notes { eventId note diff --git a/x-pack/plugins/security_solution/public/timelines/containers/persist.gql_query.ts b/x-pack/plugins/security_solution/public/timelines/containers/persist.gql_query.ts index c38aa67ccebb20..12d3e6bfd71725 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/persist.gql_query.ts +++ b/x-pack/plugins/security_solution/public/timelines/containers/persist.gql_query.ts @@ -95,6 +95,7 @@ export const persistTimelineMutation = gql` serializedQuery } } + indexNames title dateRange { start diff --git a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx index f9097ddef64900..3c81aa8dac078a 100644 --- a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx @@ -21,12 +21,12 @@ jest.mock('react-router-dom', () => { }; }); jest.mock('../../overview/components/events_by_dataset'); -jest.mock('../../common/containers/source', () => { - const originalModule = jest.requireActual('../../common/containers/source'); +jest.mock('../../common/containers/sourcerer', () => { + const originalModule = jest.requireActual('../../common/containers/sourcerer'); return { ...originalModule, - useWithSource: jest.fn().mockReturnValue({ + useSourcererScope: jest.fn().mockReturnValue({ indicesExist: true, }), }; diff --git a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx index 79d0f909c7d592..136240939e7a3f 100644 --- a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx +++ b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx @@ -15,16 +15,14 @@ import { WrapperPage } from '../../common/components/wrapper_page'; import { useKibana } from '../../common/lib/kibana'; import { SpyRoute } from '../../common/utils/route/spy_routes'; import { useApolloClient } from '../../common/utils/apollo_context'; -import { useWithSource } from '../../common/containers/source'; import { OverviewEmpty } from '../../overview/components/overview_empty'; - import { StatefulOpenTimeline } from '../components/open_timeline'; import { NEW_TEMPLATE_TIMELINE } from '../components/timeline/properties/translations'; import { NewTemplateTimeline } from '../components/timeline/properties/new_template_timeline'; import { NewTimeline } from '../components/timeline/properties/helpers'; - import * as i18n from './translations'; import { SecurityPageName } from '../../app/types'; +import { useSourcererScope } from '../../common/containers/sourcerer'; const TimelinesContainer = styled.div` width: 100%; @@ -38,7 +36,7 @@ export const TimelinesPageComponent: React.FC = () => { const onImportTimelineBtnClick = useCallback(() => { setImportDataModalToggle(true); }, [setImportDataModalToggle]); - const { indicesExist } = useWithSource(); + const { indicesExist } = useSourcererScope(); const apolloClient = useApolloClient(); const capabilitiesCanUserCRUD: boolean = !!useKibana().services.application.capabilities.siem @@ -49,7 +47,7 @@ export const TimelinesPageComponent: React.FC = () => { {indicesExist ? ( <> - + {capabilitiesCanUserCRUD && ( @@ -97,7 +95,7 @@ export const TimelinesPageComponent: React.FC = () => { ) : ( - + )} diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts index da9c363703d16b..472e82426468e0 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts @@ -15,9 +15,13 @@ import { } from '../../../timelines/components/timeline/data_providers/data_provider'; import { KueryFilterQuery, SerializedFilterQuery } from '../../../common/store/types'; -import { EventType, KqlMode, TimelineModel, ColumnHeaderOptions } from './model'; +import { KqlMode, TimelineModel, ColumnHeaderOptions } from './model'; import { TimelineNonEcsData } from '../../../../common/search_strategy/timeline'; -import { TimelineTypeLiteral, RowRendererId } from '../../../../common/types/timeline'; +import { + TimelineEventsType, + TimelineTypeLiteral, + RowRendererId, +} from '../../../../common/types/timeline'; import { InsertTimeline } from './types'; const actionCreator = actionCreatorFactory('x-pack/security_solution/local/timeline'); @@ -63,6 +67,7 @@ export const createTimeline = actionCreator<{ filters?: Filter[]; columns: ColumnHeaderOptions[]; itemsPerPage?: number; + indexNames: string[]; kqlQuery?: { filterQuery: SerializedFilterQuery | null; filterQueryDraft: KueryFilterQuery | null; @@ -264,7 +269,7 @@ export const clearEventsDeleted = actionCreator<{ id: string; }>('CLEAR_TIMELINE_EVENTS_DELETED'); -export const updateEventType = actionCreator<{ id: string; eventType: EventType }>( +export const updateEventType = actionCreator<{ id: string; eventType: TimelineEventsType }>( 'UPDATE_EVENT_TYPE' ); @@ -272,3 +277,8 @@ export const setExcludedRowRendererIds = actionCreator<{ id: string; excludedRowRendererIds: RowRendererId[]; }>('SET_TIMELINE_EXCLUDED_ROW_RENDERER_IDS'); + +export const updateIndexNames = actionCreator<{ + id: string; + indexNames: string[]; +}>('UPDATE_INDEXES_NAME'); diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts index 7980f62cff1718..ce469c2bf57a28 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts @@ -27,6 +27,7 @@ export const timelineDefaults: SubsetTimelineModel & Pick { exists: { field: '@timestamp' }, } as Filter, ], + indexNames: [], isFavorite: false, isLive: false, isSelectAllChecked: false, @@ -272,6 +273,7 @@ describe('Epic Timeline', () => { script: null, }, ], + indexNames: [], kqlMode: 'filter', kqlQuery: { filterQuery: { diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts index ad849c3a995b33..cc8e856de1b160 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts @@ -66,6 +66,7 @@ import { updateRange, updateSort, upsertColumn, + updateIndexNames, updateTimeline, updateTitle, updateAutoSaveMsg, @@ -105,6 +106,7 @@ const timelineActionsType = [ updateDescription.type, updateEventType.type, updateKqlMode.type, + updateIndexNames.type, updateProviders.type, updateSort.type, updateTitle.type, @@ -339,6 +341,7 @@ const timelineInput: TimelineInput = { filters: null, kqlMode: null, kqlQuery: null, + indexNames: null, title: null, timelineType: TimelineType.default, templateTimelineVersion: null, diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx index 8c3f30c75c35b7..6507603d304447 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx @@ -84,18 +84,16 @@ describe('epicLocalStorage', () => { dataProviders: mockDataProviders, docValueFields: [], end: endDate, - eventType: 'raw' as TimelineComponentProps['eventType'], filters: [], + indexNames: [], indexPattern, - indexToAdd: [], isLive: false, - isLoadingSource: false, isSaving: false, itemsPerPage: 5, itemsPerPageOptions: [5, 10, 20], kqlMode: 'search' as TimelineComponentProps['kqlMode'], kqlQueryExpression: '', - loadingIndexName: false, + loadingSourcerer: false, onChangeItemsPerPage: jest.fn(), onClose: jest.fn(), onDataProviderEdited: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts index 1432e133244d02..fc178df86362b2 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts @@ -22,6 +22,7 @@ import { import { KueryFilterQuery, SerializedFilterQuery } from '../../../common/store/model'; import { TimelineNonEcsData } from '../../../../common/search_strategy/timeline'; import { + TimelineEventsType, TimelineTypeLiteral, TimelineType, RowRendererId, @@ -29,7 +30,7 @@ import { import { normalizeTimeRange } from '../../../common/components/url_state/normalize_time_range'; import { timelineDefaults } from './defaults'; -import { ColumnHeaderOptions, KqlMode, TimelineModel, EventType } from './model'; +import { ColumnHeaderOptions, KqlMode, TimelineModel } from './model'; import { TimelineById } from './types'; export const isNotNull = (value: T | null): value is T => value !== null; @@ -139,6 +140,7 @@ interface AddNewTimelineParams { filters?: Filter[]; id: string; itemsPerPage?: number; + indexNames: string[]; kqlQuery?: { filterQuery: SerializedFilterQuery | null; filterQueryDraft: KueryFilterQuery | null; @@ -159,6 +161,7 @@ export const addNewTimeline = ({ filters = timelineDefaults.filters, id, itemsPerPage = timelineDefaults.itemsPerPage, + indexNames, kqlQuery = { filterQuery: null, filterQueryDraft: null }, sort = timelineDefaults.sort, show = false, @@ -186,6 +189,7 @@ export const addNewTimeline = ({ excludedRowRendererIds, filters, itemsPerPage, + indexNames, kqlQuery, sort, show, @@ -667,7 +671,7 @@ export const updateTimelineTitle = ({ interface UpdateTimelineEventTypeParams { id: string; - eventType: EventType; + eventType: TimelineEventsType; timelineById: TimelineById; } diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts index 88ec9da1e0c4ec..ec4d37d3b70a25 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts @@ -12,6 +12,7 @@ import { PinnedEvent } from '../../../graphql/types'; import { TimelineNonEcsData } from '../../../../common/search_strategy/timeline'; import { KueryFilterQuery, SerializedFilterQuery } from '../../../common/store/types'; import type { + TimelineEventsType, TimelineType, TimelineStatus, RowRendererId, @@ -19,7 +20,6 @@ import type { export const DEFAULT_PAGE_COUNT = 2; // Eui Pager will not render unless this is a minimum of 2 pages export type KqlMode = 'filter' | 'search'; -export type EventType = 'all' | 'raw' | 'alert' | 'signal'; export type ColumnHeaderType = 'not-filtered' | 'text-filter'; @@ -52,7 +52,7 @@ export interface TimelineModel { /** A summary of the events and notes in this timeline */ description: string; /** Typoe of event you want to see in this timeline */ - eventType?: EventType; + eventType?: TimelineEventsType; /** A map of events in this timeline to the chronologically ordered notes (in this timeline) associated with the event */ eventIdToNoteIds: Record; /** A list of Ids of excluded Row Renderers */ @@ -66,6 +66,8 @@ export interface TimelineModel { highlightedDropAndProviderId: string; /** Uniquely identifies the timeline */ id: string; + /** TO DO sourcerer @X define this */ + indexNames: string[]; /** If selectAll checkbox in header is checked **/ isSelectAllChecked: boolean; /** Events to be rendered as loading **/ @@ -136,6 +138,7 @@ export type SubsetTimelineModel = Readonly< | 'graphEventId' | 'highlightedDropAndProviderId' | 'historyIds' + | 'indexNames' | 'isFavorite' | 'isLive' | 'isSelectAllChecked' diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts index 45bdbd09792764..c2f43625ab464a 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { set } from '@elastic/safer-lodash-set/fp'; import { cloneDeep } from 'lodash/fp'; - import { TimelineType, TimelineStatus } from '../../../../common/types/timeline'; import { @@ -45,77 +43,76 @@ import { updateTimelineTitle, upsertTimelineColumn, } from './helpers'; -import { ColumnHeaderOptions } from './model'; +import { ColumnHeaderOptions, TimelineModel } from './model'; import { timelineDefaults } from './defaults'; import { TimelineById } from './types'; jest.mock('../../../common/components/url_state/normalize_time_range.ts'); -const timelineByIdMock: TimelineById = { - foo: { - dataProviders: [ - { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }, - ], - columns: [], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - id: 'foo', - savedObjectId: null, - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, +const basicDataProvider: DataProvider = { + and: [], + id: '123', + name: 'data provider 1', + enabled: true, + queryMatch: { + field: '', + value: '', + operator: IS_OPERATOR, }, + excluded: false, + kqlQuery: '', +}; +const basicTimeline: TimelineModel = { + columns: [], + dataProviders: [{ ...basicDataProvider }], + dateRange: { + start: '2020-07-07T08:20:18.966Z', + end: '2020-07-08T08:20:18.966Z', + }, + deletedEventIds: [], + description: '', + eventIdToNoteIds: {}, + excludedRowRendererIds: [], + highlightedDropAndProviderId: '', + historyIds: [], + id: 'foo', + indexNames: [], + isFavorite: false, + isLive: false, + isLoading: false, + isSaving: false, + isSelectAllChecked: false, + itemsPerPage: 25, + itemsPerPageOptions: [10, 25, 50], + kqlMode: 'filter', + kqlQuery: { filterQuery: null, filterQueryDraft: null }, + loadingEventIds: [], + noteIds: [], + pinnedEventIds: {}, + pinnedEventsSaveObject: {}, + savedObjectId: null, + selectedEventIds: {}, + show: true, + showCheckboxes: false, + sort: { + columnId: '@timestamp', + sortDirection: Direction.desc, + }, + status: TimelineStatus.active, + templateTimelineId: null, + templateTimelineVersion: null, + timelineType: TimelineType.default, + title: '', + version: null, + width: DEFAULT_TIMELINE_WIDTH, +}; +const timelineByIdMock: TimelineById = { + foo: { ...basicTimeline }, }; const timelineByIdTemplateMock: TimelineById = { - ...timelineByIdMock, foo: { - ...timelineByIdMock.foo, + ...basicTimeline, timelineType: TimelineType.template, }, }; @@ -132,14 +129,14 @@ describe('Timeline', () => { const update = addTimelineToStore({ id: 'foo', timeline: { - ...timelineByIdMock.foo, + ...basicTimeline, }, timelineById: timelineByIdMock, }); expect(update).toEqual({ foo: { - ...timelineByIdMock.foo, + ...basicTimeline, show: true, }, }); @@ -151,6 +148,7 @@ describe('Timeline', () => { const update = addNewTimeline({ id: 'bar', columns: defaultHeaders, + indexNames: [], timelineById: timelineByIdMock, timelineType: TimelineType.default, }); @@ -161,27 +159,29 @@ describe('Timeline', () => { const update = addNewTimeline({ id: 'bar', columns: timelineDefaults.columns, + indexNames: [], timelineById: timelineByIdMock, timelineType: TimelineType.default, }); expect(update).toEqual({ - foo: timelineByIdMock.foo, - bar: set('id', 'bar', timelineDefaults), + foo: basicTimeline, + bar: { ...timelineDefaults, id: 'bar' }, }); }); test('should add the specified columns to the timeline', () => { - const barWithEmptyColumns = set('id', 'bar', timelineDefaults); - const barWithPopulatedColumns = set('columns', defaultHeaders, barWithEmptyColumns); + const barWithEmptyColumns = { ...timelineDefaults, id: 'bar' }; + const barWithPopulatedColumns = { ...barWithEmptyColumns, columns: defaultHeaders }; const update = addNewTimeline({ id: 'bar', columns: defaultHeaders, + indexNames: [], timelineById: timelineByIdMock, timelineType: TimelineType.default, }); expect(update).toEqual({ - foo: timelineByIdMock.foo, + foo: basicTimeline, bar: barWithPopulatedColumns, }); }); @@ -203,7 +203,14 @@ describe('Timeline', () => { show: false, // value we are changing from true to false timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.show', false, timelineByIdMock)); + + expect(update).toEqual({ + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + show: false, + }, + }); }); }); @@ -211,6 +218,7 @@ describe('Timeline', () => { let timelineById: TimelineById = {}; let columns: ColumnHeaderOptions[] = []; let columnToAdd: ColumnHeaderOptions; + let mockWithExistingColumns: TimelineById; beforeEach(() => { timelineById = cloneDeep(timelineByIdMock); @@ -226,6 +234,13 @@ describe('Timeline', () => { aggregatable: true, width: DEFAULT_COLUMN_MIN_WIDTH, }; + mockWithExistingColumns = { + ...timelineById, + foo: { + ...timelineById.foo, + columns, + }, + }; }); test('should return a new reference and not the same reference', () => { @@ -248,12 +263,11 @@ describe('Timeline', () => { timelineById, }); - expect(update).toEqual(set('foo.columns', expectedColumns, timelineById)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should add a new column to an existing collection of columns at the beginning of the collection', () => { const expectedColumns = [columnToAdd, ...columns]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columnToAdd, @@ -261,13 +275,11 @@ describe('Timeline', () => { index: 0, timelineById: mockWithExistingColumns, }); - - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should add a new column to an existing collection of columns in the middle of the collection', () => { const expectedColumns = [columns[0], columnToAdd, columns[1], columns[2]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columnToAdd, @@ -276,12 +288,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should add a new column to an existing collection of columns at the end of the collection', () => { const expectedColumns = [...columns, columnToAdd]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columnToAdd, @@ -290,13 +301,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); columns.forEach((column, i) => { test(`should upsert (NOT add a new column) a column when already exists at the same index (${i})`, () => { - const mockWithExistingColumns = set('foo.columns', columns, timelineById); - const update = upsertTimelineColumn({ column, id: 'foo', @@ -304,13 +313,12 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', columns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(columns); }); }); test('should allow the 1st column to be moved to the 2nd column', () => { const expectedColumns = [columns[1], columns[0], columns[2]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columns[0], @@ -319,12 +327,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should allow the 1st column to be moved to the 3rd column', () => { const expectedColumns = [columns[1], columns[2], columns[0]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columns[0], @@ -333,12 +340,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should allow the 2nd column to be moved to the 1st column', () => { const expectedColumns = [columns[1], columns[0], columns[2]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columns[1], @@ -347,12 +353,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should allow the 2nd column to be moved to the 3rd column', () => { const expectedColumns = [columns[0], columns[2], columns[1]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columns[1], @@ -361,12 +366,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should allow the 3rd column to be moved to the 1st column', () => { const expectedColumns = [columns[2], columns[0], columns[1]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columns[2], @@ -375,12 +379,11 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should allow the 3rd column to be moved to the 2nd column', () => { const expectedColumns = [columns[0], columns[2], columns[1]]; - const mockWithExistingColumns = set('foo.columns', columns, timelineById); const update = upsertTimelineColumn({ column: columns[2], @@ -389,75 +392,39 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); }); describe('#addTimelineProvider', () => { + const providerToAdd: DataProvider = { + ...basicDataProvider, + id: '567', + name: 'data provider 2', + }; test('should return a new reference and not the same reference', () => { const update = addTimelineProvider({ id: 'foo', - provider: { - and: [], - id: '567', - name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }, + provider: providerToAdd, timelineById: timelineByIdMock, }); expect(update).not.toBe(timelineByIdMock); }); test('should add a new timeline provider', () => { - const providerToAdd: DataProvider = { - and: [], - id: '567', - name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }; const update = addTimelineProvider({ id: 'foo', provider: providerToAdd, timelineById: timelineByIdMock, }); - const addedDataProvider = timelineByIdMock.foo.dataProviders.concat(providerToAdd); - expect(update).toEqual(set('foo.dataProviders', addedDataProvider, timelineByIdMock)); + const addedDataProvider = [...basicTimeline.dataProviders].concat(providerToAdd); + expect(update.foo.dataProviders).toEqual(addedDataProvider); }); test('should NOT add a new timeline provider if it already exists and the attributes "and" is empty', () => { - const providerToAdd: DataProvider = { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }; const update = addTimelineProvider({ id: 'foo', - provider: providerToAdd, + provider: basicDataProvider, timelineById: timelineByIdMock, }); expect(update).toEqual(timelineByIdMock); @@ -467,68 +434,45 @@ describe('Timeline', () => { const myMockTimelineByIdMock = cloneDeep(timelineByIdMock); myMockTimelineByIdMock.foo.dataProviders[0].and = [ { + ...basicDataProvider, id: '456', name: 'and data provider 1', - enabled: true, - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, }, ]; - const providerToAdd: DataProvider = { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }; + const provider = { ...basicDataProvider }; const update = addTimelineProvider({ id: 'foo', - provider: providerToAdd, + provider, timelineById: myMockTimelineByIdMock, }); - expect(update).toEqual(set('foo.dataProviders[1]', providerToAdd, myMockTimelineByIdMock)); + expect(update.foo.dataProviders[1]).toEqual(provider); }); test('should UPSERT an existing timeline provider if it already exists', () => { - const providerToAdd: DataProvider = { - and: [], - id: '123', - name: 'my name changed', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - excluded: false, - kqlQuery: '', - }; const update = addTimelineProvider({ id: 'foo', - provider: providerToAdd, + provider: { + ...basicDataProvider, + name: 'my name changed', + }, timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.dataProviders[0].name', 'my name changed', timelineByIdMock)); + expect(update.foo.dataProviders[0].name).toEqual('my name changed'); }); }); describe('#removeTimelineColumn', () => { + let mockWithExistingColumns: TimelineById; + beforeEach(() => { + mockWithExistingColumns = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + columns: columnsMock, + }, + }; + }); test('should return a new reference and not the same reference', () => { - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = removeTimelineColumn({ id: 'foo', columnId: columnsMock[0].id, @@ -541,70 +485,65 @@ describe('Timeline', () => { test('should remove just the first column when the id matches', () => { const expectedColumns = [columnsMock[1], columnsMock[2]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = removeTimelineColumn({ id: 'foo', columnId: columnsMock[0].id, timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should remove just the last column when the id matches', () => { const expectedColumns = [columnsMock[0], columnsMock[1]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = removeTimelineColumn({ id: 'foo', columnId: columnsMock[2].id, timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should remove just the middle column when the id matches', () => { const expectedColumns = [columnsMock[0], columnsMock[2]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = removeTimelineColumn({ id: 'foo', columnId: columnsMock[1].id, timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should not modify the columns if the id to remove was not found', () => { const expectedColumns = cloneDeep(columnsMock); - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = removeTimelineColumn({ id: 'foo', columnId: 'does.not.exist', timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); }); describe('#applyDeltaToColumnWidth', () => { + let mockWithExistingColumns: TimelineById; + beforeEach(() => { + mockWithExistingColumns = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + columns: columnsMock, + }, + }; + }); test('should return a new reference and not the same reference', () => { const delta = 50; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = applyDeltaToTimelineColumnWidth({ id: 'foo', columnId: columnsMock[0].id, @@ -624,9 +563,6 @@ describe('Timeline', () => { }; const expectedColumns = [expectedToHaveNewWidth, columnsMock[1], columnsMock[2]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = applyDeltaToTimelineColumnWidth({ id: 'foo', columnId: aDateColumn.id, @@ -634,7 +570,7 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should NOT update (just) the specified column of type `date` when the id matches, because the result of applying the delta is less than the min width for a date column', () => { @@ -646,9 +582,6 @@ describe('Timeline', () => { }; const expectedColumns = [expectedToHaveNewWidth, columnsMock[1], columnsMock[2]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = applyDeltaToTimelineColumnWidth({ id: 'foo', columnId: aDateColumn.id, @@ -656,7 +589,7 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should update (just) the specified non-date column when the id matches, and the result of applying the delta is greater than the min width for the column', () => { @@ -668,9 +601,6 @@ describe('Timeline', () => { }; const expectedColumns = [columnsMock[0], expectedToHaveNewWidth, columnsMock[2]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = applyDeltaToTimelineColumnWidth({ id: 'foo', columnId: aNonDateColumn.id, @@ -678,7 +608,7 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); test('should NOT update the specified non-date column when the id matches, because the result of applying the delta is less than the min width for the column', () => { @@ -690,9 +620,6 @@ describe('Timeline', () => { }; const expectedColumns = [columnsMock[0], expectedToHaveNewWidth, columnsMock[2]]; - // pre-populate a new mock with existing columns: - const mockWithExistingColumns = set('foo.columns', columnsMock, timelineByIdMock); - const update = applyDeltaToTimelineColumnWidth({ id: 'foo', columnId: aNonDateColumn.id, @@ -700,24 +627,21 @@ describe('Timeline', () => { timelineById: mockWithExistingColumns, }); - expect(update).toEqual(set('foo.columns', expectedColumns, mockWithExistingColumns)); + expect(update.foo.columns).toEqual(expectedColumns); }); }); describe('#addAndProviderToTimelineProvider', () => { test('should add a new and provider to an existing timeline provider', () => { const providerToAdd: DataProvider = { - and: [], + ...basicDataProvider, id: '567', name: 'data provider 2', - enabled: true, queryMatch: { field: 'handsome', - value: 'garrett', + value: 'xavier', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }; const newTimeline = addTimelineProvider({ @@ -729,18 +653,14 @@ describe('Timeline', () => { newTimeline.foo.highlightedDropAndProviderId = '567'; const andProviderToAdd: DataProvider = { - and: [], + ...basicDataProvider, id: '568', name: 'And Data Provider', - enabled: true, queryMatch: { field: 'smart', - value: 'frank', + value: 'steph', operator: IS_OPERATOR, }, - - excluded: false, - kqlQuery: '', }; const update = addTimelineProvider({ @@ -757,30 +677,25 @@ describe('Timeline', () => { test('should add another and provider because it is not a duplicate', () => { const providerToAdd: DataProvider = { + ...basicDataProvider, and: [ { + ...basicDataProvider, id: '568', name: 'And Data Provider', - enabled: true, queryMatch: { field: 'smart', - value: 'garrett', + value: 'xavier', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }, ], id: '567', - name: 'data provider 1', - enabled: true, queryMatch: { field: 'handsome', - value: 'frank', + value: 'steph', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }; const newTimeline = addTimelineProvider({ @@ -792,17 +707,14 @@ describe('Timeline', () => { newTimeline.foo.highlightedDropAndProviderId = '567'; const andProviderToAdd: DataProvider = { - and: [], + ...basicDataProvider, id: '569', name: 'And Data Provider', - enabled: true, queryMatch: { field: 'happy', value: 'andrewG', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }; // temporary, we will have to decouple DataProvider & DataProvidersAnd // that's bigger a refactor than just fixing a bug @@ -814,36 +726,31 @@ describe('Timeline', () => { timelineById: newTimeline, }); - expect(update).toEqual(set('foo.dataProviders[1].and[1]', andProviderToAdd, newTimeline)); + expect(update.foo.dataProviders[1].and[1]).toEqual(andProviderToAdd); newTimeline.foo.highlightedDropAndProviderId = ''; }); test('should NOT add another and provider because it is a duplicate', () => { const providerToAdd: DataProvider = { + ...basicDataProvider, and: [ { + ...basicDataProvider, id: '568', name: 'And Data Provider', - enabled: true, queryMatch: { field: 'smart', - value: 'garrett', + value: 'xavier', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }, ], id: '567', - name: 'data provider 1', - enabled: true, queryMatch: { field: 'handsome', - value: 'frank', + value: 'steph', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }; const newTimeline = addTimelineProvider({ @@ -855,17 +762,14 @@ describe('Timeline', () => { newTimeline.foo.highlightedDropAndProviderId = '567'; const andProviderToAdd: DataProvider = { - and: [], + ...basicDataProvider, id: '569', name: 'And Data Provider', - enabled: true, queryMatch: { field: 'smart', - value: 'garrett', + value: 'xavier', operator: IS_OPERATOR, }, - excluded: false, - kqlQuery: '', }; const update = addTimelineProvider({ id: 'foo', @@ -894,7 +798,7 @@ describe('Timeline', () => { columns: columnsMock, timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.columns', [...columnsMock], timelineByIdMock)); + expect(update.foo.columns).toEqual([...columnsMock]); }); }); @@ -916,7 +820,7 @@ describe('Timeline', () => { description: newDescription, timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.description', newDescription, timelineByIdMock)); + expect(update.foo.description).toEqual(newDescription); }); test('should always trim all leading whitespace and allow only one trailing space', () => { @@ -925,7 +829,7 @@ describe('Timeline', () => { description: ' breathing room ', timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.description', 'breathing room ', timelineByIdMock)); + expect(update.foo.description).toEqual('breathing room '); }); }); @@ -947,7 +851,7 @@ describe('Timeline', () => { title: newTitle, timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.title', newTitle, timelineByIdMock)); + expect(update.foo.title).toEqual(newTitle); }); test('should always trim all leading whitespace and allow only one trailing space', () => { @@ -956,7 +860,7 @@ describe('Timeline', () => { title: ' room at the back ', timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.title', 'room at the back ', timelineByIdMock)); + expect(update.foo.title).toEqual('room at the back '); }); }); @@ -966,18 +870,9 @@ describe('Timeline', () => { id: 'foo', providers: [ { - and: [], + ...basicDataProvider, id: '567', name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, ], timelineById: timelineByIdMock, @@ -985,64 +880,47 @@ describe('Timeline', () => { expect(update).not.toBe(timelineByIdMock); }); - test('should add update a timeline with new providers', () => { + test('should add update a timeline with new providers BBB', () => { const providerToAdd: DataProvider = { - and: [], + ...basicDataProvider, id: '567', name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }; const update = updateTimelineProviders({ id: 'foo', providers: [providerToAdd], timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.dataProviders', [providerToAdd], timelineByIdMock)); + expect(update.foo.dataProviders).toEqual([providerToAdd]); }); }); describe('#updateTimelineRange', () => { - test('should return a new reference and not the same reference', () => { - const update = updateTimelineRange({ + let update: TimelineById; + beforeAll(() => { + update = updateTimelineRange({ id: 'foo', start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z', timelineById: timelineByIdMock, }); + }); + test('should return a new reference and not the same reference', () => { expect(update).not.toBe(timelineByIdMock); }); test('should update the timeline range', () => { - const update = updateTimelineRange({ - id: 'foo', + expect(update.foo.dateRange).toEqual({ start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z', - timelineById: timelineByIdMock, }); - expect(update).toEqual( - set( - 'foo.dateRange', - { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - timelineByIdMock - ) - ); }); }); describe('#updateTimelineSort', () => { - test('should return a new reference and not the same reference', () => { - const update = updateTimelineSort({ + let update: TimelineById; + beforeAll(() => { + update = updateTimelineSort({ id: 'foo', sort: { columnId: 'some column', @@ -1050,31 +928,19 @@ describe('Timeline', () => { }, timelineById: timelineByIdMock, }); + }); + test('should return a new reference and not the same reference', () => { expect(update).not.toBe(timelineByIdMock); }); test('should update the timeline range', () => { - const update = updateTimelineSort({ - id: 'foo', - sort: { - columnId: 'some column', - sortDirection: Direction.desc, - }, - timelineById: timelineByIdMock, - }); - expect(update).toEqual( - set( - 'foo.sort', - { columnId: 'some column', sortDirection: Direction.desc }, - timelineByIdMock - ) - ); + expect(update.foo.sort).toEqual({ columnId: 'some column', sortDirection: Direction.desc }); }); }); describe('#updateTimelineProviderEnabled', () => { test('should return a new reference and not the same reference', () => { - const update = updateTimelineProviderEnabled({ + const update: TimelineById = updateTimelineProviderEnabled({ id: 'foo', providerId: '123', enabled: false, // value we are updating from true to false @@ -1084,17 +950,17 @@ describe('Timeline', () => { }); test('should return a new reference for data provider and not the same reference of data provider', () => { - const update = updateTimelineProviderEnabled({ + const update: TimelineById = updateTimelineProviderEnabled({ id: 'foo', providerId: '123', enabled: false, // value we are updating from true to false timelineById: timelineByIdMock, }); - expect(update.foo.dataProviders).not.toBe(timelineByIdMock.foo.dataProviders); + expect(update.foo.dataProviders).not.toBe(basicTimeline.dataProviders); }); test('should update the timeline provider enabled from true to false', () => { - const update = updateTimelineProviderEnabled({ + const update: TimelineById = updateTimelineProviderEnabled({ id: 'foo', providerId: '123', enabled: false, // value we are updating from true to false @@ -1102,81 +968,29 @@ describe('Timeline', () => { }); const expected: TimelineById = { foo: { - id: 'foo', - savedObjectId: null, - columns: [], + ...basicTimeline, dataProviders: [ { - and: [], - id: '123', - name: 'data provider 1', - enabled: false, // This value changed from true to false - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, + ...basicDataProvider, + enabled: false, }, ], - deletedEventIds: [], - description: '', - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); }); test('should update only one data provider and not two data providers', () => { - const multiDataProvider = timelineByIdMock.foo.dataProviders.concat({ - and: [], + const multiDataProvider = [...basicTimeline.dataProviders].concat({ + ...basicDataProvider, id: '456', - name: 'data provider 1', - enabled: true, - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, }); - const multiDataProviderMock = set('foo.dataProviders', multiDataProvider, timelineByIdMock); + const multiDataProviderMock = { + foo: { + ...timelineByIdMock.foo, + dataProviders: multiDataProvider, + }, + }; const update = updateTimelineProviderEnabled({ id: 'foo', providerId: '123', @@ -1185,74 +999,17 @@ describe('Timeline', () => { }); const expected: TimelineById = { foo: { - id: 'foo', - savedObjectId: null, - columns: [], + ...basicTimeline, dataProviders: [ { - and: [], - id: '123', - name: 'data provider 1', - enabled: false, // value we are updating from true to false - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, + ...basicDataProvider, + enabled: false, }, { - and: [], + ...basicDataProvider, id: '456', - name: 'data provider 1', - enabled: true, - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, }, ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); @@ -1261,34 +1018,18 @@ describe('Timeline', () => { describe('#updateTimelineAndProviderEnabled', () => { let timelineByIdwithAndMock: TimelineById = timelineByIdMock; + let update: TimelineById; beforeEach(() => { const providerToAdd: DataProvider = { + ...basicDataProvider, and: [ { + ...basicDataProvider, id: '568', name: 'And Data Provider', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, ], id: '567', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }; timelineByIdwithAndMock = addTimelineProvider({ @@ -1296,43 +1037,30 @@ describe('Timeline', () => { provider: providerToAdd, timelineById: timelineByIdMock, }); - }); - test('should return a new reference and not the same reference', () => { - const update = updateTimelineProviderEnabled({ + update = updateTimelineProviderEnabled({ id: 'foo', providerId: '567', enabled: false, // value we are updating from true to false timelineById: timelineByIdwithAndMock, andProviderId: '568', }); + }); + + test('should return a new reference and not the same reference', () => { expect(update).not.toBe(timelineByIdwithAndMock); }); test('should return a new reference for and data provider and not the same reference of data and provider', () => { - const update = updateTimelineProviderEnabled({ - id: 'foo', - providerId: '567', - enabled: false, // value we are updating from true to false - timelineById: timelineByIdwithAndMock, - andProviderId: '568', - }); - expect(update.foo.dataProviders).not.toBe(timelineByIdMock.foo.dataProviders); + expect(update.foo.dataProviders).not.toBe(basicTimeline.dataProviders); }); test('should update the timeline and provider enabled from true to false', () => { - const update = updateTimelineProviderEnabled({ - id: 'foo', - providerId: '567', - enabled: false, // value we are updating from true to false - timelineById: timelineByIdwithAndMock, - andProviderId: '568', - }); const indexProvider = update.foo.dataProviders.findIndex((i) => i.id === '567'); expect(update.foo.dataProviders[indexProvider].and[0].enabled).toEqual(false); }); - test('should update only one and data provider and not two and data providers', () => { + test('should update only one and data provider and not two and data providers ahhhh', () => { const indexProvider = timelineByIdwithAndMock.foo.dataProviders.findIndex( (i) => i.id === '567' ); @@ -1351,12 +1079,9 @@ describe('Timeline', () => { excluded: false, kqlQuery: '', }); - const multiAndDataProviderMock = set( - `foo.dataProviders[${indexProvider}].and`, - multiAndDataProvider, - timelineByIdwithAndMock - ); - const update = updateTimelineProviderEnabled({ + const multiAndDataProviderMock = timelineByIdwithAndMock; + multiAndDataProviderMock.foo.dataProviders[indexProvider].and = multiAndDataProvider; + update = updateTimelineProviderEnabled({ id: 'foo', providerId: '567', enabled: false, // value we are updating from true to false @@ -1375,111 +1100,51 @@ describe('Timeline', () => { }); describe('#updateTimelineProviderExcluded', () => { - test('should return a new reference and not the same reference', () => { - const update = updateTimelineProviderExcluded({ + let update: TimelineById; + beforeAll(() => { + update = updateTimelineProviderExcluded({ id: 'foo', providerId: '123', excluded: true, // value we are updating from false to true timelineById: timelineByIdMock, }); + }); + test('should return a new reference and not the same reference', () => { expect(update).not.toBe(timelineByIdMock); }); test('should return a new reference for data provider and not the same reference of data provider', () => { - const update = updateTimelineProviderExcluded({ - id: 'foo', - providerId: '123', - excluded: true, // value we are updating from false to true - timelineById: timelineByIdMock, - }); - expect(update.foo.dataProviders).not.toBe(timelineByIdMock.foo.dataProviders); + expect(update.foo.dataProviders).not.toBe(basicTimeline.dataProviders); }); test('should update the timeline provider excluded from true to false', () => { - const update = updateTimelineProviderExcluded({ - id: 'foo', - providerId: '123', - excluded: true, // value we are updating from false to true - timelineById: timelineByIdMock, - }); const expected: TimelineById = { foo: { - id: 'foo', - savedObjectId: null, - columns: [], + ...basicTimeline, dataProviders: [ { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, - excluded: true, // This value changed from true to false - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, + ...basicDataProvider, + excluded: true, }, ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); }); test('should update only one data provider and not two data providers', () => { - const multiDataProvider = timelineByIdMock.foo.dataProviders.concat({ - and: [], + const multiDataProvider = basicTimeline.dataProviders.concat({ + ...basicDataProvider, id: '456', - name: 'data provider 1', - enabled: true, - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, }); - const multiDataProviderMock = set('foo.dataProviders', multiDataProvider, timelineByIdMock); - const update = updateTimelineProviderExcluded({ + const multiDataProviderMock = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + dataProviders: multiDataProvider, + }, + }; + update = updateTimelineProviderExcluded({ id: 'foo', providerId: '123', excluded: true, // value we are updating from false to true @@ -1487,74 +1152,17 @@ describe('Timeline', () => { }); const expected: TimelineById = { foo: { - id: 'foo', - savedObjectId: null, - columns: [], + ...basicTimeline, dataProviders: [ { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, + ...basicDataProvider, excluded: true, // value we are updating from false to true - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, }, { - and: [], + ...basicDataProvider, id: '456', - name: 'data provider 1', - enabled: true, - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, }, ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineId: null, - templateTimelineVersion: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); @@ -1596,173 +1204,71 @@ describe('Timeline', () => { const update = updateTimelineProviderType({ id: 'foo', providerId: '123', - type: DataProviderType.template, // value we are updating from default to template + type: DataProviderType.template, timelineById: timelineByIdTemplateMock, }); const expected: TimelineById = { foo: { - id: 'foo', - savedObjectId: null, - columns: [], + ...basicTimeline, dataProviders: [ { - and: [], - id: '123', - name: '', // This value changed - enabled: true, - excluded: false, - kqlQuery: '', - type: DataProviderType.template, // value we are updating from default to template + ...basicDataProvider, + name: '', queryMatch: { field: '', - value: '{}', // This value changed + value: '{}', operator: IS_OPERATOR, }, + type: DataProviderType.template, }, ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', timelineType: TimelineType.template, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; + expect(update).toEqual(expected); }); + test('should update only one data provider and not two data providers AHH', () => { + const multiDataProvider = [ + ...timelineByIdTemplateMock.foo.dataProviders, + { + ...basicDataProvider, + id: '456', + type: DataProviderType.template, + }, + ]; - test('should update only one data provider and not two data providers', () => { - const multiDataProvider = timelineByIdTemplateMock.foo.dataProviders.concat({ - and: [], - id: '456', - name: 'data provider 1', - enabled: true, - excluded: false, - type: DataProviderType.template, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, + const multiDataProviderMock = { + ...timelineByIdTemplateMock, + foo: { + ...timelineByIdTemplateMock.foo, + dataProviders: multiDataProvider, }, - }); - const multiDataProviderMock = set( - 'foo.dataProviders', - multiDataProvider, - timelineByIdTemplateMock - ); + }; const update = updateTimelineProviderType({ id: 'foo', providerId: '123', type: DataProviderType.template, // value we are updating from default to template timelineById: multiDataProviderMock, }); - const expected: TimelineById = { - foo: { - id: 'foo', - savedObjectId: null, - columns: [], - dataProviders: [ - { - and: [], - id: '123', - name: '', - enabled: true, - excluded: false, - type: DataProviderType.template, // value we are updating from default to template - kqlQuery: '', - queryMatch: { - field: '', - value: '{}', - operator: IS_OPERATOR, - }, - }, - { - and: [], - id: '456', - name: 'data provider 1', - enabled: true, - excluded: false, - kqlQuery: '', - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - type: DataProviderType.template, - }, - ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.template, - templateTimelineId: null, - templateTimelineVersion: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, + const expected = [ + { + ...basicDataProvider, + name: '', + type: DataProviderType.template, + queryMatch: { + field: '', + value: '{}', + operator: IS_OPERATOR, }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, - }; - expect(update).toEqual(expected); + { + ...basicDataProvider, + id: '456', + type: DataProviderType.template, + }, + ]; + expect(update.foo.dataProviders).toEqual(expected); }); }); @@ -1770,32 +1276,15 @@ describe('Timeline', () => { let timelineByIdwithAndMock: TimelineById = timelineByIdMock; beforeEach(() => { const providerToAdd: DataProvider = { + ...basicDataProvider, and: [ { + ...basicDataProvider, id: '568', name: 'And Data Provider', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, ], id: '567', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }; timelineByIdwithAndMock = addTimelineProvider({ @@ -1824,7 +1313,7 @@ describe('Timeline', () => { timelineById: timelineByIdwithAndMock, andProviderId: '568', }); - expect(update.foo.dataProviders).not.toBe(timelineByIdMock.foo.dataProviders); + expect(update.foo.dataProviders).not.toBe(basicTimeline.dataProviders); }); test('should update the timeline and provider excluded from true to false', () => { @@ -1846,23 +1335,12 @@ describe('Timeline', () => { const multiAndDataProvider = timelineByIdwithAndMock.foo.dataProviders[ indexProvider ].and.concat({ + ...basicDataProvider, id: '456', name: 'new and data provider', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }); - const multiAndDataProviderMock = set( - `foo.dataProviders[${indexProvider}].and`, - multiAndDataProvider, - timelineByIdwithAndMock - ); + const multiAndDataProviderMock = timelineByIdwithAndMock; + multiAndDataProviderMock.foo.dataProviders[indexProvider].and = multiAndDataProvider; const update = updateTimelineProviderExcluded({ id: 'foo', providerId: '567', @@ -1899,62 +1377,8 @@ describe('Timeline', () => { }); const expected: TimelineById = { foo: { - id: 'foo', - savedObjectId: null, - columns: [], - dataProviders: [ - { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }, - ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, + ...basicTimeline, itemsPerPage: 50, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); @@ -1979,62 +1403,8 @@ describe('Timeline', () => { }); const expected: TimelineById = { foo: { - columns: [], - dataProviders: [ - { - and: [], - id: '123', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', - }, - ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - id: 'foo', - savedObjectId: null, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, + ...basicTimeline, itemsPerPageOptions: [100, 200, 300], // updated - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); @@ -2057,25 +1427,22 @@ describe('Timeline', () => { providerId: '123', timelineById: timelineByIdMock, }); - expect(update).toEqual(set('foo.dataProviders', [], timelineByIdMock)); + expect(update.foo.dataProviders).toEqual([]); }); test('should remove only one data provider and not two data providers', () => { - const multiDataProvider = timelineByIdMock.foo.dataProviders.concat({ - and: [], + const multiDataProvider = basicTimeline.dataProviders.concat({ + ...basicDataProvider, id: '456', name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }); - const multiDataProviderMock = set('foo.dataProviders', multiDataProvider, timelineByIdMock); + const multiDataProviderMock = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + dataProviders: multiDataProvider, + }, + }; const update = removeTimelineProvider({ id: 'foo', providerId: '123', @@ -2083,62 +1450,14 @@ describe('Timeline', () => { }); const expected: TimelineById = { foo: { - columns: [], + ...basicTimeline, dataProviders: [ { - and: [], + ...basicDataProvider, id: '456', name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, ], - description: '', - deletedEventIds: [], - eventIdToNoteIds: {}, - excludedRowRendererIds: [], - highlightedDropAndProviderId: '', - historyIds: [], - id: 'foo', - savedObjectId: null, - isFavorite: false, - isLive: false, - isSelectAllChecked: false, - isLoading: false, - kqlMode: 'filter', - kqlQuery: { filterQuery: null, filterQueryDraft: null }, - loadingEventIds: [], - title: '', - timelineType: TimelineType.default, - templateTimelineVersion: null, - templateTimelineId: null, - noteIds: [], - dateRange: { - start: '2020-07-07T08:20:18.966Z', - end: '2020-07-08T08:20:18.966Z', - }, - selectedEventIds: {}, - show: true, - showCheckboxes: false, - sort: { - columnId: '@timestamp', - sortDirection: Direction.desc, - }, - status: TimelineStatus.active, - pinnedEventIds: {}, - pinnedEventsSaveObject: {}, - itemsPerPage: 25, - itemsPerPageOptions: [10, 25, 50], - width: DEFAULT_TIMELINE_WIDTH, - isSaving: false, - version: null, }, }; expect(update).toEqual(expected); @@ -2147,99 +1466,58 @@ describe('Timeline', () => { test('should remove only first provider and not nested andProvider', () => { const dataProviders: DataProvider[] = [ { - and: [], + ...basicDataProvider, id: '111', - name: 'data provider 1', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, { - and: [], + ...basicDataProvider, id: '222', name: 'data provider 2', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, { - and: [], + ...basicDataProvider, id: '333', name: 'data provider 3', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }, ]; - const multiDataProviderMock = set('foo.dataProviders', dataProviders, timelineByIdMock); - + const multiDataProviderMock = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + dataProviders, + }, + }; const andDataProvider: DataProvidersAnd = { + ...basicDataProvider, id: '211', name: 'And Data Provider', - enabled: true, - queryMatch: { - field: '', - value: '', - operator: IS_OPERATOR, - }, - - excluded: false, - kqlQuery: '', }; - const nestedMultiAndDataProviderMock = set( - 'foo.dataProviders[1].and', - [andDataProvider], - multiDataProviderMock - ); + const nestedMultiAndDataProviderMock = multiDataProviderMock; + multiDataProviderMock.foo.dataProviders[1].and = [andDataProvider]; const update = removeTimelineProvider({ id: 'foo', providerId: '222', timelineById: nestedMultiAndDataProviderMock, }); - expect(update).toEqual( - set( - 'foo.dataProviders', - [ - nestedMultiAndDataProviderMock.foo.dataProviders[0], - { ...andDataProvider, and: [] }, - nestedMultiAndDataProviderMock.foo.dataProviders[2], - ], - timelineByIdMock - ) - ); + expect(update.foo.dataProviders).toEqual([ + nestedMultiAndDataProviderMock.foo.dataProviders[0], + { ...andDataProvider, and: [] }, + nestedMultiAndDataProviderMock.foo.dataProviders[2], + ]); }); test('should remove only the first provider and keep multiple nested andProviders', () => { const multiDataProvider: DataProvider[] = [ { + ...basicDataProvider, and: [ { - enabled: true, + ...basicDataProvider, id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', name: 'root', - excluded: false, - kqlQuery: '', queryMatch: { field: 'user.name', value: 'root', @@ -2247,11 +1525,9 @@ describe('Timeline', () => { }, }, { - enabled: true, + ...basicDataProvider, id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', name: 'success', - excluded: false, - kqlQuery: '', queryMatch: { field: 'auditd.result', value: 'success', @@ -2259,11 +1535,8 @@ describe('Timeline', () => { }, }, ], - enabled: true, - excluded: false, id: 'hosts-table-hostName-suricata-iowa', name: 'suricata-iowa', - kqlQuery: '', queryMatch: { field: 'host.name', value: 'suricata-iowa', @@ -2272,7 +1545,13 @@ describe('Timeline', () => { }, ]; - const multiDataProviderMock = set('foo.dataProviders', multiDataProvider, timelineByIdMock); + const multiDataProviderMock = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + dataProviders: multiDataProvider, + }, + }; const update = removeTimelineProvider({ id: 'foo', @@ -2280,51 +1559,40 @@ describe('Timeline', () => { timelineById: multiDataProviderMock, }); - expect(update).toEqual( - set( - 'foo.dataProviders', - [ + expect(update.foo.dataProviders).toEqual([ + { + ...basicDataProvider, + id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', + name: 'root', + queryMatch: { + field: 'user.name', + value: 'root', + operator: ':', + }, + and: [ { - enabled: true, - id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', - name: 'root', - excluded: false, - kqlQuery: '', + ...basicDataProvider, + id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', + name: 'success', queryMatch: { - field: 'user.name', - value: 'root', + field: 'auditd.result', + value: 'success', operator: ':', }, - and: [ - { - enabled: true, - id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', - name: 'success', - excluded: false, - kqlQuery: '', - queryMatch: { - field: 'auditd.result', - value: 'success', - operator: ':', - }, - }, - ], }, ], - timelineByIdMock - ) - ); + }, + ]); }); test('should remove only the first AND provider when the first AND is deleted, and there are multiple andProviders', () => { const multiDataProvider: DataProvider[] = [ { + ...basicDataProvider, and: [ { - enabled: true, + ...basicDataProvider, id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', name: 'root', - excluded: false, - kqlQuery: '', queryMatch: { field: 'user.name', value: 'root', @@ -2332,11 +1600,9 @@ describe('Timeline', () => { }, }, { - enabled: true, + ...basicDataProvider, id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', name: 'success', - excluded: false, - kqlQuery: '', queryMatch: { field: 'auditd.result', value: 'success', @@ -2344,11 +1610,8 @@ describe('Timeline', () => { }, }, ], - enabled: true, - excluded: false, id: 'hosts-table-hostName-suricata-iowa', name: 'suricata-iowa', - kqlQuery: '', queryMatch: { field: 'host.name', value: 'suricata-iowa', @@ -2357,7 +1620,13 @@ describe('Timeline', () => { }, ]; - const multiDataProviderMock = set('foo.dataProviders', multiDataProvider, timelineByIdMock); + const multiDataProviderMock = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + dataProviders: multiDataProvider, + }, + }; const update = removeTimelineProvider({ andProviderId: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', @@ -2366,52 +1635,41 @@ describe('Timeline', () => { timelineById: multiDataProviderMock, }); - expect(update).toEqual( - set( - 'foo.dataProviders', - [ + expect(update.foo.dataProviders).toEqual([ + { + ...basicDataProvider, + and: [ { - and: [ - { - enabled: true, - id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', - name: 'success', - excluded: false, - kqlQuery: '', - queryMatch: { - field: 'auditd.result', - value: 'success', - operator: ':', - }, - }, - ], - enabled: true, - excluded: false, - id: 'hosts-table-hostName-suricata-iowa', - name: 'suricata-iowa', - kqlQuery: '', + ...basicDataProvider, + id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', + name: 'success', queryMatch: { - field: 'host.name', - value: 'suricata-iowa', + field: 'auditd.result', + value: 'success', operator: ':', }, }, ], - timelineByIdMock - ) - ); + id: 'hosts-table-hostName-suricata-iowa', + name: 'suricata-iowa', + queryMatch: { + field: 'host.name', + value: 'suricata-iowa', + operator: ':', + }, + }, + ]); }); test('should remove only the second AND provider when the second AND is deleted, and there are multiple andProviders', () => { const multiDataProvider: DataProvider[] = [ { + ...basicDataProvider, and: [ { - enabled: true, + ...basicDataProvider, id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', name: 'root', - excluded: false, - kqlQuery: '', queryMatch: { field: 'user.name', value: 'root', @@ -2419,11 +1677,9 @@ describe('Timeline', () => { }, }, { - enabled: true, + ...basicDataProvider, id: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', name: 'success', - excluded: false, - kqlQuery: '', queryMatch: { field: 'auditd.result', value: 'success', @@ -2431,11 +1687,8 @@ describe('Timeline', () => { }, }, ], - enabled: true, - excluded: false, id: 'hosts-table-hostName-suricata-iowa', name: 'suricata-iowa', - kqlQuery: '', queryMatch: { field: 'host.name', value: 'suricata-iowa', @@ -2444,7 +1697,13 @@ describe('Timeline', () => { }, ]; - const multiDataProviderMock = set('foo.dataProviders', multiDataProvider, timelineByIdMock); + const multiDataProviderMock = { + ...timelineByIdMock, + foo: { + ...timelineByIdMock.foo, + dataProviders: multiDataProvider, + }, + }; const update = removeTimelineProvider({ andProviderId: 'executed-yioH7GoB9v5HJNSHKnp5-auditd_result-success', @@ -2453,40 +1712,30 @@ describe('Timeline', () => { timelineById: multiDataProviderMock, }); - expect(update).toEqual( - set( - 'foo.dataProviders', - [ + expect(update.foo.dataProviders).toEqual([ + { + ...basicDataProvider, + and: [ { - and: [ - { - enabled: true, - id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', - name: 'root', - excluded: false, - kqlQuery: '', - queryMatch: { - field: 'user.name', - value: 'root', - operator: ':', - }, - }, - ], - enabled: true, - excluded: false, - id: 'hosts-table-hostName-suricata-iowa', - name: 'suricata-iowa', - kqlQuery: '', + ...basicDataProvider, + id: 'socket_closed-MSoH7GoB9v5HJNSHRYj1-user_name-root', + name: 'root', queryMatch: { - field: 'host.name', - value: 'suricata-iowa', + field: 'user.name', + value: 'root', operator: ':', }, }, ], - timelineByIdMock - ) - ); + id: 'hosts-table-hostName-suricata-iowa', + name: 'suricata-iowa', + queryMatch: { + field: 'host.name', + value: 'suricata-iowa', + operator: ':', + }, + }, + ]); }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts index d15bce5e217fa4..1d956e02e7083c 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts @@ -44,6 +44,7 @@ import { updateDescription, updateEventType, updateHighlightedDropAndProviderId, + updateIndexNames, updateIsFavorite, updateIsLive, updateIsLoading, @@ -135,6 +136,7 @@ export const timelineReducer = reducerWithInitialState(initialTimelineState) show, columns, itemsPerPage, + indexNames, kqlQuery, sort, showCheckboxes, @@ -152,6 +154,7 @@ export const timelineReducer = reducerWithInitialState(initialTimelineState) filters, id, itemsPerPage, + indexNames, kqlQuery, sort, show, @@ -521,4 +524,14 @@ export const timelineReducer = reducerWithInitialState(initialTimelineState) ...state, insertTimeline, })) + .case(updateIndexNames, (state, { id, indexNames }) => ({ + ...state, + timelineById: { + ...state.timelineById, + [id]: { + ...state.timelineById[id], + indexNames, + }, + }, + })) .build(); diff --git a/x-pack/plugins/security_solution/scripts/beat_docs/build.js b/x-pack/plugins/security_solution/scripts/beat_docs/build.js new file mode 100644 index 00000000000000..9b3607593a5db2 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/beat_docs/build.js @@ -0,0 +1,233 @@ +/* + * 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. + */ + +require('../../../../../src/setup_node_env'); + +// eslint-disable-next-line import/no-extraneous-dependencies +const extract = require('extract-zip'); +const fs = require('fs'); +// eslint-disable-next-line import/no-extraneous-dependencies +const yaml = require('js-yaml'); +const https = require('https'); +// eslint-disable-next-line import/no-extraneous-dependencies +const { get, isArray, isEmpty, isNumber, isString, pick } = require('lodash'); +// eslint-disable-next-line import/no-extraneous-dependencies +const Q = require('q'); +// eslint-disable-next-line import/no-extraneous-dependencies +const rimraf = require('rimraf'); +const { resolve } = require('path'); +// eslint-disable-next-line import/no-extraneous-dependencies +const tar = require('tar'); +const zlib = require('zlib'); + +const OUTPUT_DIRECTORY = resolve('scripts', 'beat_docs'); +const OUTPUT_SERVER_DIRECTORY = resolve('server', 'utils', 'beat_schema'); + +const beats = [ + { + filePath: `${OUTPUT_DIRECTORY}/auditbeat-7.9.0-darwin-x86_64.tar.gz`, + index: 'auditbeat-*', + outputDir: `${OUTPUT_DIRECTORY}/auditbeat-7.9.0-darwin-x86_64`, + url: + 'https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-7.9.0-darwin-x86_64.tar.gz', + }, + { + filePath: `${OUTPUT_DIRECTORY}/filebeat-7.9.0-darwin-x86_64.tar.gz`, + index: 'filebeat-*', + outputDir: `${OUTPUT_DIRECTORY}/filebeat-7.9.0-darwin-x86_64`, + url: + 'https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.9.0-darwin-x86_64.tar.gz', + }, + { + filePath: `${OUTPUT_DIRECTORY}/packetbeat-7.9.0-darwin-x86_64.tar.gz`, + index: 'packetbeat-*', + outputDir: `${OUTPUT_DIRECTORY}/packetbeat-7.9.0-darwin-x86_64`, + url: + 'https://artifacts.elastic.co/downloads/beats/packetbeat/packetbeat-7.9.0-darwin-x86_64.tar.gz', + }, + { + filePath: `${OUTPUT_DIRECTORY}/winlogbeat-7.9.0-windows-x86_64.zip`, + index: 'winlogbeat-*', + outputDir: `${OUTPUT_DIRECTORY}`, + url: + 'https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-7.9.0-windows-x86_64.zip', + }, +]; + +const download = async (url, filepath) => { + const fileStream = fs.createWriteStream(filepath); + const deferred = Q.defer(); + + fileStream + .on('open', function () { + https.get(url, function (res) { + res.on('error', function (err) { + deferred.reject(err); + }); + + res.pipe(fileStream); + }); + }) + .on('error', function (err) { + deferred.reject(err); + }) + .on('finish', function () { + deferred.resolve(filepath); + }); + + return deferred.promise; +}; + +const paramsToPick = ['category', 'description', 'example', 'name', 'type', 'format']; + +const onlyStringOrNumber = (fields) => + Object.keys(fields).reduce((acc, item) => { + let value = get(fields, item); + if (item === 'description' && isString(value)) { + value = value.replace(/\n/g, ' '); + } + return { + ...acc, + [item]: isString(value) || isNumber(value) ? value : JSON.stringify(value), + }; + }, {}); + +const convertFieldsToHash = (schemaFields, beatFields, path) => + schemaFields.fields && isArray(schemaFields.fields) + ? schemaFields.fields.reduce((accumulator, item) => { + if (item.name) { + const attr = isEmpty(path) ? item.name : `${path}.${item.name}`; + const splitAttr = attr.split('.'); + const category = splitAttr.length === 1 ? 'base' : splitAttr[0]; + const myItem = { + ...item, + category, + name: attr, + }; + if (!isEmpty(item.fields)) { + return { + ...accumulator, + ...convertFieldsToHash(myItem, beatFields, attr), + }; + } else if (beatFields[attr] === undefined) { + return { + ...accumulator, + [attr]: onlyStringOrNumber(pick(myItem, paramsToPick)), + }; + } + } + return accumulator; + }, {}) + : {}; + +const convertSchemaToHash = (schema, beatFields) => { + return schema.reduce((accumulator, item) => { + if (item.fields != null && !isEmpty(item.fields)) { + return { + ...accumulator, + ...convertFieldsToHash(item, accumulator), + }; + } + return accumulator; + }, beatFields); +}; + +const manageZipFields = async (beat, filePath, beatFields) => + new Promise((resolve, reject) => { + extract(filePath, { dir: beat.outputDir }, (err) => { + if (err) { + return reject(new Error(err)); + } + console.log('building fields', beat.index); + const obj = yaml.load( + fs.readFileSync(`${beat.outputDir}/winlogbeat-7.9.0-windows-x86_64/fields.yml`, { + encoding: 'utf-8', + }) + ); + const eBeatFields = convertSchemaToHash(obj, beatFields); + console.log('deleting files', beat.index); + rimraf.sync(`${beat.outputDir}/winlogbeat-7.9.0-windows-x86_64`); + rimraf.sync(beat.filePath); + resolve(eBeatFields); + }); + }); + +const manageTarFields = async (beat, filePath, beatFields) => + new Promise((resolve, reject) => { + fs.createReadStream(filePath) + .pipe(zlib.createGunzip()) + .pipe( + tar.extract({ + sync: true, + cwd: OUTPUT_DIRECTORY, + filter: function (path) { + return path.includes('fields.yml'); + }, + }) + ) + .on('end', function (err) { + if (err) { + return reject(new Error(err)); + } + console.log('building fields', beat.index); + const obj = yaml.load( + fs.readFileSync(`${beat.outputDir}/fields.yml`, { encoding: 'utf-8' }) + ); + const ebeatFields = convertSchemaToHash(obj, beatFields); + console.log('deleting files', beat.index); + rimraf.sync(beat.outputDir); + rimraf.sync(beat.filePath); + resolve(ebeatFields); + }); + }); + +async function main() { + let beatFields = { + _id: { + category: 'base', + description: 'Each document has an _id that uniquely identifies it', + example: 'Y-6TfmcB0WOhS6qyMv3s', + name: '_id', + type: 'keyword', + }, + _index: { + category: 'base', + description: + 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', + example: 'auditbeat-8.0.0-2019.02.19-000001', + name: '_index', + type: 'keyword', + }, + }; + + for (const myBeat of beats) { + console.log('downloading', myBeat.index); + const filepath = await download(myBeat.url, myBeat.filePath); + if (myBeat.index === 'winlogbeat-*') { + beatFields = await manageZipFields(myBeat, filepath, beatFields); + } else { + beatFields = await manageTarFields(myBeat, filepath, beatFields); + } + console.log('done for', myBeat.index); + } + const body = `/* + * 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 { BeatFields } from '../../../common/search_strategy/security_solution/beat_fields'; + + /* eslint-disable @typescript-eslint/naming-convention */ + export const fieldsBeat: BeatFields = + ${JSON.stringify(beatFields, null, 2)}; + `; + fs.writeFileSync(`${OUTPUT_SERVER_DIRECTORY}/fields.ts`, body, 'utf-8'); +} + +if (require.main === module) { + main(); +} diff --git a/x-pack/plugins/security_solution/server/graphql/index.ts b/x-pack/plugins/security_solution/server/graphql/index.ts index 959aa4549d43f8..d23494e0eeaa65 100644 --- a/x-pack/plugins/security_solution/server/graphql/index.ts +++ b/x-pack/plugins/security_solution/server/graphql/index.ts @@ -11,11 +11,9 @@ import { authenticationsSchema } from './authentications'; import { ecsSchema } from './ecs'; import { eventsSchema } from './events'; import { hostsSchema } from './hosts'; -import { ipDetailsSchemas } from './ip_details'; import { kpiHostsSchema } from './kpi_hosts'; import { kpiNetworkSchema } from './kpi_network'; import { networkSchema } from './network'; -import { overviewSchema } from './overview'; import { dateSchema } from './scalar_date'; import { noteSchema } from './note'; import { pinnedEventSchema } from './pinned_event'; @@ -26,7 +24,6 @@ import { toNumberSchema } from './scalar_to_number_array'; import { sourceStatusSchema } from './source_status'; import { sourcesSchema } from './sources'; import { timelineSchema } from './timeline'; -import { uncommonProcessesSchema } from './uncommon_processes'; import { whoAmISchema } from './who_am_i'; import { matrixHistogramSchema } from './matrix_histogram'; export const schemas = [ @@ -39,19 +36,16 @@ export const schemas = [ toDateSchema, toBooleanSchema, hostsSchema, - ...ipDetailsSchemas, kpiNetworkSchema, kpiHostsSchema, matrixHistogramSchema, networkSchema, noteSchema, - overviewSchema, pinnedEventSchema, rootSchema, sourcesSchema, sourceStatusSchema, sharedSchema, timelineSchema, - uncommonProcessesSchema, whoAmISchema, ]; diff --git a/x-pack/plugins/security_solution/server/graphql/ip_details/resolvers.ts b/x-pack/plugins/security_solution/server/graphql/ip_details/resolvers.ts deleted file mode 100644 index d0e84026de473f..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/ip_details/resolvers.ts +++ /dev/null @@ -1,50 +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 { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; -import { IpDetails, UsersRequestOptions } from '../../lib/ip_details'; -import { createOptions, createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryIpOverviewResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export type QueryUsersResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export interface IDetailsResolversDeps { - ipDetails: IpDetails; -} - -export const createIpDetailsResolvers = ( - libs: IDetailsResolversDeps -): { - Source: { - IpOverview: QueryIpOverviewResolver; - Users: QueryUsersResolver; - }; -} => ({ - Source: { - async IpOverview(source, args, { req }, info) { - const options = { ...createOptions(source, args, info), ip: args.ip }; - return libs.ipDetails.getIpOverview(req, options); - }, - async Users(source, args, { req }, info) { - const options: UsersRequestOptions = { - ...createOptionsPaginated(source, args, info), - ip: args.ip, - sort: args.sort, - flowTarget: args.flowTarget, - }; - return libs.ipDetails.getUsers(req, options); - }, - }, -}); diff --git a/x-pack/plugins/security_solution/server/graphql/ip_details/schema.gql.ts b/x-pack/plugins/security_solution/server/graphql/ip_details/schema.gql.ts deleted file mode 100644 index 2531f8d169327b..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/ip_details/schema.gql.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -const ipOverviewSchema = gql` - type AutonomousSystemOrganization { - name: String - } - - type AutonomousSystem { - number: Float - organization: AutonomousSystemOrganization - } - - type Overview { - firstSeen: Date - lastSeen: Date - autonomousSystem: AutonomousSystem! - geo: GeoEcsFields! - } - - type IpOverviewData { - client: Overview - destination: Overview - host: HostEcsFields! - server: Overview - source: Overview - inspect: Inspect - } - - extend type Source { - IpOverview( - id: String - filterQuery: String - ip: String! - defaultIndex: [String!]! - docValueFields: [docValueFieldsInput!]! - ): IpOverviewData - } -`; - -const usersSchema = gql` - enum UsersFields { - name - count - } - - input UsersSortField { - field: UsersFields! - direction: Direction! - } - - type UsersItem { - name: String - id: ToStringArray - groupId: ToStringArray - groupName: ToStringArray - count: Float - } - - type UsersNode { - _id: String - timestamp: Date - user: UsersItem - } - - type UsersEdges { - node: UsersNode! - cursor: CursorType! - } - - type UsersData { - edges: [UsersEdges!]! - totalCount: Float! - pageInfo: PageInfoPaginated! - inspect: Inspect - } - - extend type Source { - Users( - filterQuery: String - id: String - ip: String! - pagination: PaginationInputPaginated! - sort: UsersSortField! - flowTarget: FlowTarget! - timerange: TimerangeInput! - defaultIndex: [String!]! - ): UsersData! - } -`; - -export const ipDetailsSchemas = [ipOverviewSchema, usersSchema]; diff --git a/x-pack/plugins/security_solution/server/graphql/overview/resolvers.ts b/x-pack/plugins/security_solution/server/graphql/overview/resolvers.ts deleted file mode 100644 index a7bafabb640928..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/overview/resolvers.ts +++ /dev/null @@ -1,45 +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 { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; -import { Overview } from '../../lib/overview'; -import { createOptions } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -export type QueryOverviewNetworkResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export type QueryOverviewHostResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export interface OverviewResolversDeps { - overview: Overview; -} - -export const createOverviewResolvers = ( - libs: OverviewResolversDeps -): { - Source: { - OverviewHost: QueryOverviewHostResolver; - OverviewNetwork: QueryOverviewNetworkResolver; - }; -} => ({ - Source: { - async OverviewNetwork(source, args, { req }, info) { - const options = { ...createOptions(source, args, info) }; - return libs.overview.getOverviewNetwork(req, options); - }, - async OverviewHost(source, args, { req }, info) { - const options = { ...createOptions(source, args, info) }; - return libs.overview.getOverviewHost(req, options); - }, - }, -}); diff --git a/x-pack/plugins/security_solution/server/graphql/overview/schema.gql.ts b/x-pack/plugins/security_solution/server/graphql/overview/schema.gql.ts deleted file mode 100644 index 7ab4f9fdb18d6c..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/overview/schema.gql.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const overviewSchema = gql` - type OverviewNetworkData { - auditbeatSocket: Float - filebeatCisco: Float - filebeatNetflow: Float - filebeatPanw: Float - filebeatSuricata: Float - filebeatZeek: Float - packetbeatDNS: Float - packetbeatFlow: Float - packetbeatTLS: Float - inspect: Inspect - } - - type OverviewHostData { - auditbeatAuditd: Float - auditbeatFIM: Float - auditbeatLogin: Float - auditbeatPackage: Float - auditbeatProcess: Float - auditbeatUser: Float - endgameDns: Float - endgameFile: Float - endgameImageLoad: Float - endgameNetwork: Float - endgameProcess: Float - endgameRegistry: Float - endgameSecurity: Float - filebeatSystemModule: Float - winlogbeatSecurity: Float - winlogbeatMWSysmonOperational: Float - inspect: Inspect - } - - extend type Source { - OverviewNetwork( - id: String - timerange: TimerangeInput! - filterQuery: String - defaultIndex: [String!]! - ): OverviewNetworkData - OverviewHost( - id: String - timerange: TimerangeInput! - filterQuery: String - defaultIndex: [String!]! - ): OverviewHostData - } -`; diff --git a/x-pack/plugins/security_solution/server/graphql/source_status/schema.gql.ts b/x-pack/plugins/security_solution/server/graphql/source_status/schema.gql.ts index 3062113f1b6351..60dc563a3e8d2c 100644 --- a/x-pack/plugins/security_solution/server/graphql/source_status/schema.gql.ts +++ b/x-pack/plugins/security_solution/server/graphql/source_status/schema.gql.ts @@ -37,6 +37,6 @@ export const sourceStatusSchema = gql` "Whether the configured alias or wildcard pattern resolve to any auditbeat indices" indicesExist(defaultIndex: [String!]!): Boolean! "The list of fields defined in the index mappings" - indexFields(defaultIndex: [String!]!): [IndexField!]! + indexFields(defaultIndex: [String!]!): [String!]! } `; diff --git a/x-pack/plugins/security_solution/server/graphql/timeline/schema.gql.ts b/x-pack/plugins/security_solution/server/graphql/timeline/schema.gql.ts index 573539e1bb54f6..70596a1b41ea09 100644 --- a/x-pack/plugins/security_solution/server/graphql/timeline/schema.gql.ts +++ b/x-pack/plugins/security_solution/server/graphql/timeline/schema.gql.ts @@ -167,6 +167,7 @@ export const timelineSchema = gql` filters: [FilterTimelineInput!] kqlMode: String kqlQuery: SerializedFilterQueryInput + indexNames: [String!] title: String templateTimelineId: String templateTimelineVersion: Int @@ -269,6 +270,7 @@ export const timelineSchema = gql` filters: [FilterTimelineResult!] kqlMode: String kqlQuery: SerializedFilterQueryResult + indexNames: [String!] notes: [NoteResult!] noteIds: [String!] pinnedEventIds: [String!] diff --git a/x-pack/plugins/security_solution/server/graphql/types.ts b/x-pack/plugins/security_solution/server/graphql/types.ts index ed3abd25df882e..5f370ab1b8c9f7 100644 --- a/x-pack/plugins/security_solution/server/graphql/types.ts +++ b/x-pack/plugins/security_solution/server/graphql/types.ts @@ -75,12 +75,6 @@ export interface HostsSortField { direction: Direction; } -export interface UsersSortField { - field: UsersFields; - - direction: Direction; -} - export interface NetworkTopTablesSortField { field: NetworkTopTablesFields; @@ -134,6 +128,8 @@ export interface TimelineInput { kqlQuery?: Maybe; + indexNames?: Maybe; + title?: Maybe; templateTimelineId?: Maybe; @@ -309,18 +305,6 @@ export enum HostPolicyResponseActionStatus { warning = 'warning', } -export enum UsersFields { - name = 'name', - count = 'count', -} - -export enum FlowTarget { - client = 'client', - destination = 'destination', - server = 'server', - source = 'source', -} - export enum HistogramType { authentications = 'authentications', anomalies = 'anomalies', @@ -410,15 +394,18 @@ export enum NetworkHttpFields { statuses = 'statuses', } +export enum FlowTarget { + client = 'client', + destination = 'destination', + server = 'server', + source = 'source', +} + export enum FlowDirection { uniDirectional = 'uniDirectional', biDirectional = 'biDirectional', } -export type ToStringArrayNoNullable = any; - -export type ToIFieldSubTypeNonNullable = any; - export type ToStringArray = string[] | string; export type Date = string; @@ -433,6 +420,10 @@ export type ToAny = any; export type EsValue = any; +export type ToStringArrayNoNullable = any; + +export type ToIFieldSubTypeNonNullable = any; + // ==================================================== // Scalars // ==================================================== @@ -535,10 +526,6 @@ export interface Source { HostFirstLastSeen: FirstLastSeenHost; - IpOverview?: Maybe; - - Users: UsersData; - KpiNetwork?: Maybe; KpiHosts: KpiHostsData; @@ -556,12 +543,6 @@ export interface Source { NetworkDnsHistogram: NetworkDsOverTimeData; NetworkHttp: NetworkHttpData; - - OverviewNetwork?: Maybe; - - OverviewHost?: Maybe; - /** 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?: Maybe; } @@ -593,33 +574,7 @@ export interface SourceStatus { /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ indicesExist: boolean; /** The list of fields defined in the index mappings */ - indexFields: IndexField[]; -} - -/** A descriptor of a field in an index */ -export interface IndexField { - /** Where the field belong */ - category: string; - /** Example of field's value */ - example?: Maybe; - /** whether the field's belong to an alias index */ - indexes: (Maybe)[]; - /** 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; - /** Description of the field */ - description?: Maybe; - - format?: Maybe; - /** the elastic type as mapped in the index */ - esTypes?: Maybe; - - subType?: Maybe; + indexFields: string[]; } export interface AuthenticationsData { @@ -1494,76 +1449,6 @@ export interface FirstLastSeenHost { lastSeen?: Maybe; } -export interface IpOverviewData { - client?: Maybe; - - destination?: Maybe; - - host: HostEcsFields; - - server?: Maybe; - - source?: Maybe; - - inspect?: Maybe; -} - -export interface Overview { - firstSeen?: Maybe; - - lastSeen?: Maybe; - - autonomousSystem: AutonomousSystem; - - geo: GeoEcsFields; -} - -export interface AutonomousSystem { - number?: Maybe; - - organization?: Maybe; -} - -export interface AutonomousSystemOrganization { - name?: Maybe; -} - -export interface UsersData { - edges: UsersEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UsersEdges { - node: UsersNode; - - cursor: CursorType; -} - -export interface UsersNode { - _id?: Maybe; - - timestamp?: Maybe; - - user?: Maybe; -} - -export interface UsersItem { - name?: Maybe; - - id?: Maybe; - - groupId?: Maybe; - - groupName?: Maybe; - - count?: Maybe; -} - export interface KpiNetworkData { networkEvents?: Maybe; @@ -1860,92 +1745,6 @@ export interface NetworkHttpItem { statuses: string[]; } -export interface OverviewNetworkData { - auditbeatSocket?: Maybe; - - filebeatCisco?: Maybe; - - filebeatNetflow?: Maybe; - - filebeatPanw?: Maybe; - - filebeatSuricata?: Maybe; - - filebeatZeek?: Maybe; - - packetbeatDNS?: Maybe; - - packetbeatFlow?: Maybe; - - packetbeatTLS?: Maybe; - - inspect?: Maybe; -} - -export interface OverviewHostData { - auditbeatAuditd?: Maybe; - - auditbeatFIM?: Maybe; - - auditbeatLogin?: Maybe; - - auditbeatPackage?: Maybe; - - auditbeatProcess?: Maybe; - - auditbeatUser?: Maybe; - - endgameDns?: Maybe; - - endgameFile?: Maybe; - - endgameImageLoad?: Maybe; - - endgameNetwork?: Maybe; - - endgameProcess?: Maybe; - - endgameRegistry?: Maybe; - - endgameSecurity?: Maybe; - - filebeatSystemModule?: Maybe; - - winlogbeatSecurity?: Maybe; - - winlogbeatMWSysmonOperational?: Maybe; - - inspect?: Maybe; -} - -export interface UncommonProcessesData { - edges: UncommonProcessesEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface UncommonProcessesEdges { - node: UncommonProcessItem; - - cursor: CursorType; -} - -export interface UncommonProcessItem { - _id: string; - - instances: number; - - process: ProcessEcsFields; - - hosts: HostEcsFields[]; - - user?: Maybe; -} - export interface SayMyName { /** The id of the source */ appName: string; @@ -1978,6 +1777,8 @@ export interface TimelineResult { kqlQuery?: Maybe; + indexNames?: Maybe; + notes?: Maybe; noteIds?: Maybe; @@ -2250,6 +2051,32 @@ export interface HostFields { type?: Maybe; } +/** A descriptor of a field in an index */ +export interface IndexField { + /** Where the field belong */ + category: string; + /** Example of field's value */ + example?: Maybe; + /** whether the field's belong to an alias index */ + indexes: (Maybe)[]; + /** 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; + /** Description of the field */ + description?: Maybe; + + format?: Maybe; + /** the elastic type as mapped in the index */ + esTypes?: Maybe; + + subType?: Maybe; +} + // ==================================================== // Arguments // ==================================================== @@ -2372,34 +2199,6 @@ export interface HostFirstLastSeenSourceArgs { docValueFields: DocValueFieldsInput[]; } -export interface IpOverviewSourceArgs { - id?: Maybe; - - filterQuery?: Maybe; - - ip: string; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; -} -export interface UsersSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: UsersSortField; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} export interface KpiNetworkSourceArgs { id?: Maybe; @@ -2515,33 +2314,6 @@ export interface NetworkHttpSourceArgs { defaultIndex: string[]; } -export interface OverviewNetworkSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface OverviewHostSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} -export interface UncommonProcessesSourceArgs { - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - filterQuery?: Maybe; - - defaultIndex: string[]; -} export interface IndicesExistSourceStatusArgs { defaultIndex: string[]; } @@ -2953,10 +2725,6 @@ export namespace SourceResolvers { HostFirstLastSeen?: HostFirstLastSeenResolver; - IpOverview?: IpOverviewResolver, TypeParent, TContext>; - - Users?: UsersResolver; - KpiNetwork?: KpiNetworkResolver, TypeParent, TContext>; KpiHosts?: KpiHostsResolver; @@ -2978,12 +2746,6 @@ export namespace SourceResolvers { NetworkDnsHistogram?: NetworkDnsHistogramResolver; NetworkHttp?: NetworkHttpResolver; - - OverviewNetwork?: OverviewNetworkResolver, TypeParent, TContext>; - - OverviewHost?: OverviewHostResolver, TypeParent, TContext>; - /** 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, TypeParent, TContext>; } @@ -3125,68 +2887,27 @@ export namespace SourceResolvers { docValueFields: DocValueFieldsInput[]; } - export type IpOverviewResolver< - R = Maybe, + export type KpiNetworkResolver< + R = Maybe, Parent = Source, TContext = SiemContext - > = Resolver; - export interface IpOverviewArgs { + > = Resolver; + export interface KpiNetworkArgs { id?: Maybe; - filterQuery?: Maybe; + timerange: TimerangeInput; - ip: string; + filterQuery?: Maybe; defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; } - export type UsersResolver = Resolver< - R, - Parent, - TContext, - UsersArgs - >; - export interface UsersArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: UsersSortField; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; - } - - export type KpiNetworkResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface KpiNetworkArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; - } - - export type KpiHostsResolver< - R = KpiHostsData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface KpiHostsArgs { + export type KpiHostsResolver< + R = KpiHostsData, + Parent = Source, + TContext = SiemContext + > = Resolver; + export interface KpiHostsArgs { id?: Maybe; timerange: TimerangeInput; @@ -3335,51 +3056,6 @@ export namespace SourceResolvers { defaultIndex: string[]; } - export type OverviewNetworkResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface OverviewNetworkArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; - } - - export type OverviewHostResolver< - R = Maybe, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface OverviewHostArgs { - id?: Maybe; - - timerange: TimerangeInput; - - filterQuery?: Maybe; - - defaultIndex: string[]; - } - - export type UncommonProcessesResolver< - R = UncommonProcessesData, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface UncommonProcessesArgs { - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - filterQuery?: Maybe; - - defaultIndex: string[]; - } - export type WhoAmIResolver< R = Maybe, Parent = Source, @@ -3453,7 +3129,7 @@ export namespace SourceStatusResolvers { /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ indicesExist?: IndicesExistResolver; /** The list of fields defined in the index mappings */ - indexFields?: IndexFieldsResolver; + indexFields?: IndexFieldsResolver; } export type IndicesExistResolver< @@ -3466,7 +3142,7 @@ export namespace SourceStatusResolvers { } export type IndexFieldsResolver< - R = IndexField[], + R = string[], Parent = SourceStatus, TContext = SiemContext > = Resolver; @@ -3474,89 +3150,6 @@ export namespace SourceStatusResolvers { defaultIndex: string[]; } } -/** A descriptor of a field in an index */ -export namespace IndexFieldResolvers { - export interface Resolvers { - /** Where the field belong */ - category?: CategoryResolver; - /** Example of field's value */ - example?: ExampleResolver, TypeParent, TContext>; - /** whether the field's belong to an alias index */ - indexes?: IndexesResolver<(Maybe)[], TypeParent, TContext>; - /** 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; - /** Description of the field */ - description?: DescriptionResolver, TypeParent, TContext>; - - format?: FormatResolver, TypeParent, TContext>; - /** the elastic type as mapped in the index */ - esTypes?: EsTypesResolver, TypeParent, TContext>; - - subType?: SubTypeResolver, TypeParent, TContext>; - } - - export type CategoryResolver = Resolver< - R, - Parent, - TContext - >; - export type ExampleResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type IndexesResolver< - R = (Maybe)[], - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type NameResolver = Resolver< - R, - Parent, - TContext - >; - export type TypeResolver = Resolver< - R, - Parent, - TContext - >; - export type SearchableResolver< - R = boolean, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type AggregatableResolver< - R = boolean, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type DescriptionResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type FormatResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type EsTypesResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; - export type SubTypeResolver< - R = Maybe, - Parent = IndexField, - TContext = SiemContext - > = Resolver; -} export namespace AuthenticationsDataResolvers { export interface Resolvers { @@ -6472,349 +6065,120 @@ export namespace FirstLastSeenHostResolvers { > = Resolver; } -export namespace IpOverviewDataResolvers { - export interface Resolvers { - client?: ClientResolver, TypeParent, TContext>; +export namespace KpiNetworkDataResolvers { + export interface Resolvers { + networkEvents?: NetworkEventsResolver, TypeParent, TContext>; + + uniqueFlowId?: UniqueFlowIdResolver, TypeParent, TContext>; + + uniqueSourcePrivateIps?: UniqueSourcePrivateIpsResolver, TypeParent, TContext>; + + uniqueSourcePrivateIpsHistogram?: UniqueSourcePrivateIpsHistogramResolver< + Maybe, + TypeParent, + TContext + >; - destination?: DestinationResolver, TypeParent, TContext>; + uniqueDestinationPrivateIps?: UniqueDestinationPrivateIpsResolver< + Maybe, + TypeParent, + TContext + >; - host?: HostResolver; + uniqueDestinationPrivateIpsHistogram?: UniqueDestinationPrivateIpsHistogramResolver< + Maybe, + TypeParent, + TContext + >; - server?: ServerResolver, TypeParent, TContext>; + dnsQueries?: DnsQueriesResolver, TypeParent, TContext>; - source?: SourceResolver, TypeParent, TContext>; + tlsHandshakes?: TlsHandshakesResolver, TypeParent, TContext>; inspect?: InspectResolver, TypeParent, TContext>; } - export type ClientResolver< - R = Maybe, - Parent = IpOverviewData, + export type NetworkEventsResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type DestinationResolver< - R = Maybe, - Parent = IpOverviewData, + export type UniqueFlowIdResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type HostResolver< - R = HostEcsFields, - Parent = IpOverviewData, + export type UniqueSourcePrivateIpsResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type ServerResolver< - R = Maybe, - Parent = IpOverviewData, + export type UniqueSourcePrivateIpsHistogramResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = IpOverviewData, + export type UniqueDestinationPrivateIpsResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = IpOverviewData, + export type UniqueDestinationPrivateIpsHistogramResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; -} - -export namespace OverviewResolvers { - export interface Resolvers { - firstSeen?: FirstSeenResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - - autonomousSystem?: AutonomousSystemResolver; - - geo?: GeoResolver; - } - - export type FirstSeenResolver< - R = Maybe, - Parent = Overview, + export type DnsQueriesResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type LastSeenResolver< - R = Maybe, - Parent = Overview, + export type TlsHandshakesResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type AutonomousSystemResolver< - R = AutonomousSystem, - Parent = Overview, + export type InspectResolver< + R = Maybe, + Parent = KpiNetworkData, TContext = SiemContext > = Resolver; - export type GeoResolver = Resolver< - R, - Parent, - TContext - >; } -export namespace AutonomousSystemResolvers { - export interface Resolvers { - number?: NumberResolver, TypeParent, TContext>; +export namespace KpiNetworkHistogramDataResolvers { + export interface Resolvers { + x?: XResolver, TypeParent, TContext>; - organization?: OrganizationResolver, TypeParent, TContext>; + y?: YResolver, TypeParent, TContext>; } - export type NumberResolver< + export type XResolver< R = Maybe, - Parent = AutonomousSystem, + Parent = KpiNetworkHistogramData, TContext = SiemContext > = Resolver; - export type OrganizationResolver< - R = Maybe, - Parent = AutonomousSystem, + export type YResolver< + R = Maybe, + Parent = KpiNetworkHistogramData, TContext = SiemContext > = Resolver; } -export namespace AutonomousSystemOrganizationResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - } +export namespace KpiHostsDataResolvers { + export interface Resolvers { + hosts?: HostsResolver, TypeParent, TContext>; - export type NameResolver< - R = Maybe, - Parent = AutonomousSystemOrganization, - TContext = SiemContext - > = Resolver; -} + hostsHistogram?: HostsHistogramResolver, TypeParent, TContext>; -export namespace UsersDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; + authSuccess?: AuthSuccessResolver, TypeParent, TContext>; - totalCount?: TotalCountResolver; + authSuccessHistogram?: AuthSuccessHistogramResolver< + Maybe, + TypeParent, + TContext + >; - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = UsersEdges[], - Parent = UsersData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver = Resolver< - R, - Parent, - TContext - >; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = UsersData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = UsersData, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver = Resolver< - R, - Parent, - TContext - >; - export type CursorResolver< - R = CursorType, - Parent = UsersEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersNodeResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - timestamp?: TimestampResolver, TypeParent, TContext>; - - user?: UserResolver, TypeParent, TContext>; - } - - export type _IdResolver, Parent = UsersNode, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type TimestampResolver< - R = Maybe, - Parent = UsersNode, - TContext = SiemContext - > = Resolver; - export type UserResolver< - R = Maybe, - Parent = UsersNode, - TContext = SiemContext - > = Resolver; -} - -export namespace UsersItemResolvers { - export interface Resolvers { - name?: NameResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - groupId?: GroupIdResolver, TypeParent, TContext>; - - groupName?: GroupNameResolver, TypeParent, TContext>; - - count?: CountResolver, TypeParent, TContext>; - } - - export type NameResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type GroupIdResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type GroupNameResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; - export type CountResolver< - R = Maybe, - Parent = UsersItem, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiNetworkDataResolvers { - export interface Resolvers { - networkEvents?: NetworkEventsResolver, TypeParent, TContext>; - - uniqueFlowId?: UniqueFlowIdResolver, TypeParent, TContext>; - - uniqueSourcePrivateIps?: UniqueSourcePrivateIpsResolver, TypeParent, TContext>; - - uniqueSourcePrivateIpsHistogram?: UniqueSourcePrivateIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueDestinationPrivateIps?: UniqueDestinationPrivateIpsResolver< - Maybe, - TypeParent, - TContext - >; - - uniqueDestinationPrivateIpsHistogram?: UniqueDestinationPrivateIpsHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - dnsQueries?: DnsQueriesResolver, TypeParent, TContext>; - - tlsHandshakes?: TlsHandshakesResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type NetworkEventsResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueFlowIdResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueSourcePrivateIpsResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueSourcePrivateIpsHistogramResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationPrivateIpsResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type UniqueDestinationPrivateIpsHistogramResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type DnsQueriesResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type TlsHandshakesResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = KpiNetworkData, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiNetworkHistogramDataResolvers { - export interface Resolvers { - x?: XResolver, TypeParent, TContext>; - - y?: YResolver, TypeParent, TContext>; - } - - export type XResolver< - R = Maybe, - Parent = KpiNetworkHistogramData, - TContext = SiemContext - > = Resolver; - export type YResolver< - R = Maybe, - Parent = KpiNetworkHistogramData, - TContext = SiemContext - > = Resolver; -} - -export namespace KpiHostsDataResolvers { - export interface Resolvers { - hosts?: HostsResolver, TypeParent, TContext>; - - hostsHistogram?: HostsHistogramResolver, TypeParent, TContext>; - - authSuccess?: AuthSuccessResolver, TypeParent, TContext>; - - authSuccessHistogram?: AuthSuccessHistogramResolver< - Maybe, - TypeParent, - TContext - >; - - authFailure?: AuthFailureResolver, TypeParent, TContext>; + authFailure?: AuthFailureResolver, TypeParent, TContext>; authFailureHistogram?: AuthFailureHistogramResolver< Maybe, @@ -7733,301 +7097,6 @@ export namespace NetworkHttpItemResolvers { > = Resolver; } -export namespace OverviewNetworkDataResolvers { - export interface Resolvers { - auditbeatSocket?: AuditbeatSocketResolver, TypeParent, TContext>; - - filebeatCisco?: FilebeatCiscoResolver, TypeParent, TContext>; - - filebeatNetflow?: FilebeatNetflowResolver, TypeParent, TContext>; - - filebeatPanw?: FilebeatPanwResolver, TypeParent, TContext>; - - filebeatSuricata?: FilebeatSuricataResolver, TypeParent, TContext>; - - filebeatZeek?: FilebeatZeekResolver, TypeParent, TContext>; - - packetbeatDNS?: PacketbeatDnsResolver, TypeParent, TContext>; - - packetbeatFlow?: PacketbeatFlowResolver, TypeParent, TContext>; - - packetbeatTLS?: PacketbeatTlsResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type AuditbeatSocketResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatCiscoResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatNetflowResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatPanwResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatSuricataResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type FilebeatZeekResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type PacketbeatDnsResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type PacketbeatFlowResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type PacketbeatTlsResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = OverviewNetworkData, - TContext = SiemContext - > = Resolver; -} - -export namespace OverviewHostDataResolvers { - export interface Resolvers { - auditbeatAuditd?: AuditbeatAuditdResolver, TypeParent, TContext>; - - auditbeatFIM?: AuditbeatFimResolver, TypeParent, TContext>; - - auditbeatLogin?: AuditbeatLoginResolver, TypeParent, TContext>; - - auditbeatPackage?: AuditbeatPackageResolver, TypeParent, TContext>; - - auditbeatProcess?: AuditbeatProcessResolver, TypeParent, TContext>; - - auditbeatUser?: AuditbeatUserResolver, TypeParent, TContext>; - - endgameDns?: EndgameDnsResolver, TypeParent, TContext>; - - endgameFile?: EndgameFileResolver, TypeParent, TContext>; - - endgameImageLoad?: EndgameImageLoadResolver, TypeParent, TContext>; - - endgameNetwork?: EndgameNetworkResolver, TypeParent, TContext>; - - endgameProcess?: EndgameProcessResolver, TypeParent, TContext>; - - endgameRegistry?: EndgameRegistryResolver, TypeParent, TContext>; - - endgameSecurity?: EndgameSecurityResolver, TypeParent, TContext>; - - filebeatSystemModule?: FilebeatSystemModuleResolver, TypeParent, TContext>; - - winlogbeatSecurity?: WinlogbeatSecurityResolver, TypeParent, TContext>; - - winlogbeatMWSysmonOperational?: WinlogbeatMwSysmonOperationalResolver< - Maybe, - TypeParent, - TContext - >; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type AuditbeatAuditdResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatFimResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatLoginResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatPackageResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatProcessResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type AuditbeatUserResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameDnsResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameFileResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameImageLoadResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameNetworkResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameProcessResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameRegistryResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type EndgameSecurityResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type FilebeatSystemModuleResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type WinlogbeatSecurityResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type WinlogbeatMwSysmonOperationalResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = OverviewHostData, - TContext = SiemContext - > = Resolver; -} - -export namespace UncommonProcessesDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = UncommonProcessesEdges[], - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = UncommonProcessesData, - TContext = SiemContext - > = Resolver; -} - -export namespace UncommonProcessesEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = UncommonProcessItem, - Parent = UncommonProcessesEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = UncommonProcessesEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace UncommonProcessItemResolvers { - export interface Resolvers { - _id?: _IdResolver; - - instances?: InstancesResolver; - - process?: ProcessResolver; - - hosts?: HostsResolver; - - user?: UserResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = string, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type InstancesResolver< - R = number, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type ProcessResolver< - R = ProcessEcsFields, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type HostsResolver< - R = HostEcsFields[], - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; - export type UserResolver< - R = Maybe, - Parent = UncommonProcessItem, - TContext = SiemContext - > = Resolver; -} - export namespace SayMyNameResolvers { export interface Resolvers { /** The id of the source */ @@ -8073,6 +7142,8 @@ export namespace TimelineResultResolvers { kqlQuery?: KqlQueryResolver, TypeParent, TContext>; + indexNames?: IndexNamesResolver, TypeParent, TContext>; + notes?: NotesResolver, TypeParent, TContext>; noteIds?: NoteIdsResolver, TypeParent, TContext>; @@ -8173,6 +7244,11 @@ export namespace TimelineResultResolvers { Parent = TimelineResult, TContext = SiemContext > = Resolver; + export type IndexNamesResolver< + R = Maybe, + Parent = TimelineResult, + TContext = SiemContext + > = Resolver; export type NotesResolver< R = Maybe, Parent = TimelineResult, @@ -9121,6 +8197,89 @@ export namespace HostFieldsResolvers { TContext = SiemContext > = Resolver; } +/** A descriptor of a field in an index */ +export namespace IndexFieldResolvers { + export interface Resolvers { + /** Where the field belong */ + category?: CategoryResolver; + /** Example of field's value */ + example?: ExampleResolver, TypeParent, TContext>; + /** whether the field's belong to an alias index */ + indexes?: IndexesResolver<(Maybe)[], TypeParent, TContext>; + /** 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; + /** Description of the field */ + description?: DescriptionResolver, TypeParent, TContext>; + + format?: FormatResolver, TypeParent, TContext>; + /** the elastic type as mapped in the index */ + esTypes?: EsTypesResolver, TypeParent, TContext>; + + subType?: SubTypeResolver, TypeParent, TContext>; + } + + export type CategoryResolver = Resolver< + R, + Parent, + TContext + >; + export type ExampleResolver< + R = Maybe, + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type IndexesResolver< + R = (Maybe)[], + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type NameResolver = Resolver< + R, + Parent, + TContext + >; + export type TypeResolver = Resolver< + R, + Parent, + TContext + >; + export type SearchableResolver< + R = boolean, + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type AggregatableResolver< + R = boolean, + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type DescriptionResolver< + R = Maybe, + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type FormatResolver< + R = Maybe, + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type EsTypesResolver< + R = Maybe, + Parent = IndexField, + TContext = SiemContext + > = Resolver; + export type SubTypeResolver< + R = Maybe, + Parent = IndexField, + TContext = SiemContext + > = Resolver; +} /** Directs the executor to skip this field or fragment when the `if` argument is true. */ export type SkipDirectiveResolver = DirectiveResolverFn< @@ -9155,14 +8314,6 @@ export interface DeprecatedDirectiveArgs { reason?: string; } -export interface ToStringArrayNoNullableScalarConfig - extends GraphQLScalarTypeConfig { - name: 'ToStringArrayNoNullable'; -} -export interface ToIFieldSubTypeNonNullableScalarConfig - extends GraphQLScalarTypeConfig { - name: 'ToIFieldSubTypeNonNullable'; -} export interface ToStringArrayScalarConfig extends GraphQLScalarTypeConfig { name: 'ToStringArray'; } @@ -9184,6 +8335,14 @@ export interface ToAnyScalarConfig extends GraphQLScalarTypeConfig { export interface EsValueScalarConfig extends GraphQLScalarTypeConfig { name: 'EsValue'; } +export interface ToStringArrayNoNullableScalarConfig + extends GraphQLScalarTypeConfig { + name: 'ToStringArrayNoNullable'; +} +export interface ToIFieldSubTypeNonNullableScalarConfig + extends GraphQLScalarTypeConfig { + name: 'ToIFieldSubTypeNonNullable'; +} export type IResolvers = { Query?: QueryResolvers.Resolvers; @@ -9194,7 +8353,6 @@ export type IResolvers = { SourceConfiguration?: SourceConfigurationResolvers.Resolvers; SourceFields?: SourceFieldsResolvers.Resolvers; SourceStatus?: SourceStatusResolvers.Resolvers; - IndexField?: IndexFieldResolvers.Resolvers; AuthenticationsData?: AuthenticationsDataResolvers.Resolvers; AuthenticationsEdges?: AuthenticationsEdgesResolvers.Resolvers; AuthenticationItem?: AuthenticationItemResolvers.Resolvers; @@ -9270,14 +8428,6 @@ export type IResolvers = { CloudMachine?: CloudMachineResolvers.Resolvers; EndpointFields?: EndpointFieldsResolvers.Resolvers; FirstLastSeenHost?: FirstLastSeenHostResolvers.Resolvers; - IpOverviewData?: IpOverviewDataResolvers.Resolvers; - Overview?: OverviewResolvers.Resolvers; - AutonomousSystem?: AutonomousSystemResolvers.Resolvers; - AutonomousSystemOrganization?: AutonomousSystemOrganizationResolvers.Resolvers; - UsersData?: UsersDataResolvers.Resolvers; - UsersEdges?: UsersEdgesResolvers.Resolvers; - UsersNode?: UsersNodeResolvers.Resolvers; - UsersItem?: UsersItemResolvers.Resolvers; KpiNetworkData?: KpiNetworkDataResolvers.Resolvers; KpiNetworkHistogramData?: KpiNetworkHistogramDataResolvers.Resolvers; KpiHostsData?: KpiHostsDataResolvers.Resolvers; @@ -9306,11 +8456,6 @@ export type IResolvers = { NetworkHttpData?: NetworkHttpDataResolvers.Resolvers; NetworkHttpEdges?: NetworkHttpEdgesResolvers.Resolvers; NetworkHttpItem?: NetworkHttpItemResolvers.Resolvers; - OverviewNetworkData?: OverviewNetworkDataResolvers.Resolvers; - OverviewHostData?: OverviewHostDataResolvers.Resolvers; - UncommonProcessesData?: UncommonProcessesDataResolvers.Resolvers; - UncommonProcessesEdges?: UncommonProcessesEdgesResolvers.Resolvers; - UncommonProcessItem?: UncommonProcessItemResolvers.Resolvers; SayMyName?: SayMyNameResolvers.Resolvers; TimelineResult?: TimelineResultResolvers.Resolvers; ColumnHeaderResult?: ColumnHeaderResultResolvers.Resolvers; @@ -9333,8 +8478,7 @@ export type IResolvers = { EventsTimelineData?: EventsTimelineDataResolvers.Resolvers; OsFields?: OsFieldsResolvers.Resolvers; HostFields?: HostFieldsResolvers.Resolvers; - ToStringArrayNoNullable?: GraphQLScalarType; - ToIFieldSubTypeNonNullable?: GraphQLScalarType; + IndexField?: IndexFieldResolvers.Resolvers; ToStringArray?: GraphQLScalarType; Date?: GraphQLScalarType; ToNumberArray?: GraphQLScalarType; @@ -9342,6 +8486,8 @@ export type IResolvers = { ToBooleanArray?: GraphQLScalarType; ToAny?: GraphQLScalarType; EsValue?: GraphQLScalarType; + ToStringArrayNoNullable?: GraphQLScalarType; + ToIFieldSubTypeNonNullable?: GraphQLScalarType; } & { [typeName: string]: never }; export type IDirectiveResolvers = { diff --git a/x-pack/plugins/security_solution/server/graphql/uncommon_processes/resolvers.ts b/x-pack/plugins/security_solution/server/graphql/uncommon_processes/resolvers.ts deleted file mode 100644 index 03d3c3d1a1fe4f..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/uncommon_processes/resolvers.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; -import { UncommonProcesses } from '../../lib/uncommon_processes'; -import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -type QueryUncommonProcessesResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export interface UncommonProcessesResolversDeps { - uncommonProcesses: UncommonProcesses; -} - -export const createUncommonProcessesResolvers = ( - libs: UncommonProcessesResolversDeps -): { - Source: { - UncommonProcesses: QueryUncommonProcessesResolver; - }; -} => ({ - Source: { - async UncommonProcesses(source, args, { req }, info) { - const options = createOptionsPaginated(source, args, info); - return libs.uncommonProcesses.getUncommonProcesses(req, options); - }, - }, -}); diff --git a/x-pack/plugins/security_solution/server/graphql/uncommon_processes/schema.gql.ts b/x-pack/plugins/security_solution/server/graphql/uncommon_processes/schema.gql.ts deleted file mode 100644 index 36a3da6779172b..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/uncommon_processes/schema.gql.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const uncommonProcessesSchema = gql` - type UncommonProcessItem { - _id: String! - instances: Float! - process: ProcessEcsFields! - hosts: [HostEcsFields!]! - user: UserEcsFields - } - - type UncommonProcessesEdges { - node: UncommonProcessItem! - cursor: CursorType! - } - - type UncommonProcessesData { - edges: [UncommonProcessesEdges!]! - totalCount: Float! - pageInfo: PageInfoPaginated! - inspect: Inspect - } - - extend type Source { - "Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified" - UncommonProcesses( - timerange: TimerangeInput! - pagination: PaginationInputPaginated! - filterQuery: String - defaultIndex: [String!]! - ): UncommonProcessesData! - } -`; diff --git a/x-pack/plugins/security_solution/server/init_server.ts b/x-pack/plugins/security_solution/server/init_server.ts index 2ef42eaee4b986..3d2833f1c6c607 100644 --- a/x-pack/plugins/security_solution/server/init_server.ts +++ b/x-pack/plugins/security_solution/server/init_server.ts @@ -10,13 +10,11 @@ import { createAuthenticationsResolvers } from './graphql/authentications'; import { createScalarToStringArrayValueResolvers } from './graphql/ecs'; import { createEsValueResolvers, createEventsResolvers } from './graphql/events'; import { createHostsResolvers } from './graphql/hosts'; -import { createIpDetailsResolvers } from './graphql/ip_details'; import { createKpiHostsResolvers } from './graphql/kpi_hosts'; import { createKpiNetworkResolvers } from './graphql/kpi_network'; import { createNetworkResolvers } from './graphql/network'; import { createNoteResolvers } from './graphql/note'; import { createPinnedEventResolvers } from './graphql/pinned_event'; -import { createOverviewResolvers } from './graphql/overview'; import { createScalarDateResolvers } from './graphql/scalar_date'; import { createScalarToAnyValueResolvers } from './graphql/scalar_to_any'; import { createScalarToBooleanArrayValueResolvers } from './graphql/scalar_to_boolean_array'; @@ -25,7 +23,6 @@ import { createScalarToNumberArrayValueResolvers } from './graphql/scalar_to_num import { createSourceStatusResolvers } from './graphql/source_status'; import { createSourcesResolvers } from './graphql/sources'; import { createTimelineResolvers } from './graphql/timeline'; -import { createUncommonProcessesResolvers } from './graphql/uncommon_processes'; import { createWhoAmIResolvers } from './graphql/who_am_i'; import { AppBackendLibs } from './lib/types'; import { createMatrixHistogramResolvers } from './graphql/matrix_histogram'; @@ -37,14 +34,12 @@ export const initServer = (libs: AppBackendLibs) => { createEsValueResolvers() as IResolvers, createEventsResolvers(libs) as IResolvers, createHostsResolvers(libs) as IResolvers, - createIpDetailsResolvers(libs) as IResolvers, createKpiNetworkResolvers(libs) as IResolvers, createMatrixHistogramResolvers(libs) as IResolvers, createNoteResolvers(libs) as IResolvers, createPinnedEventResolvers(libs) as IResolvers, createSourcesResolvers(libs) as IResolvers, createScalarToStringArrayValueResolvers() as IResolvers, - createOverviewResolvers(libs) as IResolvers, createNetworkResolvers(libs) as IResolvers, createScalarDateResolvers() as IResolvers, createScalarToDateArrayValueResolvers() as IResolvers, @@ -54,7 +49,6 @@ export const initServer = (libs: AppBackendLibs) => { createSourcesResolvers(libs) as IResolvers, createSourceStatusResolvers(libs) as IResolvers, createTimelineResolvers(libs) as IResolvers, - createUncommonProcessesResolvers(libs) as IResolvers, createWhoAmIResolvers() as IResolvers, createKpiHostsResolvers(libs) as IResolvers, ], diff --git a/x-pack/plugins/security_solution/server/lib/compose/kibana.ts b/x-pack/plugins/security_solution/server/lib/compose/kibana.ts index bab00e33e33789..6348ee930a1090 100644 --- a/x-pack/plugins/security_solution/server/lib/compose/kibana.ts +++ b/x-pack/plugins/security_solution/server/lib/compose/kibana.ts @@ -16,17 +16,13 @@ import { KpiHosts } from '../kpi_hosts'; import { ElasticsearchKpiHostsAdapter } from '../kpi_hosts/elasticsearch_adapter'; import { ElasticsearchIndexFieldAdapter, IndexFields } from '../index_fields'; -import { ElasticsearchIpDetailsAdapter, IpDetails } from '../ip_details'; import { KpiNetwork } from '../kpi_network'; import { ElasticsearchKpiNetworkAdapter } from '../kpi_network/elasticsearch_adapter'; import { ElasticsearchNetworkAdapter, Network } from '../network'; -import { Overview } from '../overview'; -import { ElasticsearchOverviewAdapter } from '../overview/elasticsearch_adapter'; import { ElasticsearchSourceStatusAdapter, SourceStatus } from '../source_status'; import { ConfigurationSourcesAdapter, Sources } from '../sources'; import { AppBackendLibs, AppDomainLibs } from '../types'; -import { ElasticsearchUncommonProcessesAdapter, UncommonProcesses } from '../uncommon_processes'; import * as note from '../note/saved_object'; import * as pinnedEvent from '../pinned_event/saved_object'; import * as timeline from '../timeline/saved_object'; @@ -46,15 +42,12 @@ export function compose( const domainLibs: AppDomainLibs = { authentications: new Authentications(new ElasticsearchAuthenticationAdapter(framework)), events: new Events(new ElasticsearchEventsAdapter(framework)), - fields: new IndexFields(new ElasticsearchIndexFieldAdapter(framework)), + fields: new IndexFields(new ElasticsearchIndexFieldAdapter()), hosts: new Hosts(new ElasticsearchHostsAdapter(framework, endpointContext)), - ipDetails: new IpDetails(new ElasticsearchIpDetailsAdapter(framework)), kpiHosts: new KpiHosts(new ElasticsearchKpiHostsAdapter(framework)), kpiNetwork: new KpiNetwork(new ElasticsearchKpiNetworkAdapter(framework)), matrixHistogram: new MatrixHistogram(new ElasticsearchMatrixHistogramAdapter(framework)), network: new Network(new ElasticsearchNetworkAdapter(framework)), - overview: new Overview(new ElasticsearchOverviewAdapter(framework)), - uncommonProcesses: new UncommonProcesses(new ElasticsearchUncommonProcessesAdapter(framework)), }; const libs: AppBackendLibs = { diff --git a/x-pack/plugins/security_solution/server/lib/events/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/events/elasticsearch_adapter.ts index dda52e26ca42b8..8b656272ecc996 100644 --- a/x-pack/plugins/security_solution/server/lib/events/elasticsearch_adapter.ts +++ b/x-pack/plugins/security_solution/server/lib/events/elasticsearch_adapter.ts @@ -26,7 +26,6 @@ import { TimelineDetailsData, TimelineEdges, } from '../../graphql/types'; -import { baseCategoryFields } from '../../utils/beat_schema/8.0.0'; import { reduceFields } from '../../utils/build_query/reduce_fields'; import { mergeFieldsWithHit, inspectStringifyObject } from '../../utils/build_query'; import { eventFieldsMap } from '../ecs_fields'; @@ -44,6 +43,8 @@ import { TimelineRequestOptions, } from './types'; +const baseCategoryFields = ['@timestamp', 'labels', 'message', 'tags']; + export class ElasticsearchEventsAdapter implements EventsAdapter { constructor(private readonly framework: FrameworkAdapter) {} diff --git a/x-pack/plugins/security_solution/server/lib/index_fields/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/index_fields/elasticsearch_adapter.ts index 777b1cf3bb80d7..6cfa13bfd2a7ad 100644 --- a/x-pack/plugins/security_solution/server/lib/index_fields/elasticsearch_adapter.ts +++ b/x-pack/plugins/security_solution/server/lib/index_fields/elasticsearch_adapter.ts @@ -4,167 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEmpty } from 'lodash/fp'; - -import { IndexField } from '../../graphql/types'; -import { baseCategoryFields, getDocumentation, hasDocumentation } from '../../utils/beat_schema'; -import { FrameworkAdapter, FrameworkRequest } from '../framework'; -import { FieldsAdapter, IndexFieldDescriptor } from './types'; +import { FrameworkRequest } from '../framework'; +import { FieldsAdapter } from './types'; export class ElasticsearchIndexFieldAdapter implements FieldsAdapter { - constructor(private readonly framework: FrameworkAdapter) {} - public async getIndexFields(request: FrameworkRequest, indices: string[]): Promise { - const indexPatternsService = this.framework.getIndexPatternsService(request); - const responsesIndexFields = await Promise.all( - indices.map((index) => { - return indexPatternsService.getFieldsForWildcard({ - pattern: index, - }); - }) - ); - return formatIndexFields(responsesIndexFields, indices); + // Deprecated until we delete all the code + public async getIndexFields(request: FrameworkRequest, indices: string[]): Promise { + return Promise.resolve(['deprecated']); } } - -const missingFields = [ - { - name: '_id', - type: 'string', - searchable: true, - aggregatable: false, - readFromDocValues: true, - }, - { - name: '_index', - type: 'string', - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, -]; - -/** - * Creates a single field item. - * - * This is a mutatious HOT CODE PATH function that will have array sizes up to 4.7 megs - * in size at a time calling this function repeatedly. This function should be as optimized as possible - * and should avoid any and all creation of new arrays, iterating over the arrays or performing - * any n^2 operations. - * @param indexesAlias The index alias - * @param index The index its self - * @param indexesAliasIdx The index within the alias - */ -export const createFieldItem = ( - indexesAlias: string[], - index: IndexFieldDescriptor, - indexesAliasIdx: number -): IndexField => { - const alias = indexesAlias[indexesAliasIdx]; - const splitName = index.name.split('.'); - const category = baseCategoryFields.includes(splitName[0]) ? 'base' : splitName[0]; - return { - ...(hasDocumentation(alias, index.name) ? getDocumentation(alias, index.name) : {}), - ...index, - category, - indexes: [alias], - }; -}; - -/** - * This is a mutatious HOT CODE PATH function that will have array sizes up to 4.7 megs - * in size at a time when being called. This function should be as optimized as possible - * and should avoid any and all creation of new arrays, iterating over the arrays or performing - * any n^2 operations. The `.push`, and `forEach` operations are expected within this function - * to speed up performance. - * - * This intentionally waits for the next tick on the event loop to process as the large 4.7 megs - * has already consumed a lot of the event loop processing up to this function and we want to give - * I/O opportunity to occur by scheduling this on the next loop. - * @param responsesIndexFields The response index fields to loop over - * @param indexesAlias The index aliases such as filebeat-* - */ -export const formatFirstFields = async ( - responsesIndexFields: IndexFieldDescriptor[][], - indexesAlias: string[] -): Promise => { - return new Promise((resolve) => { - setTimeout(() => { - resolve( - responsesIndexFields.reduce( - ( - accumulator: IndexField[], - indexFields: IndexFieldDescriptor[], - indexesAliasIdx: number - ) => { - missingFields.forEach((index) => { - const item = createFieldItem(indexesAlias, index, indexesAliasIdx); - accumulator.push(item); - }); - indexFields.forEach((index) => { - const item = createFieldItem(indexesAlias, index, indexesAliasIdx); - accumulator.push(item); - }); - return accumulator; - }, - [] - ) - ); - }); - }); -}; - -/** - * This is a mutatious HOT CODE PATH function that will have array sizes up to 4.7 megs - * in size at a time when being called. This function should be as optimized as possible - * and should avoid any and all creation of new arrays, iterating over the arrays or performing - * any n^2 operations. The `.push`, and `forEach` operations are expected within this function - * to speed up performance. The "indexFieldNameHash" side effect hash avoids additional expensive n^2 - * look ups. - * - * This intentionally waits for the next tick on the event loop to process as the large 4.7 megs - * has already consumed a lot of the event loop processing up to this function and we want to give - * I/O opportunity to occur by scheduling this on the next loop. - * @param fields The index fields to create the secondary fields for - */ -export const formatSecondFields = async (fields: IndexField[]): Promise => { - return new Promise((resolve) => { - setTimeout(() => { - const indexFieldNameHash: Record = {}; - const reduced = fields.reduce((accumulator: IndexField[], indexfield: IndexField) => { - const alreadyExistingIndexField = indexFieldNameHash[indexfield.name]; - if (alreadyExistingIndexField != null) { - const existingIndexField = accumulator[alreadyExistingIndexField]; - if (isEmpty(accumulator[alreadyExistingIndexField].description)) { - accumulator[alreadyExistingIndexField].description = indexfield.description; - } - accumulator[alreadyExistingIndexField].indexes = Array.from( - new Set([...existingIndexField.indexes, ...indexfield.indexes]) - ); - return accumulator; - } - accumulator.push(indexfield); - indexFieldNameHash[indexfield.name] = accumulator.length - 1; - return accumulator; - }, []); - resolve(reduced); - }); - }); -}; - -/** - * Formats the index fields into a format the UI wants. - * - * NOTE: This will have array sizes up to 4.7 megs in size at a time when being called. - * This function should be as optimized as possible and should avoid any and all creation - * of new arrays, iterating over the arrays or performing any n^2 operations. - * @param responsesIndexFields The response index fields to format - * @param indexesAlias The index alias - */ -export const formatIndexFields = async ( - responsesIndexFields: IndexFieldDescriptor[][], - indexesAlias: string[] -): Promise => { - const fields = await formatFirstFields(responsesIndexFields, indexesAlias); - const secondFields = await formatSecondFields(fields); - return secondFields; -}; diff --git a/x-pack/plugins/security_solution/server/lib/index_fields/index.ts b/x-pack/plugins/security_solution/server/lib/index_fields/index.ts index a3ea8548bddc2c..94966bc16a407e 100644 --- a/x-pack/plugins/security_solution/server/lib/index_fields/index.ts +++ b/x-pack/plugins/security_solution/server/lib/index_fields/index.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexField } from '../../graphql/types'; - import { FieldsAdapter } from './types'; import { FrameworkRequest } from '../framework'; export { ElasticsearchIndexFieldAdapter } from './elasticsearch_adapter'; @@ -13,7 +11,8 @@ export { ElasticsearchIndexFieldAdapter } from './elasticsearch_adapter'; export class IndexFields { constructor(private readonly adapter: FieldsAdapter) {} - public async getFields(request: FrameworkRequest, defaultIndex: string[]): Promise { + // Deprecated until we delete all the code + public async getFields(request: FrameworkRequest, defaultIndex: string[]): Promise { return this.adapter.getIndexFields(request, defaultIndex); } } diff --git a/x-pack/plugins/security_solution/server/lib/index_fields/types.ts b/x-pack/plugins/security_solution/server/lib/index_fields/types.ts index 67b3c254007e24..fdc3509d0d452d 100644 --- a/x-pack/plugins/security_solution/server/lib/index_fields/types.ts +++ b/x-pack/plugins/security_solution/server/lib/index_fields/types.ts @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexField } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; import { IFieldSubType } from '../../../../../../src/plugins/data/common'; export interface FieldsAdapter { - getIndexFields(req: FrameworkRequest, indices: string[]): Promise; + getIndexFields(req: FrameworkRequest, indices: string[]): Promise; } export interface IndexFieldDescriptor { diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/elasticsearch_adapter.test.ts b/x-pack/plugins/security_solution/server/lib/ip_details/elasticsearch_adapter.test.ts deleted file mode 100644 index 6249e60d9a2be8..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/elasticsearch_adapter.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { FlowTarget } from '../../graphql/types'; - -import { getIpOverviewAgg, getIpOverviewHostAgg, getUsersEdges } from './elasticsearch_adapter'; - -import { - formattedDestination, - formattedEmptySource, - formattedHost, - formattedSource, - mockFormattedUsersEdges, - mockUsersData, - responseAggs, -} from './mock'; - -describe('elasticsearch_adapter', () => { - describe('#getIpOverview', () => { - test('will return a destination correctly', () => { - const destination = getIpOverviewAgg( - FlowTarget.destination, - responseAggs.aggregations.destination! - ); - expect(destination).toEqual(formattedDestination); - }); - - test('will return a source correctly', () => { - const source = getIpOverviewAgg(FlowTarget.source, responseAggs.aggregations.source!); - expect(source).toEqual(formattedSource); - }); - - test('will return a host correctly', () => { - const host = getIpOverviewHostAgg(responseAggs.aggregations.host); - expect(host).toEqual(formattedHost); - }); - - test('will return an empty source correctly', () => { - const source = getIpOverviewAgg(FlowTarget.source, {}); - expect(source).toEqual(formattedEmptySource); - }); - }); - - describe('#getUsers', () => { - test('will format edges correctly', () => { - // @ts-expect-error Re-work `DatabaseSearchResponse` types as mock ES Response won't match - const edges = getUsersEdges(mockUsersData); - expect(edges).toEqual(mockFormattedUsersEdges); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/ip_details/elasticsearch_adapter.ts deleted file mode 100644 index 90803ca302bd4f..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/elasticsearch_adapter.ts +++ /dev/null @@ -1,160 +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 { get, getOr } from 'lodash/fp'; - -import { - AutonomousSystem, - GeoEcsFields, - HostEcsFields, - IpOverviewData, - UsersData, - UsersEdges, -} from '../../graphql/types'; -import { inspectStringifyObject } from '../../utils/build_query'; -import { DatabaseSearchResponse, FrameworkAdapter, FrameworkRequest } from '../framework'; -import { TermAggregation } from '../types'; -import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants'; -import { IpOverviewRequestOptions, UsersRequestOptions } from './index'; -import { buildOverviewQuery } from './query_overview.dsl'; -import { buildUsersQuery } from './query_users.dsl'; - -import { - IpDetailsAdapter, - IpOverviewHit, - OverviewHit, - OverviewHostHit, - UsersBucketsItem, -} from './types'; - -export class ElasticsearchIpDetailsAdapter implements IpDetailsAdapter { - constructor(private readonly framework: FrameworkAdapter) {} - - public async getIpDetails( - request: FrameworkRequest, - options: IpOverviewRequestOptions - ): Promise { - const dsl = buildOverviewQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - - return { - inspect, - ...getIpOverviewAgg('source', getOr({}, 'aggregations.source', response)), - ...getIpOverviewAgg('destination', getOr({}, 'aggregations.destination', response)), - ...getIpOverviewHostAgg(getOr({}, 'aggregations.host', response)), - }; - } - - public async getUsers( - request: FrameworkRequest, - options: UsersRequestOptions - ): Promise { - if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { - throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); - } - const dsl = buildUsersQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - - const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination; - const totalCount = getOr(0, 'aggregations.user_count.value', response); - const usersEdges = getUsersEdges(response); - const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount; - const edges = usersEdges.splice(cursorStart, querySize - cursorStart); - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - const showMorePagesIndicator = totalCount > fakeTotalCount; - return { - edges, - inspect, - pageInfo: { - activePage: activePage ? activePage : 0, - fakeTotalCount, - showMorePagesIndicator, - }, - totalCount, - }; - } -} - -export const getIpOverviewAgg = (type: string, overviewHit: OverviewHit | {}) => { - const firstSeen = getOr(null, `firstSeen.value_as_string`, overviewHit); - const lastSeen = getOr(null, `lastSeen.value_as_string`, overviewHit); - const autonomousSystem: AutonomousSystem | null = getOr( - null, - `as.results.hits.hits[0]._source.${type}.as`, - overviewHit - ); - const geoFields: GeoEcsFields | null = getOr( - null, - `geo.results.hits.hits[0]._source.${type}.geo`, - overviewHit - ); - - return { - [type]: { - firstSeen, - lastSeen, - autonomousSystem: { - ...autonomousSystem, - }, - geo: { - ...geoFields, - }, - }, - }; -}; - -export const getIpOverviewHostAgg = (overviewHostHit: OverviewHostHit | {}) => { - const hostFields: HostEcsFields | null = getOr( - null, - `results.hits.hits[0]._source.host`, - overviewHostHit - ); - return { - host: { - ...hostFields, - }, - }; -}; - -export const getUsersEdges = ( - response: DatabaseSearchResponse -): UsersEdges[] => - getOr([], `aggregations.users.buckets`, response).map((bucket: UsersBucketsItem) => ({ - node: { - _id: bucket.key, - user: { - id: getOr([], 'id.buckets', bucket).map((id: UsersBucketsItem) => id.key), - name: bucket.key, - groupId: getOr([], 'groupId.buckets', bucket).map( - (groupId: UsersBucketsItem) => groupId.key - ), - groupName: getOr([], 'groupName.buckets', bucket).map( - (groupName: UsersBucketsItem) => groupName.key - ), - count: get('doc_count', bucket), - }, - }, - cursor: { - value: bucket.key, - tiebreaker: null, - }, - })); diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/index.ts b/x-pack/plugins/security_solution/server/lib/ip_details/index.ts deleted file mode 100644 index ed8824bc284e4b..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/index.ts +++ /dev/null @@ -1,37 +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 { FlowTarget, IpOverviewData, UsersData, UsersSortField } from '../../graphql/types'; -import { FrameworkRequest, RequestOptions, RequestOptionsPaginated } from '../framework'; - -import { IpDetailsAdapter } from './types'; - -export * from './elasticsearch_adapter'; - -export interface IpOverviewRequestOptions extends RequestOptions { - ip: string; -} - -export interface UsersRequestOptions extends RequestOptionsPaginated { - ip: string; - sort: UsersSortField; - flowTarget: FlowTarget; -} - -export class IpDetails { - constructor(private readonly adapter: IpDetailsAdapter) {} - - public async getIpOverview( - req: FrameworkRequest, - options: IpOverviewRequestOptions - ): Promise { - return this.adapter.getIpDetails(req, options); - } - - public async getUsers(req: FrameworkRequest, options: UsersRequestOptions): Promise { - return this.adapter.getUsers(req, options); - } -} diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/mock.ts b/x-pack/plugins/security_solution/server/lib/ip_details/mock.ts deleted file mode 100644 index 1db86e7766fcf0..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/mock.ts +++ /dev/null @@ -1,430 +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 { UsersEdges } from '../../graphql/types'; - -import { IpOverviewHit, UsersResponse } from './types'; - -export const responseAggs: IpOverviewHit = { - aggregations: { - destination: { - doc_count: 882307, - geo: { - doc_count: 62089, - results: { - hits: { - total: { - value: 62089, - relation: 'eq', - }, - max_score: null, - hits: [ - { - _source: { - destination: { - geo: { - continent_name: 'Asia', - region_iso_code: 'IN-KA', - city_name: 'Bengaluru', - country_iso_code: 'IN', - region_name: 'Karnataka', - location: { - lon: 77.5833, - lat: 12.9833, - }, - }, - }, - }, - sort: [1553894176003], - }, - ], - }, - }, - }, - lastSeen: { - value: 1553900180003, - value_as_string: '2019-03-29T22:56:20.003Z', - }, - firstSeen: { - value: 1551388820000, - value_as_string: '2019-02-28T21:20:20.000Z', - }, - autonomousSystem: { - doc_count: 0, - results: { - hits: { - total: { - value: 0, - relation: 'eq', - }, - max_score: null, - hits: [], - }, - }, - }, - }, - source: { - doc_count: 1002234, - geo: { - doc_count: 1507, - results: { - hits: { - total: { - value: 1507, - relation: 'eq', - }, - max_score: null, - hits: [ - { - _index: 'filebeat-8.0.0-2019.03.21-000002', - _type: '_doc', - _id: 'dHQ6y2kBCQofM5eXi5OE', - _score: null, - _source: { - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'IN-KA', - city_name: 'Bengaluru', - country_iso_code: 'IN', - region_name: 'Karnataka', - location: { - lon: 77.5833, - lat: 12.9833, - }, - }, - }, - }, - sort: [1553892804003], - }, - ], - }, - }, - }, - lastSeen: { - value: 1553900180003, - value_as_string: '2019-03-29T22:56:20.003Z', - }, - firstSeen: { - value: 1551388804322, - value_as_string: '2019-02-28T21:20:04.322Z', - }, - autonomousSystem: { - doc_count: 0, - results: { - hits: { - total: { - value: 0, - relation: 'eq', - }, - max_score: null, - hits: [], - }, - }, - }, - }, - host: { - doc_count: 1588091, - results: { - hits: { - total: { - value: 1588091, - relation: 'eq', - }, - max_score: null, - hits: [ - { - _index: 'filebeat-8.0.0-2019.05.20-000004', - _type: '_doc', - _id: 'NU9dD2sB9v5HJNSHMMRc', - _score: null, - _source: { - host: { - hostname: 'suricata-iowa', - os: { - kernel: '4.15.0-1032-gcp', - codename: 'bionic', - name: 'Ubuntu', - family: 'debian', - version: '18.04.2 LTS (Bionic Beaver)', - platform: 'ubuntu', - }, - ip: ['10.128.0.4', 'fe80::4001:aff:fe80:4'], - containerized: false, - name: 'suricata-iowa', - id: 'be1f3d767896212736b880e846876dcb', - mac: ['42:01:0a:80:00:04'], - architecture: 'x86_64', - }, - }, - sort: [1559330892000], - }, - ], - }, - }, - }, - }, - _shards: { - total: 42, - successful: 42, - skipped: 0, - failed: 0, - }, - hits: { - total: { - value: 71358841, - relation: 'eq', - }, - max_score: null, - hits: [], - }, - took: 392, - timeout: 500, -}; - -export const formattedDestination = { - destination: { - firstSeen: '2019-02-28T21:20:20.000Z', - lastSeen: '2019-03-29T22:56:20.003Z', - autonomousSystem: {}, - geo: { - continent_name: 'Asia', - region_iso_code: 'IN-KA', - city_name: 'Bengaluru', - country_iso_code: 'IN', - region_name: 'Karnataka', - location: { - lon: 77.5833, - lat: 12.9833, - }, - }, - }, -}; - -export const formattedSource = { - source: { - firstSeen: '2019-02-28T21:20:04.322Z', - lastSeen: '2019-03-29T22:56:20.003Z', - autonomousSystem: {}, - geo: { - continent_name: 'Asia', - region_iso_code: 'IN-KA', - city_name: 'Bengaluru', - country_iso_code: 'IN', - region_name: 'Karnataka', - location: { - lon: 77.5833, - lat: 12.9833, - }, - }, - }, -}; - -export const formattedHost = { - host: { - hostname: 'suricata-iowa', - os: { - kernel: '4.15.0-1032-gcp', - codename: 'bionic', - name: 'Ubuntu', - family: 'debian', - version: '18.04.2 LTS (Bionic Beaver)', - platform: 'ubuntu', - }, - ip: ['10.128.0.4', 'fe80::4001:aff:fe80:4'], - containerized: false, - name: 'suricata-iowa', - id: 'be1f3d767896212736b880e846876dcb', - mac: ['42:01:0a:80:00:04'], - architecture: 'x86_64', - }, -}; - -export const formattedEmptySource = { - source: { - firstSeen: null, - lastSeen: null, - autonomousSystem: {}, - geo: {}, - }, -}; - -export const mockUsersData: UsersResponse = { - took: 445, - timed_out: false, - _shards: { - total: 59, - successful: 59, - skipped: 0, - failed: 0, - }, - hits: { - max_score: null, - hits: [], - }, - aggregations: { - user_count: { - value: 3, - }, - users: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '_apt', - doc_count: 10, - groupName: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'nogroup', - doc_count: 10, - }, - ], - }, - groupId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '65534', - doc_count: 10, - }, - ], - }, - id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '104', - doc_count: 10, - }, - ], - }, - }, - { - key: 'root', - doc_count: 109, - groupName: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'Debian-exim', - doc_count: 72, - }, - { - key: 'root', - doc_count: 37, - }, - ], - }, - groupId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '116', - doc_count: 72, - }, - { - key: '0', - doc_count: 37, - }, - ], - }, - id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '0', - doc_count: 109, - }, - ], - }, - }, - { - key: 'systemd-resolve', - doc_count: 4, - groupName: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, - groupId: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, - id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '102', - doc_count: 4, - }, - ], - }, - }, - ], - }, - }, -}; - -export const mockFormattedUsersEdges: UsersEdges[] = [ - { - node: { - _id: '_apt', - user: { - id: ['104'], - name: '_apt', - groupId: ['65534'], - groupName: ['nogroup'], - count: 10, - }, - }, - cursor: { - value: '_apt', - tiebreaker: null, - }, - }, - { - node: { - _id: 'root', - user: { - id: ['0'], - name: 'root', - groupId: ['116', '0'], - groupName: ['Debian-exim', 'root'], - count: 109, - }, - }, - cursor: { - value: 'root', - tiebreaker: null, - }, - }, - { - node: { - _id: 'systemd-resolve', - user: { - id: ['102'], - name: 'systemd-resolve', - groupId: [], - groupName: [], - count: 4, - }, - }, - cursor: { - value: 'systemd-resolve', - tiebreaker: null, - }, - }, -]; diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/query_overview.dsl.ts b/x-pack/plugins/security_solution/server/lib/ip_details/query_overview.dsl.ts deleted file mode 100644 index d9c8f32d0b465c..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/query_overview.dsl.ts +++ /dev/null @@ -1,126 +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 { isEmpty } from 'lodash/fp'; -import { IpOverviewRequestOptions } from './index'; - -const getAggs = (type: string, ip: string) => { - return { - [type]: { - filter: { - term: { - [`${type}.ip`]: ip, - }, - }, - aggs: { - firstSeen: { - min: { - field: '@timestamp', - }, - }, - lastSeen: { - max: { - field: '@timestamp', - }, - }, - as: { - filter: { - exists: { - field: `${type}.as`, - }, - }, - aggs: { - results: { - top_hits: { - size: 1, - _source: [`${type}.as`], - sort: [ - { - '@timestamp': 'desc', - }, - ], - }, - }, - }, - }, - geo: { - filter: { - exists: { - field: `${type}.geo`, - }, - }, - aggs: { - results: { - top_hits: { - size: 1, - _source: [`${type}.geo`], - sort: [ - { - '@timestamp': 'desc', - }, - ], - }, - }, - }, - }, - }, - }, - }; -}; - -const getHostAggs = (ip: string) => { - return { - host: { - filter: { - term: { - 'host.ip': ip, - }, - }, - aggs: { - results: { - top_hits: { - size: 1, - _source: ['host'], - sort: [ - { - '@timestamp': 'desc', - }, - ], - }, - }, - }, - }, - }; -}; - -export const buildOverviewQuery = ({ - defaultIndex, - docValueFields, - ip, -}: IpOverviewRequestOptions) => { - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - body: { - ...(isEmpty(docValueFields) ? { docvalue_fields: docValueFields } : {}), - aggs: { - ...getAggs('source', ip), - ...getAggs('destination', ip), - ...getHostAggs(ip), - }, - query: { - bool: { - should: [], - }, - }, - size: 0, - track_total_hits: false, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/query_users.dsl.ts b/x-pack/plugins/security_solution/server/lib/ip_details/query_users.dsl.ts deleted file mode 100644 index 293a487777fd21..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/query_users.dsl.ts +++ /dev/null @@ -1,104 +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 { assertUnreachable } from '../../../common/utility_types'; -import { Direction, UsersFields, UsersSortField } from '../../graphql/types'; -import { createQueryFilterClauses } from '../../utils/build_query'; - -import { UsersRequestOptions } from './index'; - -export const buildUsersQuery = ({ - ip, - sort, - filterQuery, - flowTarget, - pagination: { querySize }, - defaultIndex, - sourceConfiguration: { - fields: { timestamp }, - }, - timerange: { from, to }, -}: UsersRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [timestamp]: { gte: from, lte: to, format: 'strict_date_optional_time' }, - }, - }, - { term: { [`${flowTarget}.ip`]: ip } }, - ]; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - body: { - aggs: { - user_count: { - cardinality: { - field: 'user.name', - }, - }, - users: { - terms: { - field: 'user.name', - size: querySize, - order: { - ...getQueryOrder(sort), - }, - }, - aggs: { - id: { - terms: { - field: 'user.id', - }, - }, - groupId: { - terms: { - field: 'user.group.id', - }, - }, - groupName: { - terms: { - field: 'user.group.name', - }, - }, - }, - }, - }, - query: { - bool: { - filter, - must_not: [ - { - term: { - 'event.category': 'authentication', - }, - }, - ], - }, - }, - size: 0, - track_total_hits: false, - }, - }; - - return dslQuery; -}; - -type QueryOrder = { _count: Direction } | { _key: Direction }; - -const getQueryOrder = (sort: UsersSortField): QueryOrder => { - switch (sort.field) { - case UsersFields.name: - return { _key: sort.direction }; - case UsersFields.count: - return { _count: sort.direction }; - default: - return assertUnreachable(sort.field); - } -}; diff --git a/x-pack/plugins/security_solution/server/lib/ip_details/types.ts b/x-pack/plugins/security_solution/server/lib/ip_details/types.ts deleted file mode 100644 index d137d919932f73..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/ip_details/types.ts +++ /dev/null @@ -1,135 +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 { IpOverviewData, UsersData } from '../../graphql/types'; -import { FrameworkRequest, RequestBasicOptions } from '../framework'; -import { Hit, ShardsResponse, TotalValue } from '../types'; - -export interface IpDetailsAdapter { - getIpDetails(request: FrameworkRequest, options: RequestBasicOptions): Promise; - getUsers(request: FrameworkRequest, options: RequestBasicOptions): Promise; -} - -interface ResultHit { - doc_count: number; - results: { - hits: { - total: TotalValue | number; - max_score: number | null; - hits: Array<{ - _source: T; - sort?: [number]; - _index?: string; - _type?: string; - _id?: string; - _score?: number | null; - }>; - }; - }; -} - -export interface OverviewHit { - took?: number; - timed_out?: boolean; - _scroll_id?: string; - _shards?: ShardsResponse; - timeout?: number; - hits?: { - total: number; - hits: Hit[]; - }; - doc_count: number; - geo: ResultHit; - autonomousSystem: ResultHit; - firstSeen: { - value: number; - value_as_string: string; - }; - lastSeen: { - value: number; - value_as_string: string; - }; -} - -export type OverviewHostHit = ResultHit; - -export interface IpOverviewHit { - aggregations: { - destination?: OverviewHit; - source?: OverviewHit; - host: ResultHit; - }; - _shards: { - total: number; - successful: number; - skipped: number; - failed: number; - }; - hits: { - total: { - value: number; - relation: string; - }; - max_score: number | null; - hits: []; - }; - took: number; - timeout: number; -} - -// Users Table - -export interface UsersResponse { - took: number; - timed_out: boolean; - _shards: UsersShards; - hits: UsersHits; - aggregations: Aggregations; -} -interface UsersShards { - total: number; - successful: number; - skipped: number; - failed: number; -} -interface UsersHits { - max_score: null; - hits: string[]; -} -interface Aggregations { - user_count: UserCount; - users: Users; -} -interface UserCount { - value: number; -} -interface Users { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: UsersBucketsItem[]; -} -export interface UsersBucketsItem { - key: string; - doc_count: number; - groupName?: UsersGroupName; - groupId?: UsersGroupId; - id?: Id; -} -export interface UsersGroupName { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: UsersBucketsItem[]; -} -export interface UsersGroupId { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: UsersBucketsItem[]; -} -interface Id { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: UsersBucketsItem[]; -} diff --git a/x-pack/plugins/security_solution/server/lib/overview/elastic_adapter.test.ts b/x-pack/plugins/security_solution/server/lib/overview/elastic_adapter.test.ts deleted file mode 100644 index f421704dffe12e..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/overview/elastic_adapter.test.ts +++ /dev/null @@ -1,187 +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 { cloneDeep } from 'lodash/fp'; - -import { OverviewHostData, OverviewNetworkData } from '../../graphql/types'; -import { FrameworkAdapter, FrameworkRequest } from '../framework'; - -import { ElasticsearchOverviewAdapter } from './elasticsearch_adapter'; -import { - mockOptionsHost, - mockOptionsNetwork, - mockRequestHost, - mockRequestNetwork, - mockResponseHost, - mockResponseNetwork, - mockResultHost, - mockResultNetwork, - mockBuildOverviewHostQuery, - mockBuildOverviewNetworkQuery, -} from './mock'; - -jest.mock('./query.dsl', () => { - return { - buildOverviewHostQuery: jest.fn(() => mockBuildOverviewHostQuery), - buildOverviewNetworkQuery: jest.fn(() => mockBuildOverviewNetworkQuery), - }; -}); - -describe('Siem Overview elasticsearch_adapter', () => { - describe('Network Stats', () => { - describe('Happy Path - get Data', () => { - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockResponseNetwork); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ - callWithRequest: mockCallWithRequest, - })); - - test('getOverviewNetwork', async () => { - const EsOverviewNetwork = new ElasticsearchOverviewAdapter(mockFramework); - const data: OverviewNetworkData = await EsOverviewNetwork.getOverviewNetwork( - mockRequestNetwork as FrameworkRequest, - mockOptionsNetwork - ); - expect(data).toEqual(mockResultNetwork); - }); - }); - - describe('Unhappy Path - No data', () => { - const mockNoDataResponse = cloneDeep(mockResponseNetwork); - mockNoDataResponse.aggregations.unique_flow_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_dns_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_suricata_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_zeek_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_socket_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_zeek_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_packetbeat_count.unique_tls_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_filebeat_count.unique_cisco_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_filebeat_count.unique_netflow_count.doc_count = 0; - mockNoDataResponse.aggregations.unique_filebeat_count.unique_panw_count.doc_count = 0; - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockNoDataResponse); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ - callWithRequest: mockCallWithRequest, - })); - - test('getOverviewNetwork', async () => { - const EsOverviewNetwork = new ElasticsearchOverviewAdapter(mockFramework); - const data: OverviewNetworkData = await EsOverviewNetwork.getOverviewNetwork( - mockRequestNetwork as FrameworkRequest, - mockOptionsNetwork - ); - expect(data).toEqual({ - inspect: { - dsl: [JSON.stringify(mockBuildOverviewNetworkQuery, null, 2)], - response: [JSON.stringify(mockNoDataResponse, null, 2)], - }, - auditbeatSocket: 0, - filebeatCisco: 0, - filebeatNetflow: 0, - filebeatPanw: 0, - filebeatSuricata: 0, - filebeatZeek: 0, - packetbeatDNS: 0, - packetbeatFlow: 0, - packetbeatTLS: 0, - }); - }); - }); - }); - describe('Host Stats', () => { - describe('Happy Path - get Data', () => { - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockResponseHost); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ - callWithRequest: mockCallWithRequest, - })); - - test('getOverviewHost', async () => { - const EsOverviewHost = new ElasticsearchOverviewAdapter(mockFramework); - const data: OverviewHostData = await EsOverviewHost.getOverviewHost( - mockRequestHost as FrameworkRequest, - mockOptionsHost - ); - expect(data).toEqual(mockResultHost); - }); - }); - - describe('Unhappy Path - No data', () => { - const mockNoDataResponse = cloneDeep(mockResponseHost); - mockNoDataResponse.aggregations.auditd_count.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.dns_event_count.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.file_event_count.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.image_load_event_count.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.network_event_count.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.process_event_count.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.registry_event.doc_count = 0; - mockNoDataResponse.aggregations.endgame_module.security_event_count.doc_count = 0; - mockNoDataResponse.aggregations.fim_count.doc_count = 0; - mockNoDataResponse.aggregations.system_module.login_count.doc_count = 0; - mockNoDataResponse.aggregations.system_module.package_count.doc_count = 0; - mockNoDataResponse.aggregations.system_module.process_count.doc_count = 0; - mockNoDataResponse.aggregations.system_module.user_count.doc_count = 0; - mockNoDataResponse.aggregations.system_module.filebeat_count.doc_count = 0; - mockNoDataResponse.aggregations.winlog_module.security_event_count.doc_count = 0; - mockNoDataResponse.aggregations.winlog_module.mwsysmon_operational_event_count.doc_count = 0; - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockNoDataResponse); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ - callWithRequest: mockCallWithRequest, - })); - - test('getOverviewHost', async () => { - const EsOverviewHost = new ElasticsearchOverviewAdapter(mockFramework); - const data: OverviewHostData = await EsOverviewHost.getOverviewHost( - mockRequestHost as FrameworkRequest, - mockOptionsHost - ); - expect(data).toEqual({ - inspect: { - dsl: [JSON.stringify(mockBuildOverviewHostQuery, null, 2)], - response: [JSON.stringify(mockNoDataResponse, null, 2)], - }, - auditbeatAuditd: 0, - auditbeatFIM: 0, - auditbeatLogin: 0, - auditbeatPackage: 0, - auditbeatProcess: 0, - auditbeatUser: 0, - endgameDns: 0, - endgameFile: 0, - endgameImageLoad: 0, - endgameNetwork: 0, - endgameProcess: 0, - endgameRegistry: 0, - endgameSecurity: 0, - filebeatSystemModule: 0, - winlogbeatSecurity: 0, - winlogbeatMWSysmonOperational: 0, - }); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/lib/overview/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/overview/elasticsearch_adapter.ts deleted file mode 100644 index 982b47110c5135..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/overview/elasticsearch_adapter.ts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { getOr } from 'lodash/fp'; - -import { OverviewHostData, OverviewNetworkData } from '../../graphql/types'; -import { inspectStringifyObject } from '../../utils/build_query'; -import { FrameworkAdapter, FrameworkRequest, RequestBasicOptions } from '../framework'; -import { TermAggregation } from '../types'; - -import { buildOverviewHostQuery, buildOverviewNetworkQuery } from './query.dsl'; -import { OverviewAdapter, OverviewHostHit, OverviewNetworkHit } from './types'; - -export class ElasticsearchOverviewAdapter implements OverviewAdapter { - constructor(private readonly framework: FrameworkAdapter) {} - - public async getOverviewNetwork( - request: FrameworkRequest, - options: RequestBasicOptions - ): Promise { - const dsl = buildOverviewNetworkQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - - return { - inspect, - auditbeatSocket: getOr(null, 'aggregations.unique_socket_count.doc_count', response), - filebeatCisco: getOr( - null, - 'aggregations.unique_filebeat_count.unique_cisco_count.doc_count', - response - ), - filebeatNetflow: getOr( - null, - 'aggregations.unique_filebeat_count.unique_netflow_count.doc_count', - response - ), - filebeatPanw: getOr( - null, - 'aggregations.unique_filebeat_count.unique_panw_count.doc_count', - response - ), - filebeatSuricata: getOr(null, 'aggregations.unique_suricata_count.doc_count', response), - filebeatZeek: getOr(null, 'aggregations.unique_zeek_count.doc_count', response), - packetbeatDNS: getOr(null, 'aggregations.unique_dns_count.doc_count', response), - packetbeatFlow: getOr(null, 'aggregations.unique_flow_count.doc_count', response), - packetbeatTLS: getOr( - null, - 'aggregations.unique_packetbeat_count.unique_tls_count.doc_count', - response - ), - }; - } - - public async getOverviewHost( - request: FrameworkRequest, - options: RequestBasicOptions - ): Promise { - const dsl = buildOverviewHostQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - - return { - inspect, - auditbeatAuditd: getOr(null, 'aggregations.auditd_count.doc_count', response), - auditbeatFIM: getOr(null, 'aggregations.fim_count.doc_count', response), - auditbeatLogin: getOr(null, 'aggregations.system_module.login_count.doc_count', response), - auditbeatPackage: getOr(null, 'aggregations.system_module.package_count.doc_count', response), - auditbeatProcess: getOr(null, 'aggregations.system_module.process_count.doc_count', response), - auditbeatUser: getOr(null, 'aggregations.system_module.user_count.doc_count', response), - endgameDns: getOr(null, 'aggregations.endgame_module.dns_event_count.doc_count', response), - endgameFile: getOr(null, 'aggregations.endgame_module.file_event_count.doc_count', response), - endgameImageLoad: getOr( - null, - 'aggregations.endgame_module.image_load_event_count.doc_count', - response - ), - endgameNetwork: getOr( - null, - 'aggregations.endgame_module.network_event_count.doc_count', - response - ), - endgameProcess: getOr( - null, - 'aggregations.endgame_module.process_event_count.doc_count', - response - ), - endgameRegistry: getOr( - null, - 'aggregations.endgame_module.registry_event.doc_count', - response - ), - endgameSecurity: getOr( - null, - 'aggregations.endgame_module.security_event_count.doc_count', - response - ), - filebeatSystemModule: getOr( - null, - 'aggregations.system_module.filebeat_count.doc_count', - response - ), - winlogbeatSecurity: getOr( - null, - 'aggregations.winlog_module.security_event_count.doc_count', - response - ), - winlogbeatMWSysmonOperational: getOr( - null, - 'aggregations.winlog_module.mwsysmon_operational_event_count.doc_count', - response - ), - }; - } -} diff --git a/x-pack/plugins/security_solution/server/lib/overview/index.ts b/x-pack/plugins/security_solution/server/lib/overview/index.ts deleted file mode 100644 index ae9f81eb261a75..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/overview/index.ts +++ /dev/null @@ -1,28 +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 { OverviewHostData, OverviewNetworkData } from '../../graphql/types'; -import { FrameworkRequest, RequestBasicOptions } from '../framework'; - -import { OverviewAdapter } from './types'; - -export class Overview { - constructor(private readonly adapter: OverviewAdapter) {} - - public async getOverviewNetwork( - req: FrameworkRequest, - options: RequestBasicOptions - ): Promise { - return this.adapter.getOverviewNetwork(req, options); - } - - public async getOverviewHost( - req: FrameworkRequest, - options: RequestBasicOptions - ): Promise { - return this.adapter.getOverviewHost(req, options); - } -} diff --git a/x-pack/plugins/security_solution/server/lib/overview/mock.ts b/x-pack/plugins/security_solution/server/lib/overview/mock.ts deleted file mode 100644 index 2621c795ecd6b8..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/overview/mock.ts +++ /dev/null @@ -1,176 +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 { DEFAULT_INDEX_PATTERN } from '../../../common/constants'; -import { RequestBasicOptions } from '../framework/types'; - -export const mockOptionsNetwork: RequestBasicOptions = { - defaultIndex: DEFAULT_INDEX_PATTERN, - sourceConfiguration: { - fields: { - container: 'docker.container.name', - host: 'beat.hostname', - message: ['message', '@message'], - pod: 'kubernetes.pod.name', - tiebreaker: '_doc', - timestamp: '@timestamp', - }, - }, - timerange: { interval: '12h', to: '2019-02-11T02:26:46.071Z', from: '2019-02-10T02:26:46.071Z' }, - filterQuery: {}, -}; - -export const mockRequestNetwork = { - body: { - operationName: 'GetOverviewNetworkQuery', - variables: { - sourceId: 'default', - timerange: { - interval: '12h', - from: '2019-02-10T02:30:30.772Z', - to: '2019-02-11T02:30:30.772Z', - }, - filterQuery: '', - }, - query: - 'query GetOverviewNetworkQuery(\n $sourceId: ID!\n $timerange: TimerangeInput!\n $filterQuery: String\n ) {\n source(id: $sourceId) {\n id\n OverviewNetwork(timerange: $timerange, filterQuery: $filterQuery) {\n packetbeatFlow\n packetbeatDNS\n filebeatSuricata\n filebeatZeek\n auditbeatSocket\n }\n }\n }', - }, -}; - -export const mockResponseNetwork = { - took: 89, - timed_out: false, - _shards: { total: 18, successful: 18, skipped: 0, failed: 0 }, - hits: { total: { value: 950867, relation: 'eq' }, max_score: null, hits: [] }, - aggregations: { - unique_flow_count: { doc_count: 50243 }, - unique_dns_count: { doc_count: 15000 }, - unique_suricata_count: { doc_count: 2375 }, - unique_zeek_count: { doc_count: 456 }, - unique_socket_count: { doc_count: 13 }, - unique_filebeat_count: { - doc_count: 456756, - unique_cisco_count: { doc_count: 14 }, - unique_netflow_count: { doc_count: 992 }, - unique_panw_count: { doc_count: 225 }, - }, - unique_packetbeat_count: { doc_count: 7897896, unique_tls_count: { doc_count: 2009 } }, - }, -}; - -export const mockBuildOverviewHostQuery = { buildOverviewHostQuery: 'buildOverviewHostQuery' }; -export const mockBuildOverviewNetworkQuery = { - buildOverviewNetworkQuery: 'buildOverviewNetworkQuery', -}; - -export const mockResultNetwork = { - inspect: { - dsl: [JSON.stringify(mockBuildOverviewNetworkQuery, null, 2)], - response: [JSON.stringify(mockResponseNetwork, null, 2)], - }, - packetbeatFlow: 50243, - packetbeatDNS: 15000, - filebeatSuricata: 2375, - filebeatZeek: 456, - auditbeatSocket: 13, - filebeatCisco: 14, - filebeatNetflow: 992, - filebeatPanw: 225, - packetbeatTLS: 2009, -}; - -export const mockOptionsHost: RequestBasicOptions = { - defaultIndex: DEFAULT_INDEX_PATTERN, - sourceConfiguration: { - fields: { - container: 'docker.container.name', - host: 'beat.hostname', - message: ['message', '@message'], - pod: 'kubernetes.pod.name', - tiebreaker: '_doc', - timestamp: '@timestamp', - }, - }, - timerange: { interval: '12h', to: '2019-02-11T02:26:46.071Z', from: '2019-02-10T02:26:46.071Z' }, - filterQuery: {}, -}; - -export const mockRequestHost = { - body: { - operationName: 'GetOverviewHostQuery', - variables: { - sourceId: 'default', - timerange: { - interval: '12h', - from: '2019-02-10T02:30:30.772Z', - to: '2019-02-11T02:30:30.772Z', - }, - filterQuery: '', - }, - query: - 'query GetOverviewHostQuery(\n $sourceId: ID!\n $timerange: TimerangeInput!\n $filterQuery: String\n ) {\n source(id: $sourceId) {\n id\n OverviewHost(timerange: $timerange, filterQuery: $filterQuery) {\n auditbeatAuditd\n auditbeatFIM\n auditbeatLogin\n auditbeatPackage\n auditbeatProcess\n auditbeatUser\n }\n }\n }', - }, -}; - -export const mockResponseHost = { - took: 89, - timed_out: false, - _shards: { total: 18, successful: 18, skipped: 0, failed: 0 }, - hits: { total: { value: 950867, relation: 'eq' }, max_score: null, hits: [] }, - aggregations: { - auditd_count: { doc_count: 73847 }, - endgame_module: { - doc_count: 6258, - dns_event_count: { doc_count: 891 }, - file_event_count: { doc_count: 892 }, - image_load_event_count: { doc_count: 893 }, - network_event_count: { doc_count: 894 }, - process_event_count: { doc_count: 895 }, - registry_event: { doc_count: 896 }, - security_event_count: { doc_count: 897 }, - }, - fim_count: { doc_count: 107307 }, - system_module: { - doc_count: 20000000, - login_count: { doc_count: 60015 }, - package_count: { doc_count: 2003 }, - process_count: { doc_count: 1200 }, - user_count: { doc_count: 1979 }, - filebeat_count: { doc_count: 225 }, - }, - winlog_module: { - security_event_count: { - doc_count: 523, - }, - mwsysmon_operational_event_count: { - doc_count: 214, - }, - }, - }, -}; - -export const mockResultHost = { - inspect: { - dsl: [JSON.stringify(mockBuildOverviewHostQuery, null, 2)], - response: [JSON.stringify(mockResponseHost, null, 2)], - }, - auditbeatAuditd: 73847, - auditbeatFIM: 107307, - auditbeatLogin: 60015, - auditbeatPackage: 2003, - auditbeatProcess: 1200, - auditbeatUser: 1979, - endgameDns: 891, - endgameFile: 892, - endgameImageLoad: 893, - endgameNetwork: 894, - endgameProcess: 895, - endgameRegistry: 896, - endgameSecurity: 897, - filebeatSystemModule: 225, - winlogbeatSecurity: 523, - winlogbeatMWSysmonOperational: 214, -}; diff --git a/x-pack/plugins/security_solution/server/lib/overview/query.dsl.ts b/x-pack/plugins/security_solution/server/lib/overview/query.dsl.ts deleted file mode 100644 index b6b1cfea394fd1..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/overview/query.dsl.ts +++ /dev/null @@ -1,397 +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 { createQueryFilterClauses } from '../../utils/build_query'; -import { RequestBasicOptions } from '../framework'; - -export const buildOverviewNetworkQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - sourceConfiguration: { - fields: { timestamp }, - }, -}: RequestBasicOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [timestamp]: { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - body: { - aggregations: { - unique_flow_count: { - filter: { - term: { type: 'flow' }, - }, - }, - unique_dns_count: { - filter: { - term: { type: 'dns' }, - }, - }, - unique_suricata_count: { - filter: { - term: { 'service.type': 'suricata' }, - }, - }, - unique_zeek_count: { - filter: { - term: { 'service.type': 'zeek' }, - }, - }, - unique_socket_count: { - filter: { - term: { 'event.dataset': 'socket' }, - }, - }, - unique_filebeat_count: { - filter: { - term: { 'agent.type': 'filebeat' }, - }, - aggs: { - unique_netflow_count: { - filter: { - term: { 'input.type': 'netflow' }, - }, - }, - unique_panw_count: { - filter: { - term: { 'event.module': 'panw' }, - }, - }, - unique_cisco_count: { - filter: { - term: { 'event.module': 'cisco' }, - }, - }, - }, - }, - unique_packetbeat_count: { - filter: { - term: { 'agent.type': 'packetbeat' }, - }, - aggs: { - unique_tls_count: { - filter: { - term: { 'network.protocol': 'tls' }, - }, - }, - }, - }, - }, - query: { - bool: { - filter, - }, - }, - size: 0, - track_total_hits: false, - }, - }; - - return dslQuery; -}; - -export const buildOverviewHostQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - sourceConfiguration: { - fields: { timestamp }, - }, -}: RequestBasicOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [timestamp]: { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - body: { - aggregations: { - auditd_count: { - filter: { - term: { - 'event.module': 'auditd', - }, - }, - }, - endgame_module: { - filter: { - bool: { - should: [ - { - term: { 'event.module': 'endpoint' }, - }, - { - term: { - 'event.module': 'endgame', - }, - }, - ], - }, - }, - aggs: { - dns_event_count: { - filter: { - bool: { - should: [ - { - bool: { - filter: [ - { term: { 'network.protocol': 'dns' } }, - { term: { 'event.category': 'network' } }, - ], - }, - }, - { - term: { - 'endgame.event_type_full': 'dns_event', - }, - }, - ], - }, - }, - }, - file_event_count: { - filter: { - bool: { - should: [ - { - term: { - 'event.category': 'file', - }, - }, - { - term: { - 'endgame.event_type_full': 'file_event', - }, - }, - ], - }, - }, - }, - image_load_event_count: { - filter: { - bool: { - should: [ - { - bool: { - should: [ - { - term: { - 'event.category': 'library', - }, - }, - { - term: { - 'event.category': 'driver', - }, - }, - ], - }, - }, - { - term: { - 'endgame.event_type_full': 'image_load_event', - }, - }, - ], - }, - }, - }, - network_event_count: { - filter: { - bool: { - should: [ - { - bool: { - filter: [ - { - bool: { - must_not: { - term: { 'network.protocol': 'dns' }, - }, - }, - }, - { - term: { 'event.category': 'network' }, - }, - ], - }, - }, - { - term: { - 'endgame.event_type_full': 'network_event', - }, - }, - ], - }, - }, - }, - process_event_count: { - filter: { - bool: { - should: [ - { - term: { 'event.category': 'process' }, - }, - { - term: { - 'endgame.event_type_full': 'process_event', - }, - }, - ], - }, - }, - }, - registry_event: { - filter: { - bool: { - should: [ - { - term: { 'event.category': 'registry' }, - }, - { - term: { - 'endgame.event_type_full': 'registry_event', - }, - }, - ], - }, - }, - }, - security_event_count: { - filter: { - bool: { - should: [ - { - bool: { - filter: [ - { term: { 'event.category': 'session' } }, - { term: { 'event.category': 'authentication' } }, - ], - }, - }, - { - term: { - 'endgame.event_type_full': 'security_event', - }, - }, - ], - }, - }, - }, - }, - }, - fim_count: { - filter: { - term: { - 'event.module': 'file_integrity', - }, - }, - }, - winlog_module: { - filter: { - term: { - 'agent.type': 'winlogbeat', - }, - }, - aggs: { - mwsysmon_operational_event_count: { - filter: { - term: { - 'winlog.channel': 'Microsoft-Windows-Sysmon/Operational', - }, - }, - }, - security_event_count: { - filter: { - term: { - 'winlog.channel': 'Security', - }, - }, - }, - }, - }, - system_module: { - filter: { - term: { - 'event.module': 'system', - }, - }, - aggs: { - login_count: { - filter: { - term: { - 'event.dataset': 'login', - }, - }, - }, - package_count: { - filter: { - term: { - 'event.dataset': 'package', - }, - }, - }, - process_count: { - filter: { - term: { - 'event.dataset': 'process', - }, - }, - }, - user_count: { - filter: { - term: { - 'event.dataset': 'user', - }, - }, - }, - filebeat_count: { - filter: { - term: { - 'agent.type': 'filebeat', - }, - }, - }, - }, - }, - }, - query: { - bool: { - filter, - }, - }, - size: 0, - track_total_hits: false, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/lib/overview/types.ts b/x-pack/plugins/security_solution/server/lib/overview/types.ts deleted file mode 100644 index 7fdad08ac9b379..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/overview/types.ts +++ /dev/null @@ -1,109 +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 { OverviewHostData, OverviewNetworkData } from '../../graphql/types'; -import { FrameworkRequest, RequestBasicOptions } from '../framework'; -import { SearchHit } from '../types'; - -export interface OverviewAdapter { - getOverviewNetwork( - request: FrameworkRequest, - options: RequestBasicOptions - ): Promise; - getOverviewHost( - request: FrameworkRequest, - options: RequestBasicOptions - ): Promise; -} - -export interface OverviewNetworkHit extends SearchHit { - aggregations: { - unique_flow_count: { - doc_count: number; - }; - unique_dns_count: { - doc_count: number; - }; - unique_suricata_count: { - doc_count: number; - }; - unique_zeek_count: { - doc_count: number; - }; - unique_socket_count: { - doc_count: number; - }; - unique_filebeat_count: { - unique_netflow_count: { - doc_count: number; - }; - unique_panw_count: { - doc_count: number; - }; - unique_cisco_count: { - doc_count: number; - }; - }; - unique_packetbeat_count: { - unique_tls_count: { - doc_count: number; - }; - }; - }; -} - -export interface OverviewHostHit extends SearchHit { - aggregations: { - auditd_count: { - doc_count: number; - }; - endgame_module: { - dns_event_count: { - doc_count: number; - }; - file_event_count: { - doc_count: number; - }; - image_load_event_count: { - doc_count: number; - }; - network_event_count: { - doc_count: number; - }; - process_event_count: { - doc_count: number; - }; - registry_event: { - doc_count: number; - }; - security_event_count: { - doc_count: number; - }; - }; - fim_count: { - doc_count: number; - }; - system_module: { - login_count: { - doc_count: number; - }; - package_count: { - doc_count: number; - }; - process_count: { - doc_count: number; - }; - user_count: { - doc_count: number; - }; - filebeat_count: { - doc_count: number; - }; - }; - winlog_count: { - doc_count: number; - }; - }; -} diff --git a/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings.ts b/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings.ts index c5ee611dfa27f0..11082cd7295cc4 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings.ts @@ -213,6 +213,9 @@ export const timelineSavedObjectMappings: SavedObjectsType['mappings'] = { }, }, }, + indexNames: { + type: 'text', + }, kqlMode: { type: 'keyword', }, diff --git a/x-pack/plugins/security_solution/server/lib/types.ts b/x-pack/plugins/security_solution/server/lib/types.ts index 4f70e3aa8652ac..6e233f6e49d3b5 100644 --- a/x-pack/plugins/security_solution/server/lib/types.ts +++ b/x-pack/plugins/security_solution/server/lib/types.ts @@ -13,14 +13,11 @@ import { Events } from './events'; import { FrameworkAdapter, FrameworkRequest } from './framework'; import { Hosts } from './hosts'; import { IndexFields } from './index_fields'; -import { IpDetails } from './ip_details'; import { KpiHosts } from './kpi_hosts'; import { KpiNetwork } from './kpi_network'; import { Network } from './network'; -import { Overview } from './overview'; import { SourceStatus } from './source_status'; import { Sources } from './sources'; -import { UncommonProcesses } from './uncommon_processes'; import { Note } from './note/saved_object'; import { PinnedEvent } from './pinned_event/saved_object'; import { Timeline } from './timeline/saved_object'; @@ -33,12 +30,9 @@ export interface AppDomainLibs { events: Events; fields: IndexFields; hosts: Hosts; - ipDetails: IpDetails; matrixHistogram: MatrixHistogram; network: Network; kpiNetwork: KpiNetwork; - overview: Overview; - uncommonProcesses: UncommonProcesses; kpiHosts: KpiHosts; } diff --git a/x-pack/plugins/security_solution/server/lib/uncommon_processes/elasticsearch_adapter.test.ts b/x-pack/plugins/security_solution/server/lib/uncommon_processes/elasticsearch_adapter.test.ts deleted file mode 100644 index 2a15f1fe074f81..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/uncommon_processes/elasticsearch_adapter.test.ts +++ /dev/null @@ -1,265 +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 { UncommonProcessesEdges } from '../../graphql/types'; -import { processFieldsMap } from '../ecs_fields'; - -import { formatUncommonProcessesData, getHosts } from './elasticsearch_adapter'; -import { UncommonProcessBucket, UncommonProcessHit } from './types'; - -describe('elasticsearch_adapter', () => { - describe('#getHosts', () => { - const bucket1: UncommonProcessBucket = { - key: '123', - hosts: { - buckets: [ - { - key: '123', - host: { - hits: { - total: 0, - max_score: 0, - hits: [ - { - _index: 'hit-1', - _type: 'type-1', - _id: 'id-1', - _score: 0, - _source: { - host: { - name: ['host-1'], - id: ['host-id-1'], - }, - }, - }, - ], - }, - }, - }, - ], - }, - process: { - hits: { - total: { - value: 1, - relation: 'eq', - }, - max_score: 5, - hits: [], - }, - }, - }; - const bucket2: UncommonProcessBucket = { - key: '345', - hosts: { - buckets: [ - { - key: '123', - host: { - hits: { - total: 0, - max_score: 0, - hits: [ - { - _index: 'hit-1', - _type: 'type-1', - _id: 'id-1', - _score: 0, - _source: { - host: { - name: ['host-1'], - id: ['host-id-1'], - }, - }, - }, - ], - }, - }, - }, - { - key: '345', - host: { - hits: { - total: 0, - max_score: 0, - hits: [ - { - _index: 'hit-2', - _type: 'type-2', - _id: 'id-2', - _score: 0, - _source: { - host: { - name: ['host-2'], - id: ['host-id-2'], - }, - }, - }, - ], - }, - }, - }, - ], - }, - process: { - hits: { - total: { - value: 1, - relation: 'eq', - }, - max_score: 5, - hits: [], - }, - }, - }; - const bucket3: UncommonProcessBucket = { - key: '789', - hosts: { - buckets: [ - { - key: '789', - host: { - hits: { - total: 0, - max_score: 0, - hits: [ - { - _index: 'hit-9', - _type: 'type-9', - _id: 'id-9', - _score: 0, - _source: { - // @ts-expect-error ts doesn't like seeing the object written this way, but sometimes this is the data we get! - 'host.id': ['host-id-9'], - 'host.name': ['host-9'], - }, - }, - ], - }, - }, - }, - ], - }, - process: { - hits: { - total: { - value: 1, - relation: 'eq', - }, - max_score: 5, - hits: [], - }, - }, - }; - - test('will return a single host correctly', () => { - const hosts = getHosts(bucket1.hosts.buckets); - expect(hosts).toEqual([{ id: ['123'], name: ['host-1'] }]); - }); - - test('will return two hosts correctly', () => { - const hosts = getHosts(bucket2.hosts.buckets); - expect(hosts).toEqual([ - { id: ['123'], name: ['host-1'] }, - { id: ['345'], name: ['host-2'] }, - ]); - }); - - test('will return a dot notation host', () => { - const hosts = getHosts(bucket3.hosts.buckets); - expect(hosts).toEqual([{ id: ['789'], name: ['host-9'] }]); - }); - - test('will return no hosts when given an empty array', () => { - const hosts = getHosts([]); - expect(hosts).toEqual([]); - }); - }); - - describe('#formatUncommonProcessesData', () => { - const hit: UncommonProcessHit = { - _index: 'index-123', - _type: 'type-123', - _id: 'id-123', - _score: 10, - total: { - value: 100, - relation: 'eq', - }, - host: [ - { id: ['host-id-1'], name: ['host-name-1'] }, - { id: ['host-id-1'], name: ['host-name-1'] }, - ], - _source: { - '@timestamp': 'time', - process: { - name: ['process-1'], - title: ['title-1'], - }, - }, - cursor: 'cursor-1', - sort: [0], - }; - - test('it formats a uncommon process data with a source of name correctly', () => { - const fields: readonly string[] = ['process.name']; - const data = formatUncommonProcessesData(fields, hit, processFieldsMap); - const expected: UncommonProcessesEdges = { - cursor: { tiebreaker: null, value: 'cursor-1' }, - node: { - _id: 'id-123', - hosts: [ - { id: ['host-id-1'], name: ['host-name-1'] }, - { id: ['host-id-1'], name: ['host-name-1'] }, - ], - process: { - name: ['process-1'], - }, - instances: 100, - }, - }; - expect(data).toEqual(expected); - }); - - test('it formats a uncommon process data with a source of name and title correctly', () => { - const fields: readonly string[] = ['process.name', 'process.title']; - const data = formatUncommonProcessesData(fields, hit, processFieldsMap); - const expected: UncommonProcessesEdges = { - cursor: { tiebreaker: null, value: 'cursor-1' }, - node: { - _id: 'id-123', - hosts: [ - { id: ['host-id-1'], name: ['host-name-1'] }, - { id: ['host-id-1'], name: ['host-name-1'] }, - ], - instances: 100, - process: { - name: ['process-1'], - title: ['title-1'], - }, - }, - }; - expect(data).toEqual(expected); - }); - - test('it formats a uncommon process data without any data if fields is empty', () => { - const fields: readonly string[] = []; - const data = formatUncommonProcessesData(fields, hit, processFieldsMap); - const expected: UncommonProcessesEdges = { - cursor: { - tiebreaker: null, - value: '', - }, - node: { - _id: '', - hosts: [], - instances: 0, - process: {}, - }, - }; - expect(data).toEqual(expected); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/lib/uncommon_processes/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/uncommon_processes/elasticsearch_adapter.ts deleted file mode 100644 index 046823da7cb85f..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/uncommon_processes/elasticsearch_adapter.ts +++ /dev/null @@ -1,118 +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 { get, getOr } from 'lodash/fp'; - -import { UncommonProcessesData, UncommonProcessesEdges } from '../../graphql/types'; -import { mergeFieldsWithHit, inspectStringifyObject } from '../../utils/build_query'; -import { processFieldsMap, userFieldsMap } from '../ecs_fields'; -import { FrameworkAdapter, FrameworkRequest, RequestOptionsPaginated } from '../framework'; -import { HostHits, TermAggregation } from '../types'; -import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants'; -import { buildQuery } from './query.dsl'; -import { - UncommonProcessBucket, - UncommonProcessData, - UncommonProcessesAdapter, - UncommonProcessHit, -} from './types'; - -export class ElasticsearchUncommonProcessesAdapter implements UncommonProcessesAdapter { - constructor(private readonly framework: FrameworkAdapter) {} - - public async getUncommonProcesses( - request: FrameworkRequest, - options: RequestOptionsPaginated - ): Promise { - if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { - throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); - } - const dsl = buildQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination; - const totalCount = getOr(0, 'aggregations.process_count.value', response); - const buckets = getOr([], 'aggregations.group_by_process.buckets', response); - const hits = getHits(buckets); - - const uncommonProcessesEdges = hits.map((hit) => - formatUncommonProcessesData(options.fields, hit, { ...processFieldsMap, ...userFieldsMap }) - ); - - const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount; - const edges = uncommonProcessesEdges.splice(cursorStart, querySize - cursorStart); - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - - const showMorePagesIndicator = totalCount > fakeTotalCount; - return { - edges, - inspect, - pageInfo: { - activePage: activePage ? activePage : 0, - fakeTotalCount, - showMorePagesIndicator, - }, - totalCount, - }; - } -} - -export const getHits = (buckets: readonly UncommonProcessBucket[]): readonly UncommonProcessHit[] => - buckets.map((bucket: Readonly) => ({ - _id: bucket.process.hits.hits[0]._id, - _index: bucket.process.hits.hits[0]._index, - _type: bucket.process.hits.hits[0]._type, - _score: bucket.process.hits.hits[0]._score, - _source: bucket.process.hits.hits[0]._source, - sort: bucket.process.hits.hits[0].sort, - cursor: bucket.process.hits.hits[0].cursor, - total: bucket.process.hits.total, - host: getHosts(bucket.hosts.buckets), - })); - -export const getHosts = (buckets: ReadonlyArray<{ key: string; host: HostHits }>) => - buckets.map((bucket) => { - const source = get('host.hits.hits[0]._source', bucket); - return { - id: [bucket.key], - name: get('host.name', source), - }; - }); - -export const formatUncommonProcessesData = ( - fields: readonly string[], - hit: UncommonProcessHit, - fieldMap: Readonly> -): UncommonProcessesEdges => - fields.reduce( - (flattenedFields, fieldName) => { - flattenedFields.node._id = hit._id; - flattenedFields.node.instances = getOr(0, 'total.value', hit); - flattenedFields.node.hosts = hit.host; - if (hit.cursor) { - flattenedFields.cursor.value = hit.cursor; - } - return mergeFieldsWithHit(fieldName, flattenedFields, fieldMap, hit); - }, - { - node: { - _id: '', - instances: 0, - process: {}, - hosts: [], - }, - cursor: { - value: '', - tiebreaker: null, - }, - } - ); diff --git a/x-pack/plugins/security_solution/server/lib/uncommon_processes/index.ts b/x-pack/plugins/security_solution/server/lib/uncommon_processes/index.ts deleted file mode 100644 index 0ba0e90f391e1d..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/uncommon_processes/index.ts +++ /dev/null @@ -1,21 +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 { UncommonProcessesData } from '../../graphql/types'; -import { FrameworkRequest, RequestOptionsPaginated } from '../framework'; -export * from './elasticsearch_adapter'; -import { UncommonProcessesAdapter } from './types'; - -export class UncommonProcesses { - constructor(private readonly adapter: UncommonProcessesAdapter) {} - - public async getUncommonProcesses( - req: FrameworkRequest, - options: RequestOptionsPaginated - ): Promise { - return this.adapter.getUncommonProcesses(req, options); - } -} diff --git a/x-pack/plugins/security_solution/server/lib/uncommon_processes/query.dsl.ts b/x-pack/plugins/security_solution/server/lib/uncommon_processes/query.dsl.ts deleted file mode 100644 index 4563c769cdc31b..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/uncommon_processes/query.dsl.ts +++ /dev/null @@ -1,222 +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 { createQueryFilterClauses } from '../../utils/build_query'; -import { reduceFields } from '../../utils/build_query/reduce_fields'; -import { hostFieldsMap, processFieldsMap, userFieldsMap } from '../ecs_fields'; -import { RequestOptionsPaginated } from '../framework'; - -export const buildQuery = ({ - defaultIndex, - fields, - filterQuery, - pagination: { querySize }, - sourceConfiguration: { - fields: { timestamp }, - }, - timerange: { from, to }, -}: RequestOptionsPaginated) => { - const processUserFields = reduceFields(fields, { ...processFieldsMap, ...userFieldsMap }); - const hostFields = reduceFields(fields, hostFieldsMap); - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [timestamp]: { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const agg = { - process_count: { - cardinality: { - field: 'process.name', - }, - }, - }; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - body: { - aggregations: { - ...agg, - group_by_process: { - terms: { - size: querySize, - field: 'process.name', - order: [ - { - host_count: 'asc', - }, - { - _count: 'asc', - }, - { - _key: 'asc', - }, - ], - }, - aggregations: { - process: { - top_hits: { - size: 1, - sort: [{ '@timestamp': { order: 'desc' } }], - _source: processUserFields, - }, - }, - host_count: { - cardinality: { - field: 'host.name', - }, - }, - hosts: { - terms: { - field: 'host.name', - }, - aggregations: { - host: { - top_hits: { - size: 1, - _source: hostFields, - }, - }, - }, - }, - }, - }, - }, - query: { - bool: { - should: [ - { - bool: { - filter: [ - { - term: { - 'agent.type': 'auditbeat', - }, - }, - { - term: { - 'event.module': 'auditd', - }, - }, - { - term: { - 'event.action': 'executed', - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - term: { - 'agent.type': 'auditbeat', - }, - }, - { - term: { - 'event.module': 'system', - }, - }, - { - term: { - 'event.dataset': 'process', - }, - }, - { - term: { - 'event.action': 'process_started', - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - term: { - 'agent.type': 'winlogbeat', - }, - }, - { - term: { - 'event.code': '4688', - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - term: { - 'winlog.event_id': 1, - }, - }, - { - term: { - 'winlog.channel': 'Microsoft-Windows-Sysmon/Operational', - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - term: { - 'event.type': 'process_start', - }, - }, - { - term: { - 'event.category': 'process', - }, - }, - ], - }, - }, - { - bool: { - filter: [ - { - term: { - 'event.category': 'process', - }, - }, - { - term: { - 'event.type': 'start', - }, - }, - ], - }, - }, - ], - minimum_should_match: 1, - filter, - }, - }, - }, - size: 0, - track_total_hits: false, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/lib/uncommon_processes/types.ts b/x-pack/plugins/security_solution/server/lib/uncommon_processes/types.ts deleted file mode 100644 index dc60de5963a187..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/uncommon_processes/types.ts +++ /dev/null @@ -1,54 +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 { ProcessEcsFields, UncommonProcessesData } from '../../graphql/types'; -import { FrameworkRequest, RequestOptionsPaginated } from '../framework'; -import { Hit, Hits, HostHits, SearchHit, TotalHit } from '../types'; - -export interface UncommonProcessesAdapter { - getUncommonProcesses( - req: FrameworkRequest, - options: RequestOptionsPaginated - ): Promise; -} - -type StringOrNumber = string | number; -export interface UncommonProcessHit extends Hit { - total: TotalHit; - host: Array<{ - id: string[] | string | null | undefined; - name: string[] | string | null | undefined; - }>; - _source: { - '@timestamp': string; - process: ProcessEcsFields; - }; - cursor: string; - sort: StringOrNumber[]; -} - -export type ProcessHits = Hits; - -export interface UncommonProcessBucket { - key: string; - hosts: { - buckets: Array<{ key: string; host: HostHits }>; - }; - process: ProcessHits; -} - -export interface UncommonProcessData extends SearchHit { - sort: string[]; - aggregations: { - process_count: { - value: number; - }; - group_by_process: { - after_key: string; - buckets: UncommonProcessBucket[]; - }; - }; -} diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 0571c4878956f3..22dbd623930c54 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -62,6 +62,7 @@ import { initUsageCollectors } from './usage'; import { AppRequestContext } from './types'; import { registerTrustedAppsRoutes } from './endpoint/routes/trusted_apps'; import { securitySolutionSearchStrategyProvider } from './search_strategy/security_solution'; +import { securitySolutionIndexFieldsProvider } from './search_strategy/index_fields'; import { securitySolutionTimelineSearchStrategyProvider } from './search_strategy/timeline'; export interface SetupPlugins { @@ -277,10 +278,16 @@ export class Plugin implements IPlugin { @@ -29,7 +24,7 @@ describe('Index Fields', () => { sortBy('name', [ { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -37,41 +32,37 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['auditbeat', 'filebeat', 'packetbeat'], + readFromDocValues: true, + esTypes: [], }, { description: 'Each document has an _id that uniquely identifies it', example: 'Y-6TfmcB0WOhS6qyMv3s', - footnote: '', - group: 1, - level: 'core', name: '_id', - required: true, type: 'string', searchable: true, aggregatable: false, - readFromDocValues: true, - category: '_id', + readFromDocValues: false, + category: 'base', indexes: ['auditbeat', 'filebeat', 'packetbeat'], + esTypes: [], }, { description: 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', example: 'auditbeat-8.0.0-2019.02.19-000001', - footnote: '', - group: 1, - level: 'core', name: '_index', - required: true, type: 'string', searchable: true, aggregatable: true, - readFromDocValues: true, - category: '_index', + readFromDocValues: false, + category: 'base', indexes: ['auditbeat', 'filebeat', 'packetbeat'], + esTypes: [], }, { description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', + 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', example: '8a4f500f', name: 'agent.ephemeral_id', type: 'string', @@ -79,18 +70,24 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, + esTypes: [], }, { + description: + 'Deprecated - use agent.name or agent.id to identify an agent. Hostname of the agent. ', name: 'agent.hostname', searchable: true, type: 'string', aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', + 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', example: '8a4f500d', name: 'agent.id', type: 'string', @@ -98,10 +95,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['packetbeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', example: 'foo', name: 'agent.name', type: 'string', @@ -109,10 +108,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat', 'filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', example: 'filebeat', name: 'agent.type', type: 'string', @@ -120,6 +121,8 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat', 'packetbeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'Version of the agent.', @@ -130,6 +133,8 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat', 'filebeat'], + readFromDocValues: false, + esTypes: [], }, ]) ); @@ -146,37 +151,31 @@ describe('Index Fields', () => { { description: 'Each document has an _id that uniquely identifies it', example: 'Y-6TfmcB0WOhS6qyMv3s', - footnote: '', - group: 1, - level: 'core', name: '_id', - required: true, type: 'string', searchable: true, aggregatable: false, - readFromDocValues: true, - category: '_id', + readFromDocValues: false, + category: 'base', indexes: ['auditbeat'], + esTypes: [], }, { description: 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', example: 'auditbeat-8.0.0-2019.02.19-000001', - footnote: '', - group: 1, - level: 'core', name: '_index', - required: true, type: 'string', searchable: true, aggregatable: true, - readFromDocValues: true, - category: '_index', + readFromDocValues: false, + category: 'base', indexes: ['auditbeat'], + esTypes: [], }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -184,10 +183,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['auditbeat'], + readFromDocValues: true, + esTypes: [], }, { description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', + 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', example: '8a4f500f', name: 'agent.ephemeral_id', type: 'string', @@ -195,10 +196,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', example: 'foo', name: 'agent.name', type: 'string', @@ -206,10 +209,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', example: 'filebeat', name: 'agent.type', type: 'string', @@ -217,6 +222,8 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'Version of the agent.', @@ -227,41 +234,37 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'Each document has an _id that uniquely identifies it', example: 'Y-6TfmcB0WOhS6qyMv3s', - footnote: '', - group: 1, - level: 'core', name: '_id', - required: true, type: 'string', searchable: true, aggregatable: false, - readFromDocValues: true, - category: '_id', + category: 'base', indexes: ['filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', example: 'auditbeat-8.0.0-2019.02.19-000001', - footnote: '', - group: 1, - level: 'core', name: '_index', - required: true, type: 'string', searchable: true, aggregatable: true, - readFromDocValues: true, - category: '_index', + category: 'base', indexes: ['filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -269,18 +272,24 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['filebeat'], + readFromDocValues: true, + esTypes: [], }, { + description: + 'Deprecated - use agent.name or agent.id to identify an agent. Hostname of the agent. ', name: 'agent.hostname', searchable: true, type: 'string', aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', example: 'foo', name: 'agent.name', type: 'string', @@ -288,6 +297,8 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'Version of the agent.', @@ -298,41 +309,37 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'Each document has an _id that uniquely identifies it', example: 'Y-6TfmcB0WOhS6qyMv3s', - footnote: '', - group: 1, - level: 'core', name: '_id', - required: true, type: 'string', searchable: true, aggregatable: false, - readFromDocValues: true, - category: '_id', + category: 'base', indexes: ['packetbeat'], + readFromDocValues: false, + esTypes: [], }, { description: 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', example: 'auditbeat-8.0.0-2019.02.19-000001', - footnote: '', - group: 1, - level: 'core', name: '_index', - required: true, type: 'string', searchable: true, aggregatable: true, - readFromDocValues: true, - category: '_index', + category: 'base', indexes: ['packetbeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -340,10 +347,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['packetbeat'], + readFromDocValues: true, + esTypes: [], }, { description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', + 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', example: '8a4f500d', name: 'agent.id', type: 'string', @@ -351,10 +360,12 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['packetbeat'], + readFromDocValues: false, + esTypes: [], }, { description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', example: 'filebeat', name: 'agent.type', type: 'string', @@ -362,6 +373,8 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['packetbeat'], + readFromDocValues: false, + esTypes: [], }, ]); }); @@ -377,8 +390,9 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: false, - category: '_id', + category: 'base', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: @@ -388,12 +402,13 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: true, - category: '_index', + category: 'base', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -401,10 +416,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['auditbeat'], + readFromDocValues: true, }, { description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', + 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', example: '8a4f500f', name: 'agent.ephemeral_id', type: 'string', @@ -412,10 +428,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', example: 'foo', name: 'agent.name', type: 'string', @@ -423,10 +440,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', example: 'filebeat', name: 'agent.type', type: 'string', @@ -434,6 +452,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: 'Version of the agent.', @@ -444,6 +463,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: 'Each document has an _id that uniquely identifies it', @@ -452,8 +472,9 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: false, - category: '_id', + category: 'base', indexes: ['filebeat'], + readFromDocValues: false, }, { description: @@ -463,12 +484,13 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: true, - category: '_index', + category: 'base', indexes: ['filebeat'], + readFromDocValues: false, }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -476,6 +498,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['filebeat'], + readFromDocValues: true, }, { name: 'agent.hostname', @@ -484,10 +507,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, }, { description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', example: 'foo', name: 'agent.name', type: 'string', @@ -495,6 +519,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, }, { description: 'Version of the agent.', @@ -505,6 +530,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, }, { description: 'Each document has an _id that uniquely identifies it', @@ -513,8 +539,9 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: false, - category: '_id', + category: 'base', indexes: ['packetbeat'], + readFromDocValues: false, }, { description: @@ -524,12 +551,13 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: true, - category: '_index', + category: 'base', indexes: ['packetbeat'], + readFromDocValues: false, }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -537,10 +565,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['packetbeat'], + readFromDocValues: true, }, { description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', + 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', example: '8a4f500d', name: 'agent.id', type: 'string', @@ -548,10 +577,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['packetbeat'], + readFromDocValues: false, }, { description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', example: 'filebeat', name: 'agent.type', type: 'string', @@ -559,6 +589,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['packetbeat'], + readFromDocValues: false, }, ]); expect(fields).toEqual([ @@ -569,8 +600,9 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: false, - category: '_id', + category: 'base', indexes: ['auditbeat', 'filebeat', 'packetbeat'], + readFromDocValues: false, }, { description: @@ -580,12 +612,13 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: true, - category: '_index', + category: 'base', indexes: ['auditbeat', 'filebeat', 'packetbeat'], + readFromDocValues: false, }, { description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', example: '2016-05-23T08:05:34.853Z', name: '@timestamp', type: 'date', @@ -593,10 +626,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'base', indexes: ['auditbeat', 'filebeat', 'packetbeat'], + readFromDocValues: true, }, { description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', + 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', example: '8a4f500f', name: 'agent.ephemeral_id', type: 'string', @@ -604,10 +638,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat'], + readFromDocValues: false, }, { description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', example: 'foo', name: 'agent.name', type: 'string', @@ -615,10 +650,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat', 'filebeat'], + readFromDocValues: false, }, { description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', example: 'filebeat', name: 'agent.type', type: 'string', @@ -626,6 +662,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat', 'packetbeat'], + readFromDocValues: false, }, { description: 'Version of the agent.', @@ -636,6 +673,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['auditbeat', 'filebeat'], + readFromDocValues: false, }, { name: 'agent.hostname', @@ -644,10 +682,11 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['filebeat'], + readFromDocValues: false, }, { description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', + 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', example: '8a4f500d', name: 'agent.id', type: 'string', @@ -655,6 +694,7 @@ describe('Index Fields', () => { aggregatable: true, category: 'agent', indexes: ['packetbeat'], + readFromDocValues: false, }, ]); }); @@ -669,22 +709,22 @@ describe('Index Fields', () => { type: 'string', searchable: true, aggregatable: false, + readFromDocValues: false, + esTypes: [], }, 0 ); expect(item).toEqual({ description: 'Each document has an _id that uniquely identifies it', example: 'Y-6TfmcB0WOhS6qyMv3s', - footnote: '', - group: 1, - level: 'core', name: '_id', - required: true, type: 'string', searchable: true, aggregatable: false, - category: '_id', + category: 'base', indexes: ['auditbeat'], + readFromDocValues: false, + esTypes: [], }); }); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts b/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts new file mode 100644 index 00000000000000..403a9425b221fa --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts @@ -0,0 +1,224 @@ +/* + * 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 isEmpty from 'lodash/isEmpty'; +import { IndexPatternsFetcher, ISearchStrategy } from '../../../../../../src/plugins/data/server'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { FieldDescriptor } from '../../../../../../src/plugins/data/server/index_patterns'; +import { + IndexFieldsStrategyResponse, + IndexField, + IndexFieldsStrategyRequest, +} from '../../../common/search_strategy/index_fields'; + +import { fieldsBeat } from '../../utils/beat_schema/fields'; + +export const securitySolutionIndexFieldsProvider = (): ISearchStrategy< + IndexFieldsStrategyRequest, + IndexFieldsStrategyResponse +> => { + return { + search: async (context, request) => { + const { elasticsearch } = context.core; + const indexPatternsFetcher = new IndexPatternsFetcher( + elasticsearch.legacy.client.callAsCurrentUser + ); + const dedupeIndices = dedupeIndexName(request.indices); + + const responsesIndexFields = await Promise.all( + dedupeIndices + .map((index) => + indexPatternsFetcher.getFieldsForWildcard({ + pattern: index, + }) + ) + .map((p) => p.catch((e) => false)) + ); + let indexFields: IndexField[] = []; + + if (!request.onlyCheckIfIndicesExist) { + indexFields = await formatIndexFields( + responsesIndexFields.filter((rif) => rif !== false) as FieldDescriptor[][], + dedupeIndices + ); + } + + return Promise.resolve({ + indexFields, + indicesExist: dedupeIndices.filter((index, i) => responsesIndexFields[i] !== false), + rawResponse: { + timed_out: false, + took: -1, + _shards: { + total: -1, + successful: -1, + failed: -1, + skipped: -1, + }, + hits: { + total: -1, + max_score: -1, + hits: [ + { + _index: '', + _type: '', + _id: '', + _score: -1, + _source: null, + }, + ], + }, + }, + }); + }, + }; +}; + +export const dedupeIndexName = (indices: string[]) => + indices.reduce((acc, index) => { + if (index.trim() !== '' && index.trim() !== '_all' && !acc.includes(index.trim())) { + return [...acc, index]; + } + return acc; + }, []); + +const missingFields: FieldDescriptor[] = [ + { + name: '_id', + type: 'string', + searchable: true, + aggregatable: false, + readFromDocValues: false, + esTypes: [], + }, + { + name: '_index', + type: 'string', + searchable: true, + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, +]; + +/** + * Creates a single field item. + * + * This is a mutatious HOT CODE PATH function that will have array sizes up to 4.7 megs + * in size at a time calling this function repeatedly. This function should be as optimized as possible + * and should avoid any and all creation of new arrays, iterating over the arrays or performing + * any n^2 operations. + * @param indexesAlias The index alias + * @param index The index its self + * @param indexesAliasIdx The index within the alias + */ +export const createFieldItem = ( + indexesAlias: string[], + index: FieldDescriptor, + indexesAliasIdx: number +): IndexField => { + const alias = indexesAlias[indexesAliasIdx]; + return { + ...(fieldsBeat[index.name] ?? {}), + ...index, + indexes: [alias], + }; +}; + +/** + * This is a mutatious HOT CODE PATH function that will have array sizes up to 4.7 megs + * in size at a time when being called. This function should be as optimized as possible + * and should avoid any and all creation of new arrays, iterating over the arrays or performing + * any n^2 operations. The `.push`, and `forEach` operations are expected within this function + * to speed up performance. + * + * This intentionally waits for the next tick on the event loop to process as the large 4.7 megs + * has already consumed a lot of the event loop processing up to this function and we want to give + * I/O opportunity to occur by scheduling this on the next loop. + * @param responsesIndexFields The response index fields to loop over + * @param indexesAlias The index aliases such as filebeat-* + */ +export const formatFirstFields = async ( + responsesIndexFields: FieldDescriptor[][], + indexesAlias: string[] +): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve( + responsesIndexFields.reduce( + (accumulator: IndexField[], indexFields: FieldDescriptor[], indexesAliasIdx: number) => { + missingFields.forEach((index) => { + const item = createFieldItem(indexesAlias, index, indexesAliasIdx); + accumulator.push(item); + }); + indexFields.forEach((index) => { + const item = createFieldItem(indexesAlias, index, indexesAliasIdx); + accumulator.push(item); + }); + return accumulator; + }, + [] + ) + ); + }); + }); +}; + +/** + * This is a mutatious HOT CODE PATH function that will have array sizes up to 4.7 megs + * in size at a time when being called. This function should be as optimized as possible + * and should avoid any and all creation of new arrays, iterating over the arrays or performing + * any n^2 operations. The `.push`, and `forEach` operations are expected within this function + * to speed up performance. The "indexFieldNameHash" side effect hash avoids additional expensive n^2 + * look ups. + * + * This intentionally waits for the next tick on the event loop to process as the large 4.7 megs + * has already consumed a lot of the event loop processing up to this function and we want to give + * I/O opportunity to occur by scheduling this on the next loop. + * @param fields The index fields to create the secondary fields for + */ +export const formatSecondFields = async (fields: IndexField[]): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + const indexFieldNameHash: Record = {}; + const reduced = fields.reduce((accumulator: IndexField[], indexfield: IndexField) => { + const alreadyExistingIndexField = indexFieldNameHash[indexfield.name]; + if (alreadyExistingIndexField != null) { + const existingIndexField = accumulator[alreadyExistingIndexField]; + if (isEmpty(accumulator[alreadyExistingIndexField].description)) { + accumulator[alreadyExistingIndexField].description = indexfield.description; + } + accumulator[alreadyExistingIndexField].indexes = Array.from( + new Set([...existingIndexField.indexes, ...indexfield.indexes]) + ); + return accumulator; + } + accumulator.push(indexfield); + indexFieldNameHash[indexfield.name] = accumulator.length - 1; + return accumulator; + }, []); + resolve(reduced); + }); + }); +}; + +/** + * Formats the index fields into a format the UI wants. + * + * NOTE: This will have array sizes up to 4.7 megs in size at a time when being called. + * This function should be as optimized as possible and should avoid any and all creation + * of new arrays, iterating over the arrays or performing any n^2 operations. + * @param responsesIndexFields The response index fields to format + * @param indexesAlias The index alias + */ +export const formatIndexFields = async ( + responsesIndexFields: FieldDescriptor[][], + indexesAlias: string[] +): Promise => { + const fields = await formatFirstFields(responsesIndexFields, indexesAlias); + const secondFields = await formatSecondFields(fields); + return secondFields; +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/index_fields/mock.ts b/x-pack/plugins/security_solution/server/search_strategy/index_fields/mock.ts new file mode 100644 index 00000000000000..efb992a868f655 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/index_fields/mock.ts @@ -0,0 +1,113 @@ +/* + * 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. + */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { FieldDescriptor } from '../../../../../../src/plugins/data/server/index_patterns'; + +export const mockAuditbeatIndexField: FieldDescriptor[] = [ + { + name: '@timestamp', + searchable: true, + type: 'date', + aggregatable: true, + readFromDocValues: true, + esTypes: [], + }, + { + name: 'agent.ephemeral_id', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, + { + name: 'agent.name', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, + { + name: 'agent.type', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, + { + name: 'agent.version', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, +]; + +export const mockFilebeatIndexField: FieldDescriptor[] = [ + { + name: '@timestamp', + searchable: true, + type: 'date', + aggregatable: true, + readFromDocValues: true, + esTypes: [], + }, + { + name: 'agent.hostname', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, + { + name: 'agent.name', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, + { + name: 'agent.version', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, +]; + +export const mockPacketbeatIndexField: FieldDescriptor[] = [ + { + name: '@timestamp', + searchable: true, + type: 'date', + aggregatable: true, + readFromDocValues: true, + esTypes: [], + }, + { + name: 'agent.id', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, + { + name: 'agent.type', + searchable: true, + type: 'string', + aggregatable: true, + readFromDocValues: false, + esTypes: [], + }, +]; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/overview/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/overview/index.ts index 7a28c983ec466d..61c228a5fd164d 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/overview/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/overview/index.ts @@ -8,7 +8,7 @@ import { get, getOr } from 'lodash/fp'; import { IEsSearchResponse } from '../../../../../../../../../src/plugins/data/common'; import { - HostOverviewStrategyResponse, + HostsOverviewStrategyResponse, HostsQueries, HostOverviewRequestOptions, OverviewHostHit, @@ -22,7 +22,7 @@ export const hostOverview: SecuritySolutionFactory = { parse: async ( options: HostOverviewRequestOptions, response: IEsSearchResponse - ): Promise => { + ): Promise => { const aggregations: OverviewHostHit = get('aggregations', response.rawResponse) || {}; const inspect = { dsl: [inspectStringifyObject(buildOverviewHostQuery(options))], diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.test.ts index 096ca570ae852a..a6f44c78e5cc4c 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.test.ts @@ -7,8 +7,8 @@ import { processFieldsMap } from '../../../../../../common/ecs/ecs_fields'; import { - UncommonProcessesEdges, - UncommonProcessHit, + HostsUncommonProcessesEdges, + HostsUncommonProcessHit, } from '../../../../../../common/search_strategy'; import { formatUncommonProcessesData, getHosts, UncommonProcessBucket } from './helpers'; @@ -183,7 +183,7 @@ describe('helpers', () => { }); describe('#formatUncommonProcessesData', () => { - const hit: UncommonProcessHit = { + const hit: HostsUncommonProcessHit = { _index: 'index-123', _type: 'type-123', _id: 'id-123', @@ -210,7 +210,7 @@ describe('helpers', () => { test('it formats a uncommon process data with a source of name correctly', () => { const fields: readonly string[] = ['process.name']; const data = formatUncommonProcessesData(fields, hit, processFieldsMap); - const expected: UncommonProcessesEdges = { + const expected: HostsUncommonProcessesEdges = { cursor: { tiebreaker: null, value: 'cursor-1' }, node: { _id: 'id-123', @@ -230,7 +230,7 @@ describe('helpers', () => { test('it formats a uncommon process data with a source of name and title correctly', () => { const fields: readonly string[] = ['process.name', 'process.title']; const data = formatUncommonProcessesData(fields, hit, processFieldsMap); - const expected: UncommonProcessesEdges = { + const expected: HostsUncommonProcessesEdges = { cursor: { tiebreaker: null, value: 'cursor-1' }, node: { _id: 'id-123', @@ -251,7 +251,7 @@ describe('helpers', () => { test('it formats a uncommon process data without any data if fields is empty', () => { const fields: readonly string[] = []; const data = formatUncommonProcessesData(fields, hit, processFieldsMap); - const expected: UncommonProcessesEdges = { + const expected: HostsUncommonProcessesEdges = { cursor: { tiebreaker: null, value: '', diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.ts index 5c3d76175b7e4a..20b3f5b05bc87d 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/helpers.ts @@ -9,8 +9,8 @@ import { set } from '@elastic/safer-lodash-set/fp'; import { mergeFieldsWithHit } from '../../../../../utils/build_query'; import { ProcessHits, - UncommonProcessesEdges, - UncommonProcessHit, + HostsUncommonProcessesEdges, + HostsUncommonProcessHit, } from '../../../../../../common/search_strategy/security_solution/hosts/uncommon_processes'; import { toArray } from '../../../../helpers/to_array'; import { HostHits } from '../../../../../../common/search_strategy'; @@ -25,7 +25,9 @@ export const uncommonProcessesFields = [ 'hosts.name', ]; -export const getHits = (buckets: readonly UncommonProcessBucket[]): readonly UncommonProcessHit[] => +export const getHits = ( + buckets: readonly UncommonProcessBucket[] +): readonly HostsUncommonProcessHit[] => buckets.map((bucket: Readonly) => ({ _id: bucket.process.hits.hits[0]._id, _index: bucket.process.hits.hits[0]._index, @@ -57,10 +59,10 @@ export const getHosts = (buckets: ReadonlyArray<{ key: string; host: HostHits }> export const formatUncommonProcessesData = ( fields: readonly string[], - hit: UncommonProcessHit, + hit: HostsUncommonProcessHit, fieldMap: Readonly> -): UncommonProcessesEdges => - fields.reduce( +): HostsUncommonProcessesEdges => + fields.reduce( (flattenedFields, fieldName) => { flattenedFields.node._id = hit._id; flattenedFields.node.instances = getOr(0, 'total.value', hit); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.test.ts index a5fa9b459d1bf9..5016c8cc38ce44 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.test.ts @@ -6,7 +6,7 @@ import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants'; -import { HostUncommonProcessesRequestOptions } from '../../../../../../common/search_strategy/security_solution'; +import { HostsUncommonProcessesRequestOptions } from '../../../../../../common/search_strategy/security_solution'; import * as buildQuery from './dsl/query.dsl'; import { uncommonProcesses } from '.'; import { @@ -35,7 +35,7 @@ describe('uncommonProcesses search strategy', () => { ...mockOptions.pagination, querySize: DEFAULT_MAX_TABLE_QUERY_SIZE, }, - } as HostUncommonProcessesRequestOptions; + } as HostsUncommonProcessesRequestOptions; expect(() => { uncommonProcesses.buildDsl(overSizeOptions); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.ts index 5682e63b50ed0c..add2cdb76628ad 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/index.ts @@ -12,8 +12,8 @@ import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants import { HostsQueries } from '../../../../../../common/search_strategy/security_solution'; import { processFieldsMap, userFieldsMap } from '../../../../../../common/ecs/ecs_fields'; import { - HostUncommonProcessesRequestOptions, - HostUncommonProcessesStrategyResponse, + HostsUncommonProcessesRequestOptions, + HostsUncommonProcessesStrategyResponse, } from '../../../../../../common/search_strategy/security_solution/hosts/uncommon_processes'; import { inspectStringifyObject } from '../../../../../utils/build_query'; @@ -23,16 +23,16 @@ import { buildQuery } from './dsl/query.dsl'; import { formatUncommonProcessesData, getHits, uncommonProcessesFields } from './helpers'; export const uncommonProcesses: SecuritySolutionFactory = { - buildDsl: (options: HostUncommonProcessesRequestOptions) => { + buildDsl: (options: HostsUncommonProcessesRequestOptions) => { if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); } return buildQuery(options); }, parse: async ( - options: HostUncommonProcessesRequestOptions, + options: HostsUncommonProcessesRequestOptions, response: IEsSearchResponse - ): Promise => { + ): Promise => { const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination; const totalCount = getOr(0, 'aggregations.process_count.value', response.rawResponse); const buckets = getOr([], 'aggregations.group_by_process.buckets', response.rawResponse); diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/helpers.ts index edff22766cc54e..b2ce57d87ae6d8 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/all/helpers.ts @@ -19,6 +19,7 @@ export const formatTimelineData = ( flattenedFields.node._id = hit._id; flattenedFields.node._index = hit._index; flattenedFields.node.ecs._id = hit._id; + flattenedFields.node.ecs.timestamp = hit._source['@timestamp']; flattenedFields.node.ecs._index = hit._index; if (hit.sort && hit.sort.length > 1) { flattenedFields.cursor.value = hit.sort[0]; diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/details/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/details/helpers.ts index 3b0935db9a5d66..2dd406ffaa4504 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/details/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/factory/events/details/helpers.ts @@ -7,7 +7,8 @@ import { get, isEmpty, isNumber, isObject, isString } from 'lodash/fp'; import { TimelineEventsDetailsItem } from '../../../../../../common/search_strategy/timeline'; -import { baseCategoryFields } from '../../../../../utils/beat_schema/8.0.0'; + +export const baseCategoryFields = ['@timestamp', 'labels', 'message', 'tags']; export const getFieldCategory = (field: string): string => { const fieldCategory = field.split('.')[0]; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/auditbeat.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/auditbeat.ts deleted file mode 100644 index 76c865679dd058..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/auditbeat.ts +++ /dev/null @@ -1,7902 +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. - */ - -/** - * An instance of the unmodified schema exported from auditbeat-8.0.0-SNAPSHOT-darwin-x86_64.tar.gz - * - */ - -import { Schema } from '../type'; - -export const auditbeatSchema: Schema = [ - { - key: 'ecs', - title: 'ECS', - description: 'ECS Fields.', - fields: [ - { - name: '@timestamp', - level: 'core', - required: true, - type: 'date', - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'labels', - level: 'core', - type: 'object', - object_type: 'keyword', - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - }, - { - name: 'tags', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - }, - { - name: 'agent', - title: 'Agent', - group: 2, - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - footnote: - 'Examples: In the case of Beats for logs, the agent.name is filebeat.\nFor APM, it is the agent running in the app/service. The agent information does\nnot change if data is sent through queuing systems like Kafka, Redis, or processing\nsystems such as Logstash or APM Server.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the agent.', - example: '6.0.0-rc2', - }, - ], - }, - { - name: 'as', - title: 'Autonomous System', - group: 2, - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - type: 'group', - fields: [ - { - name: 'number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - ], - }, - { - name: 'client', - title: 'Client', - group: 2, - description: - 'A client is defined as the initiator of a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the client is the initiator of the TCP connection that sends\nthe SYN packet(s). For other protocols, the client is generally the initiator\nor requestor in the network transaction. Some systems use the term "originator"\nto refer the client in TCP connections. The client fields describe details about\nthe system acting as the client in the network event. Client fields are usually\npopulated in conjunction with server fields. Client fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event client addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the client to the server.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Client domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the client.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the client.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated IP of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the client to the server.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the client.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered client domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'cloud', - title: 'Cloud', - group: 2, - description: 'Fields related to the cloud or infrastructure the events are coming\nfrom.', - footnote: - 'Examples: If Metricbeat is running on an EC2 host and fetches data\nfrom its host, the cloud info contains the data about this machine. If Metricbeat\nruns on a remote machine outside the cloud and fetches data from a service running\nin the cloud, the field contains cloud data from the machine the service is\nrunning on.', - type: 'group', - fields: [ - { - name: 'account.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The cloud account or organization id used to identify different\nentities in a multi-tenant environment.\n\nExamples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: 666777888999, - }, - { - name: 'availability_zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - }, - { - name: 'instance.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance ID of the host machine.', - example: 'i-1234567890abcdef0', - }, - { - name: 'instance.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance name of the host machine.', - }, - { - name: 'machine.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Machine type of the host machine.', - example: 't2.medium', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the cloud provider. Example values are aws, azure, gcp,\nor digitalocean.', - example: 'aws', - }, - { - name: 'region', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Region in which this host is running.', - example: 'us-east-1', - }, - ], - }, - { - name: 'code_signature', - title: 'Code Signature', - group: 2, - description: 'These fields contain information about binary code signatures.', - type: 'group', - fields: [ - { - name: 'exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - ], - }, - { - name: 'container', - title: 'Container', - group: 2, - description: - 'Container fields are used for meta information about the specific\ncontainer that is the source of information.\n\nThese fields help correlate data based containers from any runtime.', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique container id.', - }, - { - name: 'image.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the image the container was built on.', - }, - { - name: 'image.tag', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container image tags.', - }, - { - name: 'labels', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: 'Image labels.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container name.', - }, - { - name: 'runtime', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Runtime managing this container.', - example: 'docker', - }, - ], - }, - { - name: 'destination', - title: 'Destination', - group: 2, - description: - 'Destination fields describe details about the destination of a packet/event.\n\nDestination fields are usually populated in conjunction with source fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event destination addresses are defined ambiguously. The\nevent will sometimes list an IP, a domain or a unix socket. You should always\nstore the raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the destination to the source.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Destination domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the destination.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the destination.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Port the source session is translated to by NAT Device.\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the destination to the source.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the destination.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered destination domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'dll', - title: 'DLL', - group: 2, - description: - 'These fields contain information about code libraries dynamically\nloaded into processes.\n\n\nMany operating systems refer to "shared code libraries" with different names,\nbut this field set refers to all of the following:\n\n* Dynamic-link library (`.dll`) commonly used on Windows\n\n* Shared Object (`.so`) commonly used on Unix-like operating systems\n\n* Dynamic library (`.dylib`) commonly used on macOS', - type: 'group', - fields: [ - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the library.\n\nThis generally maps to the name of the file on disk.', - example: 'kernel32.dll', - default_field: false, - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Full file path of the library.', - example: 'C:\\Windows\\System32\\kernel32.dll', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'dns', - title: 'DNS', - group: 2, - description: - 'Fields describing DNS queries and answers.\n\nDNS events should either represent a single DNS query prior to getting answers\n(`dns.type:query`) or they should represent a full exchange and contain the\nquery details as well as all of the answers that were provided for this query\n(`dns.type:answer`).', - type: 'group', - fields: [ - { - name: 'answers', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'An array containing an object for each answer section returned\nby the server.\n\nThe main keys that should be present in these objects are defined by ECS.\nRecords that have more information may contain more keys than what ECS defines.\n\nNot all DNS data sources give all details about DNS answers. At minimum, answer\nobjects must contain the `data` key. If more information is available, map\nas much of it to ECS as possible, and add any additional fields to the answer\nobjects as custom fields.', - }, - { - name: 'answers.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of DNS data contained in this resource record.', - example: 'IN', - }, - { - name: 'answers.data', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The data describing the resource.\n\nThe meaning of this data depends on the type and class of the resource record.', - example: '10.10.10.10', - }, - { - name: 'answers.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The domain name to which this resource record pertains.\n\nIf a chain of CNAME is being resolved, each answer `name` should be the\none that corresponds with the answer `data`. It should not simply be the\noriginal `question.name` repeated.', - example: 'www.google.com', - }, - { - name: 'answers.ttl', - level: 'extended', - type: 'long', - description: - 'The time interval in seconds that this resource record may be cached\nbefore it should be discarded. Zero values mean that the data should not be\ncached.', - example: 180, - }, - { - name: 'answers.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of data contained in this resource record.', - example: 'CNAME', - }, - { - name: 'header_flags', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of 2 letter DNS header flags.\n\nExpected values are: AA, TC, RD, RA, AD, CD, DO.', - example: ['RD', 'RA'], - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS packet identifier assigned by the program that generated\nthe query. The identifier is copied to the response.', - example: 62111, - }, - { - name: 'op_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS operation code that specifies the kind of query in the\nmessage. This value is set by the originator of a query and copied into the\nresponse.', - example: 'QUERY', - }, - { - name: 'question.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of records being queried.', - example: 'IN', - }, - { - name: 'question.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name being queried.\n\nIf the name field contains non-printable characters (below 32 or above 126),\nthose characters should be represented as escaped base 10 integers (\\DDD).\nBack slashes and quotes should be escaped. Tabs, carriage returns, and line\nfeeds should be converted to \\t, \\r, and \\n respectively.', - example: 'www.google.com', - }, - { - name: 'question.registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'question.subdomain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The subdomain is all of the labels under the registered_domain.\n\nIf the domain has multiple levels of subdomain, such as "sub2.sub1.example.com",\nthe subdomain field should contain "sub2.sub1", with no trailing period.', - example: 'www', - }, - { - name: 'question.top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'question.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of record being queried.', - example: 'AAAA', - }, - { - name: 'resolved_ip', - level: 'extended', - type: 'ip', - description: - 'Array containing all IPs seen in `answers.data`.\n\nThe `answers` array can be difficult to use, because of the variety of data\nformats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip`\nmakes it possible to index them as IP addresses, and makes them easier to\nvisualize and query for.', - example: ['10.10.10.10', '10.10.10.11'], - }, - { - name: 'response_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The DNS response code.', - example: 'NOERROR', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of DNS event captured, query or answer.\n\nIf your source of DNS events only gives you DNS queries, you should only create\ndns events of type `dns.type:query`.\n\nIf your source of DNS events gives you answers as well, you should create\none event per query (optionally as soon as the query is seen). And a second\nevent containing all query details as well as an array of answers.', - example: 'answer', - }, - ], - }, - { - name: 'ecs', - title: 'ECS', - group: 2, - description: 'Meta-information specific to ECS.', - type: 'group', - fields: [ - { - name: 'version', - level: 'core', - required: true, - type: 'keyword', - ignore_above: 1024, - description: - 'ECS version this event conforms to. `ecs.version` is a required\nfield and must exist in all events.\n\nWhen querying across multiple indices -- which may conform to slightly different\nECS versions -- this field lets integrations adjust to the schema version\nof the events.', - example: '1.0.0', - }, - ], - }, - { - name: 'error', - title: 'Error', - group: 2, - description: - 'These fields can represent errors of any kind.\n\nUse them for errors that happen while fetching events or in cases where the\nevent itself contains an error.', - type: 'group', - fields: [ - { - name: 'code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Error code describing the error.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the error.', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: 'Error message.', - }, - { - name: 'stack_trace', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The stack trace of this error in plain text.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of the error, for example the class name of the exception.', - example: 'java.lang.NullPointerException', - }, - ], - }, - { - name: 'event', - title: 'Event', - group: 2, - description: - 'The event fields are used for context information about the log\nor metric event itself.\n\nA log is defined as an event containing details of something that happened.\nLog events must include the time at which the thing happened. Examples of log\nevents include a process starting on a host, a network packet being sent from\na source to a destination, or a network connection between a client and a server\nbeing initiated or closed. A metric is defined as an event containing one or\nmore numerical measurements and the time at which the measurement was taken.\nExamples of metric events include memory pressure measured on a host and device\ntemperature. See the `event.kind` definition in this section for additional\ndetails about metric and state events.', - type: 'group', - fields: [ - { - name: 'action', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.', - example: 'user-password-change', - }, - { - name: 'category', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nsecond level in the ECS category hierarchy.\n\n`event.category` represents the "big buckets" of ECS categories. For example,\nfiltering on `event.category:process` yields all events relating to process\nactivity. This field is closely related to `event.type`, which is used as\na subcategory.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple categories.', - example: 'authentication', - }, - { - name: 'code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Identification code for this event, if one exists.\n\nSome event sources use event codes to identify messages unambiguously, regardless\nof message language or wording adjustments over time. An example of this is\nthe Windows Event ID.', - example: 4648, - }, - { - name: 'created', - level: 'core', - type: 'date', - description: - 'event.created contains the date/time when the event was first\nread by an agent, or by your pipeline.\n\nThis field is distinct from @timestamp in that @timestamp typically contain\nthe time extracted from the original event.\n\nIn most situations, these two timestamps will be slightly different. The difference\ncan be used to calculate the delay between your source generating an event,\nand the time when your agent first processed it. This can be used to monitor\nyour agent or pipeline ability to keep up with your event source.\n\nIn case the two timestamps are identical, @timestamp should be used.', - example: '2016-05-23T08:05:34.857Z', - }, - { - name: 'dataset', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the dataset.\n\nIf an event source publishes more than one type of log or events (e.g. access\nlog, error log), the dataset is used to specify which one the event comes\nfrom.\n\nIt is recommended but not required to start the dataset name with the module\nname, followed by a dot, then the dataset name.', - example: 'apache.access', - }, - { - name: 'duration', - level: 'core', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - output_format: 'asMilliseconds', - output_precision: 1, - description: - 'Duration of the event in nanoseconds.\n\nIf event.start and event.end are known this value should be the difference\nbetween the end and start time.', - }, - { - name: 'end', - level: 'extended', - type: 'date', - description: - 'event.end contains the date when the event ended or when the activity\nwas last observed.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Hash (perhaps logstash fingerprint) of raw field to be able to\ndemonstrate log integrity.', - example: '123456789012345678901234567890ABCD', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique ID to describe the event.', - example: '8a4f500d', - }, - { - name: 'ingested', - level: 'core', - type: 'date', - description: - 'Timestamp when an event arrived in the central data store.\n\nThis is different from `@timestamp`, which is when the event originally occurred. It is\nalso different from `event.created`, which is meant to capture the first time\nan agent saw the event.\n\nIn normal conditions, assuming no tampering, the timestamps should chronologically\nlook like this: `@timestamp` < `event.created` < `event.ingested`.', - example: '2016-05-23T08:05:35.101Z', - default_field: false, - }, - { - name: 'kind', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nhighest level in the ECS category hierarchy.\n\n`event.kind` gives high-level information about what type of information the\nevent contains, without being specific to the contents of the event. For example,\nvalues of this field distinguish alert events from metric events.\n\nThe value of this field can be used to inform how these kinds of events should\nbe handled. They may warrant different retention, different access control,\nit may also help understand whether the data coming in at a regular interval\nor not.', - example: 'alert', - }, - { - name: 'module', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the module this data is coming from.\n\nIf your monitoring agent supports the concept of modules or plugins to process\nevents of a given source (e.g. Apache logs), `event.module` should contain\nthe name of this module.', - example: 'apache', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Raw text message of entire event. Used to demonstrate log integrity.\n\nThis field is not indexed and doc_values are disabled. It cannot be searched,\nbut it can be retrieved from `_source`.', - example: - 'Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100|\nworm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232', - }, - { - name: 'outcome', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nlowest level in the ECS category hierarchy.\n\n`event.outcome` simply denotes whether the event represents a success or a\nfailure from the perspective of the entity that produced the event.\n\nNote that when a single transaction is described in multiple events, each\nevent may populate different values of `event.outcome`, according to their\nperspective.\n\nAlso note that in the case of a compound event (a single event that contains\nmultiple logical events), this field should be populated with the value that\nbest captures the overall success or failure from the perspective of the event\nproducer.\n\nFurther note that not all events will have an associated outcome. For example,\nthis field is generally not populated for metric events, events with `event.type:info`,\nor any events for which an outcome does not make logical sense.', - example: 'success', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Source of the event.\n\nEvent transports such as Syslog or the Windows Event Log typically mention\nthe source of an event. It can be the name of the software that generated\nthe event (e.g. Sysmon, httpd), or of a subsystem of the operating system\n(kernel, Microsoft-Windows-Security-Auditing).', - example: 'kernel', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL linking to additional information about this event.\n\nThis URL links to a static definition of the this event. Alert events, indicated\nby `event.kind:alert`, are a common use case for this field.', - example: 'https://system.vendor.com/event/#0001234', - default_field: false, - }, - { - name: 'risk_score', - level: 'core', - type: 'float', - description: - "Risk score or priority of the event (e.g. security solutions).\nUse your system's original value here.", - }, - { - name: 'risk_score_norm', - level: 'extended', - type: 'float', - description: - 'Normalized risk score or priority of the event, on a scale of\n0 to 100.\n\nThis is mainly useful if you use more than one system that assigns risk scores,\nand you want to see a normalized value across all systems.', - }, - { - name: 'sequence', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Sequence number of the event.\n\nThe sequence number is a value published by some event sources, to make the\nexact ordering of events unambiguous, regardless of the timestamp precision.', - }, - { - name: 'severity', - level: 'core', - type: 'long', - format: 'string', - description: - 'The numeric severity of the event according to your event source.\n\nWhat the different severity values mean can be different between sources and\nuse cases. It is up to the implementer to make sure severities are consistent\nacross events from the same source.\n\nThe Syslog severity belongs in `log.syslog.severity.code`. `event.severity`\nis meant to represent the severity according to the event source (e.g. firewall,\nIDS). If the event source does not publish its own severity, you may optionally\ncopy the `log.syslog.severity.code` to `event.severity`.', - example: 7, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: - 'event.start contains the date when the event started or when the\nactivity was first observed.', - }, - { - name: 'timezone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'This field should be populated when the event timestamp does\nnot include timezone information already (e.g. default Syslog timestamps).\nIt is optional otherwise.\n\nAcceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"),\nabbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nthird level in the ECS category hierarchy.\n\n`event.type` represents a categorization "sub-bucket" that, when used along\nwith the `event.category` field values, enables filtering events down to a\nlevel appropriate for single visualization.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple event types.', - }, - { - name: 'url', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'URL linking to an external system to continue investigation of\nthis event.\n\nThis URL links to another system where in-depth investigation of the specific\noccurence of this event can take place. Alert events, indicated by `event.kind:alert`,\nare a common use case for this field.', - example: 'https://mysystem.mydomain.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe', - default_field: false, - }, - ], - }, - { - name: 'file', - title: 'File', - group: 2, - description: - 'A file is defined as a set of information that has been created\non, or has existed on a filesystem.\n\nFile objects can be associated with host events, network events, and/or file\nevents (e.g., those produced by File Integrity Monitoring [FIM] products or\nservices). File fields provide details about the affected file associated with\nthe event or metric.', - type: 'group', - fields: [ - { - name: 'accessed', - level: 'extended', - type: 'date', - description: - 'Last time the file was accessed.\n\nNote that not all filesystems keep track of access time.', - }, - { - name: 'attributes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of file attributes.\n\nAttributes names will vary by platform. Here is a non-exhaustive list of values\nthat are expected in this field: archive, compressed, directory, encrypted,\nexecute, hidden, read, readonly, system, write.', - example: '["readonly", "system"]', - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'created', - level: 'extended', - type: 'date', - description: - 'File creation time.\n\nNote that not all filesystems store the creation time.', - }, - { - name: 'ctime', - level: 'extended', - type: 'date', - description: - 'Last time the file attributes or metadata changed.\n\nNote that changes to the file content will update `mtime`. This implies `ctime`\nwill be adjusted at the same time, since `mtime` is an attribute of the file.', - }, - { - name: 'device', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Device that is the source of the file.', - example: 'sda', - }, - { - name: 'directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Directory where the file is located. It should include the drive\nletter, when appropriate.', - example: '/home/alice', - }, - { - name: 'drive_letter', - level: 'extended', - type: 'keyword', - ignore_above: 1, - description: - 'Drive letter where the file is located. This field is only relevant\non Windows.\n\nThe value should be uppercase, and not include the colon.', - example: 'C', - default_field: false, - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File extension.', - example: 'png', - }, - { - name: 'gid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group ID (GID) of the file.', - example: '1001', - }, - { - name: 'group', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group name of the file.', - example: 'alice', - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'inode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Inode representing the file in the filesystem.', - example: '256383', - }, - { - name: 'mime_type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'MIME type should identify the format of the file or stream of bytes\nusing https://www.iana.org/assignments/media-types/media-types.xhtml[IANA\nofficial types], where possible. When more than one type is applicable, the\nmost specific type should be used.', - default_field: false, - }, - { - name: 'mode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Mode of the file in octal representation.', - example: '0640', - }, - { - name: 'mtime', - level: 'extended', - type: 'date', - description: 'Last time the file content was modified.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the file including the extension, without the directory.', - example: 'example.png', - }, - { - name: 'owner', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: "File owner's username.", - example: 'alice', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Full path to the file, including the file name. It should include\nthe drive letter, when appropriate.', - example: '/home/alice/example.png', - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - description: 'File size in bytes.\n\nOnly relevant when `file.type` is "file".', - example: 16384, - }, - { - name: 'target_path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Target path for symlinks.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File type (file, dir, or symlink).', - example: 'file', - }, - { - name: 'uid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The user ID (UID) or security identifier (SID) of the file owner.', - example: '1001', - }, - ], - }, - { - name: 'geo', - title: 'Geo', - group: 2, - description: - 'Geo fields can carry data about a specific location related to an\nevent.\n\nThis geolocation information can be derived from techniques such as Geo IP,\nor be user-supplied.', - type: 'group', - fields: [ - { - name: 'city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - ], - }, - { - name: 'group', - title: 'Group', - group: 2, - description: - 'The group fields are meant to represent groups that are relevant\nto the event.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - ], - }, - { - name: 'hash', - title: 'Hash', - group: 2, - description: - 'The hash fields represent different hash algorithms and their values.\n\nField names for common hashes (e.g. MD5, SHA1) are predefined. Add fields for\nother hashes by lowercasing the hash algorithm name and using underscore separators\nas appropriate (snake case, e.g. sha3_512).', - type: 'group', - fields: [ - { - name: 'md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - ], - }, - { - name: 'host', - title: 'Host', - group: 2, - description: - 'A host is defined as a general computing instance.\n\nECS host.* fields should be populated with details about the host on which the\nevent happened, or from which the measurement was taken. Host types include\nhardware, virtual machines, Docker containers, and Kubernetes nodes.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system architecture.', - example: 'x86_64', - }, - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the domain of which the host is a member.\n\nFor example, on Windows this could be the host Active Directory domain\nor NetBIOS domain name. For Linux this could be the domain of the host\nLDAP provider.', - example: 'CONTOSO', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Hostname of the host.\n\nIt normally contains what the `hostname` command returns on the host machine.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique host id.\n\nAs hostname is not always unique, use values that are meaningful in your environment.\n\nExample: The current usage of `beat.name`.', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'Host ip addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Host mac addresses.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of host.\n\nFor Cloud providers this can be the machine type like `t2.medium`. If vm,\nthis could be the container, for example, or other information meaningful\nin your environment.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the host has been up.', - example: 1325, - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'http', - title: 'HTTP', - group: 2, - description: - 'Fields related to HTTP activity. Use the `url` field set to store\nthe url of the request.', - type: 'group', - fields: [ - { - name: 'request.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the request body.', - example: 887, - }, - { - name: 'request.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP request body.', - example: 'Hello world', - }, - { - name: 'request.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the request (body and headers).', - example: 1437, - }, - { - name: 'request.method', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'HTTP request method.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'get, post, put', - }, - { - name: 'request.referrer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Referrer for this HTTP request.', - example: 'https://blog.example.com/', - }, - { - name: 'response.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the response body.', - example: 887, - }, - { - name: 'response.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP response body.', - example: 'Hello world', - }, - { - name: 'response.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the response (body and headers).', - example: 1437, - }, - { - name: 'response.status_code', - level: 'extended', - type: 'long', - format: 'string', - description: 'HTTP response status code.', - example: 404, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'HTTP version.', - example: 1.1, - }, - ], - }, - { - name: 'interface', - title: 'Interface', - group: 2, - description: - 'The interface fields are used to record ingress and egress interface\ninformation when reported by an observer (e.g. firewall, router, load balancer)\nin the context of the observer handling a network connection. In the case of\na single observer interface (e.g. network sensor on a span port) only the observer.ingress\ninformation should be populated.', - type: 'group', - fields: [ - { - name: 'alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - ], - }, - { - name: 'log', - title: 'Log', - group: 2, - description: - 'Details about the event logging mechanism or logging transport.\n\nThe log.* fields are typically populated with details about the logging mechanism\nused to create and/or transport the event. For example, syslog details belong\nunder `log.syslog.*`.\n\nThe details specific to your event source are typically not logged under `log.*`,\nbut rather in `event.*` or in other ECS fields.', - type: 'group', - fields: [ - { - name: 'level', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Original log level of the log event.\n\nIf the source of the event provides a log level or textual severity, this\nis the one that goes in `log.level`. If your source does not specify one,\nyou may put your event transport severity here (e.g. Syslog severity).\n\nSome examples are `warn`, `err`, `i`, `informational`.', - example: 'error', - }, - { - name: 'logger', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the logger inside an application. This is usually the\nname of the class which initialized the logger, or can be a custom name.', - example: 'org.elasticsearch.bootstrap.Bootstrap', - }, - { - name: 'origin.file.line', - level: 'extended', - type: 'integer', - description: - 'The line number of the file containing the source code which originated\nthe log event.', - example: 42, - }, - { - name: 'origin.file.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the file containing the source code which originated\nthe log event. Note that this is not the name of the log file.', - example: 'Bootstrap.java', - }, - { - name: 'origin.function', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the function or method which originated the log event.', - example: 'init', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is the original log message and contains the full log message\nbefore splitting it up in multiple parts.\n\nIn contrast to the `message` field which can contain an extracted part of\nthe log message, this field contains the original, full log message. It can\nhave already some modifications applied like encoding or new lines removed\nto clean up the log message.\n\nThis field is not indexed and doc_values are disabled so it cannot be queried\nbut the value can be retrieved from `_source`.', - example: 'Sep 19 08:26:10 localhost My log', - }, - { - name: 'syslog', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'The Syslog metadata of the event, if the event was transmitted\nvia Syslog. Please see RFCs 5424 or 3164.', - }, - { - name: 'syslog.facility.code', - level: 'extended', - type: 'long', - format: 'string', - description: - 'The Syslog numeric facility of the log event, if available.\n\nAccording to RFCs 5424 and 3164, this value should be an integer between 0\nand 23.', - example: 23, - }, - { - name: 'syslog.facility.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The Syslog text-based facility of the log event, if available.', - example: 'local7', - }, - { - name: 'syslog.priority', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Syslog numeric priority of the event, if available.\n\nAccording to RFCs 5424 and 3164, the priority is 8 * facility + severity.\nThis number is therefore expected to contain a value between 0 and 191.', - example: 135, - }, - { - name: 'syslog.severity.code', - level: 'extended', - type: 'long', - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different numeric severity\nvalue (e.g. firewall, IDS), your source numeric severity should go to `event.severity`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `event.severity`.', - example: 3, - }, - { - name: 'syslog.severity.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different severity value\n(e.g. firewall, IDS), your source text severity should go to `log.level`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `log.level`.', - example: 'Error', - }, - ], - }, - { - name: 'network', - title: 'Network', - group: 2, - description: - 'The network is defined as the communication path over which a host\nor network event happens.\n\nThe network.* fields should be populated with details about the network activity\nassociated with an event.', - type: 'group', - fields: [ - { - name: 'application', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A name given to an application level protocol. This can be arbitrarily\nassigned for things like microservices, but also apply to things like skype,\nicq, facebook, twitter. This would be used in situations where the vendor\nor service can be decoded such as from the source/dest IP owners, ports, or\nwire format.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'aim', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: - 'Total bytes transferred in both directions.\n\nIf `source.bytes` and `destination.bytes` are known, `network.bytes` is their\nsum.', - example: 368, - }, - { - name: 'community_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of source and destination IPs and ports, as well as the\nprotocol used in a communication. This is a tool-agnostic standard to identify\nflows.\n\nLearn more at https://github.com/corelight/community-id-spec.', - example: '1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=', - }, - { - name: 'direction', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - "Direction of the network traffic.\nRecommended values are:\n * inbound\n * outbound\n * internal\n * external\n * unknown\n\nWhen mapping events from a host-based monitoring context, populate this field from the host's point of view.\nWhen mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of your network perimeter.", - example: 'inbound', - }, - { - name: 'forwarded_ip', - level: 'core', - type: 'ip', - description: 'Host IP address when the source IP address is the proxy.', - example: '192.1.1.2', - }, - { - name: 'iana_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).\nStandardized list of protocols. This aligns well with NetFlow and sFlow related\nlogs which use the IANA Protocol Number.', - example: 6, - }, - { - name: 'inner', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Network.inner fields are added in addition to network.vlan fields\nto describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed\nfields include vlan.id and vlan.name. Inner vlan fields are typically used\nwhen sending traffic with multiple 802.1q encapsulations to a network sensor\n(e.g. Zeek, Wireshark.)', - default_field: false, - }, - { - name: 'inner.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'inner.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name given by operators to sections of their network.', - example: 'Guest Wifi', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: - 'Total packets transferred in both directions.\n\nIf `source.packets` and `destination.packets` are known, `network.packets`\nis their sum.', - example: 24, - }, - { - name: 'protocol', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'L7 Network protocol name. ex. http, lumberjack, transport protocol.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'http', - }, - { - name: 'transport', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Same as network.iana_number, but instead using the Keyword name\nof the transport layer (udp, tcp, ipv6-icmp, etc.)\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'tcp', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'In the OSI Model this would be the Network Layer. ipv4, ipv6,\nipsec, pim, etc\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'ipv4', - }, - { - name: 'vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'observer', - title: 'Observer', - group: 2, - description: - 'An observer is defined as a special network, security, or application\ndevice used to detect, observe, or create network, security, or application-related\nevents and metrics.\n\nThis could be a custom hardware appliance or a server that has been configured\nto run special network, security, or application software. Examples include\nfirewalls, web proxies, intrusion detection/prevention systems, network monitoring\nsensors, web application firewalls, data loss prevention systems, and APM servers.\nThe observer.* fields shall be populated with details of the system, if any,\nthat detects, observes and/or creates a network, security, or application event\nor metric. Message queues and ETL components used in processing events or metrics\nare not considered observers in ECS.', - type: 'group', - fields: [ - { - name: 'egress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.egress holds information like interface number and name,\nvlan, and zone information to classify egress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'egress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'egress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'egress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'egress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of outbound traffic as reported by the observer to\ncategorize the destination area of egress traffic, e.g. Internal, External,\nDMZ, HR, Legal, etc.', - example: 'Public_Internet', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hostname of the observer.', - }, - { - name: 'ingress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.ingress holds information like interface number and name,\nvlan, and zone information to classify ingress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'ingress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'ingress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'ingress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'ingress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of incoming traffic as reported by the observer to\ncategorize the source area of ingress traffic. e.g. internal, External, DMZ,\nHR, Legal, etc.', - example: 'DMZ', - default_field: false, - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP addresses of the observer.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC addresses of the observer', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the observer.\n\nThis is a name that can be given to an observer. This can be helpful for example\nif multiple firewalls of the same model are used in an organization.\n\nIf no custom name is needed, the field can be left empty.', - example: '1_proxySG', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The product name of the observer.', - example: 's200', - }, - { - name: 'serial_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Observer serial number.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the observer the data is coming from.\n\nThere is no predefined list of observer types. Some examples are `forwarder`,\n`firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.', - example: 'firewall', - }, - { - name: 'vendor', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Vendor name of the observer.', - example: 'Symantec', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Observer version.', - }, - ], - }, - { - name: 'organization', - title: 'Organization', - group: 2, - description: - 'The organization fields enrich data with information about the company\nor entity the data is associated with.\n\nThese fields help you arrange or filter data stored in an index by one or multiple\norganizations.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the organization.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - }, - ], - }, - { - name: 'os', - title: 'Operating System', - group: 2, - description: 'The OS fields contain information about the operating system.', - type: 'group', - fields: [ - { - name: 'family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - ], - }, - { - name: 'package', - title: 'Package', - group: 2, - description: - 'These fields contain information about an installed software package.\nIt contains general information about a package, such as name, version or size.\nIt also contains installation details, such as time or location.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package architecture.', - example: 'x86_64', - }, - { - name: 'build_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the build version of the installed\npackage.\n\nFor example use the commit SHA of a non-released package.', - example: '36f4f7e89dd61b0988b12ee000b98966867710cd', - default_field: false, - }, - { - name: 'checksum', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Checksum of the installed package for verification.', - example: '68b329da9893e34099c7d8ad5cb9c940', - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Description of the package.', - example: - 'Open source programming language to build simple/reliable/efficient\nsoftware.', - }, - { - name: 'install_scope', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Indicating how the package was installed, e.g. user-local, global.', - example: 'global', - }, - { - name: 'installed', - level: 'extended', - type: 'date', - description: 'Time when package was installed.', - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'License under which the package was released.\n\nUse a short name, e.g. the license identifier from SPDX License List where\npossible (https://spdx.org/licenses/).', - example: 'Apache License 2.0', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package name', - example: 'go', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path where the package is installed.', - example: '/usr/local/Cellar/go/1.12.9/', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Home page or reference URL of the software in this package, if\navailable.', - example: 'https://golang.org', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - format: 'string', - description: 'Package size in bytes.', - example: 62231, - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of package.\n\nThis should contain the package file type, rather than the package manager\nname. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar.', - example: 'rpm', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package version', - example: '1.12.9', - }, - ], - }, - { - name: 'pe', - title: 'PE Header', - group: 2, - description: 'These fields contain Windows Portable Executable (PE) metadata.', - type: 'group', - fields: [ - { - name: 'company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'process', - title: 'Process', - group: 2, - description: - 'These fields contain information about a process.\n\nThese fields can help you correlate metrics information with a process id/name\nfrom a log message. The `process.pid` often stays in the metric itself and\nis copied to the global field for correlation.', - type: 'group', - fields: [ - { - name: 'args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.', - example: ['/usr/bin/ssh', '-l', 'user', '10.0.0.16'], - }, - { - name: 'args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - }, - { - name: 'exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - }, - { - name: 'parent.args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments.\n\nMay be filtered to protect sensitive information.', - example: ['ssh', '-l', 'user', '10.0.0.16'], - default_field: false, - }, - { - name: 'parent.args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'parent.code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'parent.code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'parent.code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'parent.command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'parent.entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'parent.executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - default_field: false, - }, - { - name: 'parent.exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'parent.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'parent.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - default_field: false, - }, - { - name: 'parent.pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - default_field: false, - }, - { - name: 'parent.pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - default_field: false, - }, - { - name: 'parent.ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - default_field: false, - }, - { - name: 'parent.start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - default_field: false, - }, - { - name: 'parent.thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - default_field: false, - }, - { - name: 'parent.thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - default_field: false, - }, - { - name: 'parent.title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - default_field: false, - }, - { - name: 'parent.uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - default_field: false, - }, - { - name: 'parent.working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - }, - { - name: 'pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - }, - { - name: 'ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - }, - { - name: 'thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - }, - { - name: 'title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - }, - { - name: 'working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - }, - ], - }, - { - name: 'registry', - title: 'Registry', - group: 2, - description: 'Fields related to Windows Registry operations.', - type: 'group', - fields: [ - { - name: 'data.bytes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Original bytes written with base64 encoding.\n\nFor Windows registry operations, such as SetValueEx and RegQueryValueEx, this\ncorresponds to the data pointed by `lp_data`. This is optional but provides\nbetter recoverability and should be populated for REG_BINARY encoded values.', - example: 'ZQBuAC0AVQBTAAAAZQBuAAAAAAA=', - default_field: false, - }, - { - name: 'data.strings', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Content when writing string types.\n\nPopulated as an array when writing string data to the registry. For single\nstring registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with\none string. For sequences of string with REG_MULTI_SZ, this array will be\nvariable length. For numeric data, such as REG_DWORD and REG_QWORD, this should\nbe populated with the decimal representation (e.g `"1"`).', - example: '["C:\\rta\\red_ttp\\bin\\myapp.exe"]', - default_field: false, - }, - { - name: 'data.type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Standard registry type for encoding contents', - example: 'REG_SZ', - default_field: false, - }, - { - name: 'hive', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Abbreviated name for the hive.', - example: 'HKLM', - default_field: false, - }, - { - name: 'key', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hive-relative path of keys.', - example: - 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe', - default_field: false, - }, - { - name: 'path', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Full path, including hive, key and value', - example: - 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution\nOptions\\winword.exe\\Debugger', - default_field: false, - }, - { - name: 'value', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the value written.', - example: 'Debugger', - default_field: false, - }, - ], - }, - { - name: 'related', - title: 'Related', - group: 2, - description: - 'This field set is meant to facilitate pivoting around a piece of\ndata.\n\nSome pieces of information can be seen in many places in an ECS event. To facilitate\nsearching for them, store an array of all seen values to their corresponding\nfield in `related.`.\n\nA concrete example is IP addresses, which can be under host, observer, source,\ndestination, client, server, and network.forwarded_ip. If you append all IPs\nto `related.ip`, you can then search for a given IP trivially, no matter where\nit appeared, by querying `related.ip:192.0.2.15`.', - type: 'group', - fields: [ - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - "All the hashes seen on your event. Populating this field, then\nusing it to search for hashes can help in situations where you're unsure what\nthe hash algorithm is (and therefore which key name to search).", - default_field: false, - }, - { - name: 'ip', - level: 'extended', - type: 'ip', - description: 'All of the IPs seen on your event.', - }, - { - name: 'user', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'All the user names seen on your event.', - default_field: false, - }, - ], - }, - { - name: 'rule', - title: 'Rule', - group: 2, - description: - 'Rule fields are used to capture the specifics of any observer or\nagent rules that generate alerts or other notable events.\n\nExamples of data sources that would populate the rule fields include: network\nadmission control platforms, network or host IDS/IPS, network firewalls, web\napplication firewalls, url filters, endpoint detection and response (EDR) systems,\netc.', - type: 'group', - fields: [ - { - name: 'author', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name, organization, or pseudonym of the author or authors who created\nthe rule used to generate this event.', - example: ['Star-Lord'], - default_field: false, - }, - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A categorization value keyword used by the entity using the rule\nfor detection of this event.', - example: 'Attempted Information Leak', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The description of the rule generating the event.', - example: 'Block requests to public DNS over HTTPS / TLS protocols', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of an agent, observer,\nor other entity using the rule for detection of this event.', - example: 101, - default_field: false, - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the license under which the rule used to generate this\nevent is made available.', - example: 'Apache 2.0', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the rule or signature generating the event.', - example: 'BLOCK_DNS_over_TLS', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL to additional information about the rule used to\ngenerate this event.\n\nThe URL can point to the vendor documentation about the rule. If that is\nnot available, it can also be a link to a more general page describing this\ntype of alert.', - example: 'https://en.wikipedia.org/wiki/DNS_over_TLS', - default_field: false, - }, - { - name: 'ruleset', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the ruleset, policy, group, or parent category in which\nthe rule used to generate this event is a member.', - example: 'Standard_Protocol_Filters', - default_field: false, - }, - { - name: 'uuid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of a set or group of\nagents, observers, or other entities using the rule for detection of this\nevent.', - example: 1100110011, - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The version / revision of the rule being used for analysis.', - example: 1.1, - default_field: false, - }, - ], - }, - { - name: 'server', - title: 'Server', - group: 2, - description: - 'A Server is defined as the responder in a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the server is the receiver of the initial SYN packet(s) of the\nTCP connection. For other protocols, the server is generally the responder in\nthe network transaction. Some systems actually use the term "responder" to refer\nthe server in TCP connections. The server fields describe details about the\nsystem acting as the server in the network event. Server fields are usually\npopulated in conjunction with client fields. Server fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event server addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the server to the client.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Server domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the server.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the server.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the server to the client.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the server.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered server domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'service', - title: 'Service', - group: 2, - description: - 'The service fields describe the service for or from which the data\nwas collected.\n\nThese fields help you find and correlate logs for a specific service and version.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this service (if one exists).\n\nThis id normally changes across restarts, but `service.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the running service. If the service is comprised\nof many nodes, the `service.id` should be the same for all nodes.\n\nThis id should uniquely identify the service. This makes it possible to correlate\nlogs and metrics for one specific service, no matter which particular node\nemitted the event.\n\nNote that if you need to see the events from one specific host of the service,\nyou should filter on that `host.name` or `host.id` instead.', - example: 'd37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the service data is collected from.\n\nThe name of the service is normally user given. This allows for distributed\nservices that run on multiple hosts to correlate the related instances based\non the name.\n\nIn the case of Elasticsearch the `service.name` could contain the cluster\nname. For Beats the `service.name` is by default a copy of the `service.type`\nfield if no name is specified.', - example: 'elasticsearch-metrics', - }, - { - name: 'node.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of a service node.\n\nThis allows for two nodes of the same service running on the same host to\nbe differentiated. Therefore, `service.node.name` should typically be unique\nacross nodes of a given service.\n\nIn the case of Elasticsearch, the `service.node.name` could contain the unique\nnode name within the Elasticsearch cluster. In cases where the service does not\nhave the concept of a node name, the host name or container name can be used\nto distinguish running instances that make up this service. If those do not\nprovide uniqueness (e.g. multiple instances of the service running on the\nsame host) - the node name can be manually set.', - example: 'instance-0000000016', - }, - { - name: 'state', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Current state of the service.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the service data is collected from.\n\nThe type can be used to group and correlate logs and metrics from one service\ntype.\n\nExample: If logs or metrics are collected from Elasticsearch, `service.type`\nwould be `elasticsearch`.', - example: 'elasticsearch', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Version of the service the data was collected from.\n\nThis allows to look at a data set only for a specific version of a service.', - example: '3.2.4', - }, - ], - }, - { - name: 'source', - title: 'Source', - group: 2, - description: - 'Source fields describe details about the source of a packet/event.\n\nSource fields are usually populated in conjunction with destination fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event source addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the source to the destination.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Source domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the source.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the source.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of source based NAT sessions (e.g. internal client\nto internet)\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions. (e.g. internal client\nto internet)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the source to the destination.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the source.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered source domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'threat', - title: 'Threat', - group: 2, - description: - 'Fields to classify events and alerts according to a threat taxonomy\nsuch as the Mitre ATT&CK framework.\n\nThese fields are for users to classify alerts from all of their sources (e.g.\nIDS, NGFW, etc.) within a common taxonomy. The threat.tactic.* are meant to\ncapture the high level category of the threat (e.g. "impact"). The threat.technique.*\nfields are meant to capture which kind of approach is used by this detected\nthreat, to accomplish the goal (e.g. "endpoint denial of service").', - type: 'group', - fields: [ - { - name: 'framework', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the threat framework used to further categorize and classify\nthe tactic and technique of the reported threat. Framework classification\ncan be provided by detecting systems, evaluated at ingest time, or retrospectively\ntagged to events.', - example: 'MITRE ATT&CK', - }, - { - name: 'tactic.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of tactic used by this threat. You can use the Mitre ATT&CK\nMatrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'TA0040', - }, - { - name: 'tactic.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the type of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'impact', - }, - { - name: 'tactic.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'https://attack.mitre.org/tactics/TA0040/', - }, - { - name: 'technique.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'T1499', - }, - { - name: 'technique.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'The name of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'endpoint denial of service', - }, - { - name: 'technique.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of technique used by this tactic. You can use\nthe Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'https://attack.mitre.org/techniques/T1499/', - }, - ], - }, - { - name: 'tls', - title: 'TLS', - group: 2, - description: - 'Fields related to a TLS connection. These fields focus on the TLS\nprotocol itself and intentionally avoids in-depth analysis of the related x.509\ncertificate files.', - type: 'group', - fields: [ - { - name: 'cipher', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the cipher used during the current connection.', - example: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', - default_field: false, - }, - { - name: 'client.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the client. This\nis usually mutually-exclusive of `client.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'client.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the client. This is usually mutually-exclusive of `client.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'client.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'client.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'client.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the client. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'client.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the issuer of the x.509 certificate\npresented by the client.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.ja3', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies clients based on how they perform an SSL/TLS\nhandshake.', - example: 'd4e5b18d6b55c71272893221c96ba240', - default_field: false, - }, - { - name: 'client.not_after', - level: 'extended', - type: 'date', - description: - 'Date/Time indicating when client certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.not_before', - level: 'extended', - type: 'date', - description: 'Date/Time indicating when client certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.server_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Also called an SNI, this tells the server which hostname to which\nthe client is attempting to connect. When this value is available, it should\nget copied to `destination.domain`.', - example: 'www.elastic.co', - default_field: false, - }, - { - name: 'client.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the x.509 certificate presented\nby the client.', - example: 'CN=myclient, OU=Documentation Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.supported_ciphers', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Array of ciphers offered by the client during the client hello.', - example: [ - 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', - 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', - '...', - ], - default_field: false, - }, - { - name: 'curve', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the curve used for the given cipher, when applicable.', - example: 'secp256r1', - default_field: false, - }, - { - name: 'established', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if the TLS negotiation was successful and\ntransitioned to an encrypted tunnel.', - default_field: false, - }, - { - name: 'next_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'String indicating the protocol being tunneled. Per the values in\nthe IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids),\nthis string should be lower case.', - example: 'http/1.1', - default_field: false, - }, - { - name: 'resumed', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if this TLS connection was resumed from\nan existing TLS negotiation.', - default_field: false, - }, - { - name: 'server.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the server. This\nis usually mutually-exclusive of `server.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'server.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the server. This is usually mutually-exclusive of `server.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'server.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'server.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'server.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the server. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'server.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the issuer of the x.509 certificate presented by the\nserver.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'server.ja3s', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies servers based on how they perform an SSL/TLS\nhandshake.', - example: '394441ab65754e2207b1e1b457b3641d', - default_field: false, - }, - { - name: 'server.not_after', - level: 'extended', - type: 'date', - description: - 'Timestamp indicating when server certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.not_before', - level: 'extended', - type: 'date', - description: 'Timestamp indicating when server certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the x.509 certificate presented by the server.', - example: 'CN=www.mydomain.com, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Numeric part of the version parsed from the original string.', - example: '1.2', - default_field: false, - }, - { - name: 'version_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Normalized lowercase protocol name parsed from original string.', - example: 'tls', - default_field: false, - }, - ], - }, - { - name: 'tracing', - title: 'Tracing', - group: 2, - description: - 'Distributed tracing makes it possible to analyze performance throughout\na microservice architecture all in one view. This is accomplished by tracing\nall of the requests - from the initial web request in the front-end service\n- to queries made through multiple back-end services.', - type: 'group', - fields: [ - { - name: 'trace.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the trace.\n\nA trace groups multiple events like transactions that belong together. For\nexample, a user request handled by multiple inter-connected services.', - example: '4bf92f3577b34da6a3ce929d0e0e4736', - }, - { - name: 'transaction.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the transaction.\n\nA transaction is the highest level of work measured within a service, such\nas a request to a server.', - example: '00f067aa0ba902b7', - }, - ], - }, - { - name: 'url', - title: 'URL', - group: 2, - description: - 'URL fields provide support for complete or partial URLs, and supports\nthe breaking down into scheme, domain, path, and so on.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Domain of the url, such as "www.elastic.co".\n\nIn some cases a URL may refer to an IP and/or port directly, without a domain\nname. In this case, the IP address would go to the `domain` field.', - example: 'www.elastic.co', - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The field contains the file extension from the original request\nurl.\n\nThe file extension is only set if it exists, as not every url has a file extension.\n\nThe leading period must not be included. For example, the value must be "png",\nnot ".png".', - example: 'png', - }, - { - name: 'fragment', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Portion of the url after the `#`, such as "top".\n\nThe `#` is not part of the fragment.', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'If full URLs are important to your use case, they should be stored\nin `url.full`, whether this field is reconstructed or present in the event\nsource.', - example: 'https://www.elastic.co:443/search?q=elasticsearch#top', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Unmodified original url as seen in the event source.\n\nNote that in network monitoring, the observed URL may be a full URL, whereas\nin access logs, the URL is often just represented as a path.\n\nThis field is meant to represent the URL as it was observed, complete or not.', - example: - 'https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch', - }, - { - name: 'password', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Password of the request.', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path of the request, such as "/search".', - }, - { - name: 'port', - level: 'extended', - type: 'long', - format: 'string', - description: 'Port of the request, such as 443.', - example: 443, - }, - { - name: 'query', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The query field describes the query string of the request, such\nas "q=elasticsearch".\n\nThe `?` is excluded from the query string. If a URL contains no `?`, there\nis no query field. If there is a `?` but no query, the query field exists\nwith an empty string. The `exists` query can be used to differentiate between\nthe two cases.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered url domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'scheme', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Scheme of the request, such as "https".\n\nNote: The `:` is not part of the scheme.', - example: 'https', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'username', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Username of the request.', - }, - ], - }, - { - name: 'user', - title: 'User', - group: 2, - description: - 'The user fields describe information about the user that is relevant\nto the event.\n\nFields can have one entry or multiple entries. If a user has more than one id,\nprovide an array that includes all of them.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'user_agent', - title: 'User agent', - group: 2, - description: - 'The user_agent fields normally come from a browser request.\n\nThey often show up in web service logs coming from the parsed user agent string.', - type: 'group', - fields: [ - { - name: 'device.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the device.', - example: 'iPhone', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the user agent.', - example: 'Safari', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Unparsed user_agent string.', - example: - 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15\n(KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the user agent.', - example: 12, - }, - ], - }, - { - name: 'vlan', - title: 'VLAN', - group: 2, - description: - 'The VLAN fields are used to identify 802.1q tag(s) of a packet,\nas well as ingress and egress VLAN associations of an observer in relation to\na specific packet or connection.\n\nNetwork.vlan fields are used to record a single VLAN tag, or the outer tag in\nthe case of q-in-q encapsulations, for a packet or connection as observed, typically\nprovided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic.\n\nNetwork.inner VLAN fields are used to report inner q-in-q 802.1q tags (multiple\n802.1q encapsulations) as observed, typically provided by a network sensor (e.g.\nZeek, Wireshark) passively reporting on traffic. Network.inner VLAN fields should\nonly be used in addition to network.vlan fields to indicate q-in-q tagging.\n\nObserver.ingress and observer.egress VLAN values are used to record observer\nspecific information when observer events contain discrete ingress and egress\nVLAN information, typically provided by firewalls, routers, or load balancers.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'vulnerability', - title: 'Vulnerability', - group: 2, - description: - 'The vulnerability fields describe information about a vulnerability\nthat is relevant to an event.', - type: 'group', - fields: [ - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of system or architecture that the vulnerability affects.\nThese may be platform-specific (for example, Debian or SUSE) or general (for\nexample, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys\nvulnerability categories])\n\nThis field must be an array.', - example: '["Firewall"]', - default_field: false, - }, - { - name: 'classification', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The classification of the vulnerability scoring system. For example\n(https://www.first.org/cvss/)', - example: 'CVSS', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'The description of the vulnerability that provides additional context\nof the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common\nVulnerabilities and Exposure CVE description])', - example: 'In macOS before 2.12.6, there is a vulnerability in the RPC...', - default_field: false, - }, - { - name: 'enumeration', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of identifier used for this vulnerability. For example\n(https://cve.mitre.org/about/)', - example: 'CVE', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The identification (ID) is the number portion of a vulnerability\nentry. It includes a unique identification number for the vulnerability. For\nexample (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities\nand Exposure CVE ID]', - example: 'CVE-2019-00001', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A resource that provides additional information, context, and mitigations\nfor the identified vulnerability.', - example: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111', - default_field: false, - }, - { - name: 'report_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The report or scan identification number.', - example: 20191018.0001, - default_field: false, - }, - { - name: 'scanner.vendor', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the vulnerability scanner vendor.', - example: 'Tenable', - default_field: false, - }, - { - name: 'score.base', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nBase scores cover an assessment for exploitability metrics (attack vector,\ncomplexity, privileges, and user interaction), impact metrics (confidentiality,\nintegrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.environmental', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nEnvironmental scores cover an assessment for any modified Base metrics, confidentiality,\nintegrity, and availability requirements. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.temporal', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nTemporal scores cover an assessment for code maturity, remediation level,\nand confidence. For example (https://www.first.org/cvss/specification-document)', - default_field: false, - }, - { - name: 'score.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The National Vulnerability Database (NVD) provides qualitative\nseverity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score\nranges in addition to the severity ratings for CVSS v3.0 as they are defined\nin the CVSS v3.0 specification.\n\nCVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit\norganization, whose mission is to help computer security incident response\nteams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 2, - default_field: false, - }, - { - name: 'severity', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The severity of the vulnerability can help with metrics and internal\nprioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 'Critical', - default_field: false, - }, - ], - }, - ], - }, - { - key: 'beat', - anchor: 'beat-common', - title: 'Beat', - description: 'Contains common beat fields available in all event types.\n', - fields: [ - { - name: 'agent.hostname', - type: 'keyword', - description: 'Hostname of the agent.', - }, - { - name: 'beat.timezone', - type: 'alias', - path: 'event.timezone', - migration: true, - }, - { - name: 'fields', - type: 'object', - object_type: 'keyword', - description: 'Contains user configurable fields.\n', - }, - { - name: 'beat.name', - type: 'alias', - path: 'host.name', - migration: true, - }, - { - name: 'beat.hostname', - type: 'alias', - path: 'agent.hostname', - migration: true, - }, - { - name: 'timeseries.instance', - type: 'keyword', - description: 'Time series instance id', - }, - ], - }, - { - key: 'cloud', - title: 'Cloud provider metadata', - description: 'Metadata from cloud providers added by the add_cloud_metadata processor.\n', - fields: [ - { - name: 'cloud.project.id', - example: 'project-x', - description: 'Name of the project in Google Cloud.\n', - }, - { - name: 'cloud.image.id', - example: 'ami-abcd1234', - description: 'Image ID for the cloud instance.\n', - }, - { - name: 'meta.cloud.provider', - type: 'alias', - path: 'cloud.provider', - migration: true, - }, - { - name: 'meta.cloud.instance_id', - type: 'alias', - path: 'cloud.instance.id', - migration: true, - }, - { - name: 'meta.cloud.instance_name', - type: 'alias', - path: 'cloud.instance.name', - migration: true, - }, - { - name: 'meta.cloud.machine_type', - type: 'alias', - path: 'cloud.machine.type', - migration: true, - }, - { - name: 'meta.cloud.availability_zone', - type: 'alias', - path: 'cloud.availability_zone', - migration: true, - }, - { - name: 'meta.cloud.project_id', - type: 'alias', - path: 'cloud.project.id', - migration: true, - }, - { - name: 'meta.cloud.region', - type: 'alias', - path: 'cloud.region', - migration: true, - }, - ], - }, - { - key: 'docker', - title: 'Docker', - description: 'Docker stats collected from Docker.\n', - short_config: false, - anchor: 'docker-processor', - fields: [ - { - name: 'docker', - type: 'group', - fields: [ - { - name: 'container.id', - type: 'alias', - path: 'container.id', - migration: true, - }, - { - name: 'container.image', - type: 'alias', - path: 'container.image.name', - migration: true, - }, - { - name: 'container.name', - type: 'alias', - path: 'container.name', - migration: true, - }, - { - name: 'container.labels', - type: 'object', - object_type: 'keyword', - description: 'Image labels.\n', - }, - ], - }, - ], - }, - { - key: 'host', - title: 'Host', - description: 'Info collected for the host machine.\n', - anchor: 'host-processor', - fields: [ - { - name: 'host', - type: 'group', - fields: [ - { - name: 'containerized', - type: 'boolean', - description: 'If the host is a container.\n', - }, - { - name: 'os.build', - type: 'keyword', - example: '18D109', - description: 'OS build information.\n', - }, - { - name: 'os.codename', - type: 'keyword', - example: 'stretch', - description: 'OS codename, if any.\n', - }, - ], - }, - ], - }, - { - key: 'kubernetes', - title: 'Kubernetes', - description: 'Kubernetes metadata added by the kubernetes processor\n', - short_config: false, - anchor: 'kubernetes-processor', - fields: [ - { - name: 'kubernetes', - type: 'group', - fields: [ - { - name: 'pod.name', - type: 'keyword', - description: 'Kubernetes pod name\n', - }, - { - name: 'pod.uid', - type: 'keyword', - description: 'Kubernetes Pod UID\n', - }, - { - name: 'namespace', - type: 'keyword', - description: 'Kubernetes namespace\n', - }, - { - name: 'node.name', - type: 'keyword', - description: 'Kubernetes node name\n', - }, - { - name: 'labels.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Kubernetes labels map\n', - }, - { - name: 'annotations.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Kubernetes annotations map\n', - }, - { - name: 'replicaset.name', - type: 'keyword', - description: 'Kubernetes replicaset name\n', - }, - { - name: 'deployment.name', - type: 'keyword', - description: 'Kubernetes deployment name\n', - }, - { - name: 'statefulset.name', - type: 'keyword', - description: 'Kubernetes statefulset name\n', - }, - { - name: 'container.name', - type: 'keyword', - description: 'Kubernetes container name\n', - }, - { - name: 'container.image', - type: 'keyword', - description: 'Kubernetes container image\n', - }, - ], - }, - ], - }, - { - key: 'process', - title: 'Process', - description: 'Process metadata fields\n', - fields: [ - { - name: 'process', - type: 'group', - fields: [ - { - name: 'exe', - type: 'alias', - path: 'process.executable', - migration: true, - }, - ], - }, - ], - }, - { - key: 'jolokia-autodiscover', - title: 'Jolokia Discovery autodiscover provider', - description: 'Metadata from Jolokia Discovery added by the jolokia provider.\n', - fields: [ - { - name: 'jolokia.agent.version', - type: 'keyword', - description: 'Version number of jolokia agent.\n', - }, - { - name: 'jolokia.agent.id', - type: 'keyword', - description: - 'Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type.\n', - }, - { - name: 'jolokia.server.product', - type: 'keyword', - description: 'The container product if detected.\n', - }, - { - name: 'jolokia.server.version', - type: 'keyword', - description: "The container's version (if detected).\n", - }, - { - name: 'jolokia.server.vendor', - type: 'keyword', - description: 'The vendor of the container the agent is running in.\n', - }, - { - name: 'jolokia.url', - type: 'keyword', - description: 'The URL how this agent can be contacted.\n', - }, - { - name: 'jolokia.secured', - type: 'boolean', - description: 'Whether the agent was configured for authentication or not.\n', - }, - ], - }, - { - key: 'common', - title: 'Common', - description: 'Contains common fields available in all event types.\n', - fields: [ - { - name: 'file', - type: 'group', - description: 'File attributes.', - fields: [ - { - name: 'setuid', - type: 'boolean', - example: true, - description: 'Set if the file has the `setuid` bit set. Omitted otherwise.', - }, - { - name: 'setgid', - type: 'boolean', - example: true, - description: 'Set if the file has the `setgid` bit set. Omitted otherwise.', - }, - { - name: 'origin', - type: 'keyword', - description: - 'An array of strings describing a possible external origin for this file. For example, the URL it was downloaded from. Only supported in macOS, via the kMDItemWhereFroms attribute. Omitted if origin information is not available.\n', - multi_fields: [ - { - name: 'raw', - type: 'keyword', - description: - 'This is a non-analyzed field that is useful for aggregations on the origin data.\n', - }, - ], - }, - { - name: 'selinux', - type: 'group', - description: 'The SELinux identity of the file.', - fields: [ - { - name: 'user', - type: 'keyword', - description: 'The owner of the object.', - }, - { - name: 'role', - type: 'keyword', - description: "The object's SELinux role.", - }, - { - name: 'domain', - type: 'keyword', - description: "The object's SELinux domain or type.", - }, - { - name: 'level', - type: 'keyword', - example: 's0', - description: "The object's SELinux level.", - }, - ], - }, - ], - }, - { - name: 'user', - type: 'group', - description: 'User information.', - fields: [ - { - name: 'audit', - type: 'group', - description: 'Audit user information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Audit user ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Audit user name.', - }, - ], - }, - { - name: 'effective', - type: 'group', - description: 'Effective user information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Effective user ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Effective user name.', - }, - { - name: 'group', - type: 'group', - description: 'Effective group information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Effective group ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Effective group name.', - }, - ], - }, - ], - }, - { - name: 'filesystem', - type: 'group', - description: 'Filesystem user information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Filesystem user ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Filesystem user name.', - }, - { - name: 'group', - type: 'group', - description: 'Filesystem group information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Filesystem group ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Filesystem group name.', - }, - ], - }, - ], - }, - { - name: 'saved', - type: 'group', - description: 'Saved user information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Saved user ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Saved user name.', - }, - { - name: 'group', - type: 'group', - description: 'Saved group information.', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Saved group ID.', - }, - { - name: 'name', - type: 'keyword', - description: 'Saved group name.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'auditd', - title: 'Auditd', - description: 'These are the fields generated by the auditd module.', - fields: [ - { - name: 'user', - type: 'group', - fields: [ - { - name: 'auid', - type: 'alias', - path: 'user.audit.id', - migration: true, - }, - { - name: 'uid', - type: 'alias', - path: 'user.id', - migration: true, - }, - { - name: 'euid', - type: 'alias', - path: 'user.effective.id', - migration: true, - }, - { - name: 'fsuid', - type: 'alias', - path: 'user.filesystem.id', - migration: true, - }, - { - name: 'suid', - type: 'alias', - path: 'user.saved.id', - migration: true, - }, - { - name: 'gid', - type: 'alias', - path: 'user.group.id', - migration: true, - }, - { - name: 'egid', - type: 'alias', - path: 'user.effective.group.id', - migration: true, - }, - { - name: 'sgid', - type: 'alias', - path: 'user.saved.group.id', - migration: true, - }, - { - name: 'fsgid', - type: 'alias', - path: 'user.filesystem.group.id', - migration: true, - }, - { - name: 'name_map', - type: 'group', - description: - 'If `resolve_ids` is set to true in the configuration then `name_map` will contain a mapping of uid field names to the resolved name (e.g. auid -> root).\n', - fields: [ - { - name: 'auid', - type: 'alias', - path: 'user.audit.name', - migration: true, - }, - { - name: 'uid', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'euid', - type: 'alias', - path: 'user.effective.name', - migration: true, - }, - { - name: 'fsuid', - type: 'alias', - path: 'user.filesystem.name', - migration: true, - }, - { - name: 'suid', - type: 'alias', - path: 'user.saved.name', - migration: true, - }, - { - name: 'gid', - type: 'alias', - path: 'user.group.name', - migration: true, - }, - { - name: 'egid', - type: 'alias', - path: 'user.effective.group.name', - migration: true, - }, - { - name: 'sgid', - type: 'alias', - path: 'user.saved.group.name', - migration: true, - }, - { - name: 'fsgid', - type: 'alias', - path: 'user.filesystem.group.name', - migration: true, - }, - ], - }, - { - name: 'selinux', - type: 'group', - description: 'The SELinux identity of the actor.', - fields: [ - { - name: 'user', - type: 'keyword', - description: 'account submitted for authentication', - }, - { - name: 'role', - type: 'keyword', - description: "user's SELinux role", - }, - { - name: 'domain', - type: 'keyword', - description: "The actor's SELinux domain or type.", - }, - { - name: 'level', - type: 'keyword', - example: 's0', - description: "The actor's SELinux level.", - }, - { - name: 'category', - type: 'keyword', - description: "The actor's SELinux category or compartments.", - }, - ], - }, - ], - }, - { - name: 'process', - type: 'group', - description: 'Process attributes.', - fields: [ - { - name: 'cwd', - type: 'alias', - path: 'process.working_directory', - migration: true, - description: 'The current working directory.', - }, - ], - }, - { - name: 'source', - type: 'group', - description: 'Source that triggered the event.', - fields: [ - { - name: 'path', - type: 'keyword', - description: 'This is the path associated with a unix socket.', - }, - ], - }, - { - name: 'destination', - type: 'group', - description: 'Destination address that triggered the event.', - fields: [ - { - name: 'path', - type: 'keyword', - description: 'This is the path associated with a unix socket.', - }, - ], - }, - { - name: 'auditd', - type: 'group', - fields: [ - { - name: 'message_type', - type: 'keyword', - example: 'syscall', - description: 'The audit message type (e.g. syscall or apparmor_denied).\n', - }, - { - name: 'sequence', - type: 'long', - description: - 'The sequence number of the event as assigned by the kernel. Sequence numbers are stored as a uint32 in the kernel and can rollover.\n', - }, - { - name: 'session', - type: 'keyword', - description: - 'The session ID assigned to a login. All events related to a login session will have the same value.\n', - }, - { - name: 'result', - type: 'keyword', - example: 'success or fail', - description: 'The result of the audited operation (success/fail).', - }, - { - name: 'summary', - type: 'group', - fields: [ - { - name: 'actor', - type: 'group', - description: 'The actor is the user that triggered the audit event.', - fields: [ - { - name: 'primary', - type: 'keyword', - description: - "The primary identity of the actor. This is the actor's original login ID. It will not change even if the user changes to another account.\n", - }, - { - name: 'secondary', - type: 'keyword', - description: - 'The secondary identity of the actor. This is typically\nthe same as the primary, except for when the user has used `su`.', - }, - ], - }, - { - name: 'object', - type: 'group', - description: 'This is the thing or object being acted upon in the event.\n', - fields: [ - { - name: 'type', - type: 'keyword', - description: - 'A description of the what the "thing" is (e.g. file, socket, user-session).\n', - }, - { - name: 'primary', - type: 'keyword', - description: '', - }, - { - name: 'secondary', - type: 'keyword', - description: '', - }, - ], - }, - { - name: 'how', - type: 'keyword', - description: - 'This describes how the action was performed. Usually this is the exe or command that was being executed that triggered the event.\n', - }, - ], - }, - { - name: 'paths', - type: 'group', - description: 'List of paths associated with the event.', - fields: [ - { - name: 'inode', - type: 'keyword', - description: 'inode number', - }, - { - name: 'dev', - type: 'keyword', - description: 'device name as found in /dev', - }, - { - name: 'obj_user', - type: 'keyword', - description: '', - }, - { - name: 'obj_role', - type: 'keyword', - description: '', - }, - { - name: 'obj_domain', - type: 'keyword', - description: '', - }, - { - name: 'obj_level', - type: 'keyword', - description: '', - }, - { - name: 'objtype', - type: 'keyword', - description: '', - }, - { - name: 'ouid', - type: 'keyword', - description: 'file owner user ID', - }, - { - name: 'rdev', - type: 'keyword', - description: 'the device identifier (special files only)', - }, - { - name: 'nametype', - type: 'keyword', - description: 'kind of file operation being referenced', - }, - { - name: 'ogid', - type: 'keyword', - description: 'file owner group ID', - }, - { - name: 'item', - type: 'keyword', - description: 'which item is being recorded', - }, - { - name: 'mode', - type: 'keyword', - description: 'mode flags on a file', - }, - { - name: 'name', - type: 'keyword', - description: 'file name in avcs', - }, - ], - }, - { - name: 'data', - type: 'group', - description: 'The data from the audit messages.', - fields: [ - { - name: 'action', - type: 'keyword', - description: 'netfilter packet disposition', - }, - { - name: 'minor', - type: 'keyword', - description: 'device minor number', - }, - { - name: 'acct', - type: 'keyword', - description: "a user's account name", - }, - { - name: 'addr', - type: 'keyword', - description: 'the remote address that the user is connecting from', - }, - { - name: 'cipher', - type: 'keyword', - description: 'name of crypto cipher selected', - }, - { - name: 'id', - type: 'keyword', - description: 'during account changes', - }, - { - name: 'entries', - type: 'keyword', - description: 'number of entries in the netfilter table', - }, - { - name: 'kind', - type: 'keyword', - description: 'server or client in crypto operation', - }, - { - name: 'ksize', - type: 'keyword', - description: 'key size for crypto operation', - }, - { - name: 'spid', - type: 'keyword', - description: 'sent process ID', - }, - { - name: 'arch', - type: 'keyword', - description: 'the elf architecture flags', - }, - { - name: 'argc', - type: 'keyword', - description: 'the number of arguments to an execve syscall', - }, - { - name: 'major', - type: 'keyword', - description: 'device major number', - }, - { - name: 'unit', - type: 'keyword', - description: 'systemd unit', - }, - { - name: 'table', - type: 'keyword', - description: 'netfilter table name', - }, - { - name: 'terminal', - type: 'keyword', - description: 'terminal name the user is running programs on', - }, - { - name: 'grantors', - type: 'keyword', - description: 'pam modules approving the action', - }, - { - name: 'direction', - type: 'keyword', - description: 'direction of crypto operation', - }, - { - name: 'op', - type: 'keyword', - description: 'the operation being performed that is audited', - }, - { - name: 'tty', - type: 'keyword', - description: 'tty udevice the user is running programs on', - }, - { - name: 'syscall', - type: 'keyword', - description: 'syscall number in effect when the event occurred', - }, - { - name: 'data', - type: 'keyword', - description: 'TTY text', - }, - { - name: 'family', - type: 'keyword', - description: 'netfilter protocol', - }, - { - name: 'mac', - type: 'keyword', - description: 'crypto MAC algorithm selected', - }, - { - name: 'pfs', - type: 'keyword', - description: 'perfect forward secrecy method', - }, - { - name: 'items', - type: 'keyword', - description: 'the number of path records in the event', - }, - { - name: 'a0', - type: 'keyword', - description: '', - }, - { - name: 'a1', - type: 'keyword', - description: '', - }, - { - name: 'a2', - type: 'keyword', - description: '', - }, - { - name: 'a3', - type: 'keyword', - description: '', - }, - { - name: 'hostname', - type: 'keyword', - description: 'the hostname that the user is connecting from', - }, - { - name: 'lport', - type: 'keyword', - description: 'local network port', - }, - { - name: 'rport', - type: 'keyword', - description: 'remote port number', - }, - { - name: 'exit', - type: 'keyword', - description: 'syscall exit code', - }, - { - name: 'fp', - type: 'keyword', - description: 'crypto key finger print', - }, - { - name: 'laddr', - type: 'keyword', - description: 'local network address', - }, - { - name: 'sport', - type: 'keyword', - description: 'local port number', - }, - { - name: 'capability', - type: 'keyword', - description: 'posix capabilities', - }, - { - name: 'nargs', - type: 'keyword', - description: 'the number of arguments to a socket call', - }, - { - name: 'new-enabled', - type: 'keyword', - description: 'new TTY audit enabled setting', - }, - { - name: 'audit_backlog_limit', - type: 'keyword', - description: "audit system's backlog queue size", - }, - { - name: 'dir', - type: 'keyword', - description: 'directory name', - }, - { - name: 'cap_pe', - type: 'keyword', - description: 'process effective capability map', - }, - { - name: 'model', - type: 'keyword', - description: 'security model being used for virt', - }, - { - name: 'new_pp', - type: 'keyword', - description: 'new process permitted capability map', - }, - { - name: 'old-enabled', - type: 'keyword', - description: 'present TTY audit enabled setting', - }, - { - name: 'oauid', - type: 'keyword', - description: "object's login user ID", - }, - { - name: 'old', - type: 'keyword', - description: 'old value', - }, - { - name: 'banners', - type: 'keyword', - description: 'banners used on printed page', - }, - { - name: 'feature', - type: 'keyword', - description: 'kernel feature being changed', - }, - { - name: 'vm-ctx', - type: 'keyword', - description: "the vm's context string", - }, - { - name: 'opid', - type: 'keyword', - description: "object's process ID", - }, - { - name: 'seperms', - type: 'keyword', - description: 'SELinux permissions being used', - }, - { - name: 'seresult', - type: 'keyword', - description: 'SELinux AVC decision granted/denied', - }, - { - name: 'new-rng', - type: 'keyword', - description: 'device name of rng being added from a vm', - }, - { - name: 'old-net', - type: 'keyword', - description: 'present MAC address assigned to vm', - }, - { - name: 'sigev_signo', - type: 'keyword', - description: 'signal number', - }, - { - name: 'ino', - type: 'keyword', - description: 'inode number', - }, - { - name: 'old_enforcing', - type: 'keyword', - description: 'old MAC enforcement status', - }, - { - name: 'old-vcpu', - type: 'keyword', - description: 'present number of CPU cores', - }, - { - name: 'range', - type: 'keyword', - description: "user's SE Linux range", - }, - { - name: 'res', - type: 'keyword', - description: 'result of the audited operation(success/fail)', - }, - { - name: 'added', - type: 'keyword', - description: 'number of new files detected', - }, - { - name: 'fam', - type: 'keyword', - description: 'socket address family', - }, - { - name: 'nlnk-pid', - type: 'keyword', - description: 'pid of netlink packet sender', - }, - { - name: 'subj', - type: 'keyword', - description: "lspp subject's context string", - }, - { - name: 'a[0-3]', - type: 'keyword', - description: 'the arguments to a syscall', - }, - { - name: 'cgroup', - type: 'keyword', - description: 'path to cgroup in sysfs', - }, - { - name: 'kernel', - type: 'keyword', - description: "kernel's version number", - }, - { - name: 'ocomm', - type: 'keyword', - description: "object's command line name", - }, - { - name: 'new-net', - type: 'keyword', - description: 'MAC address being assigned to vm', - }, - { - name: 'permissive', - type: 'keyword', - description: 'SELinux is in permissive mode', - }, - { - name: 'class', - type: 'keyword', - description: 'resource class assigned to vm', - }, - { - name: 'compat', - type: 'keyword', - description: 'is_compat_task result', - }, - { - name: 'fi', - type: 'keyword', - description: 'file assigned inherited capability map', - }, - { - name: 'changed', - type: 'keyword', - description: 'number of changed files', - }, - { - name: 'msg', - type: 'keyword', - description: 'the payload of the audit record', - }, - { - name: 'dport', - type: 'keyword', - description: 'remote port number', - }, - { - name: 'new-seuser', - type: 'keyword', - description: 'new SELinux user', - }, - { - name: 'invalid_context', - type: 'keyword', - description: 'SELinux context', - }, - { - name: 'dmac', - type: 'keyword', - description: 'remote MAC address', - }, - { - name: 'ipx-net', - type: 'keyword', - description: 'IPX network number', - }, - { - name: 'iuid', - type: 'keyword', - description: "ipc object's user ID", - }, - { - name: 'macproto', - type: 'keyword', - description: 'ethernet packet type ID field', - }, - { - name: 'obj', - type: 'keyword', - description: 'lspp object context string', - }, - { - name: 'ipid', - type: 'keyword', - description: 'IP datagram fragment identifier', - }, - { - name: 'new-fs', - type: 'keyword', - description: 'file system being added to vm', - }, - { - name: 'vm-pid', - type: 'keyword', - description: "vm's process ID", - }, - { - name: 'cap_pi', - type: 'keyword', - description: 'process inherited capability map', - }, - { - name: 'old-auid', - type: 'keyword', - description: 'previous auid value', - }, - { - name: 'oses', - type: 'keyword', - description: "object's session ID", - }, - { - name: 'fd', - type: 'keyword', - description: 'file descriptor number', - }, - { - name: 'igid', - type: 'keyword', - description: "ipc object's group ID", - }, - { - name: 'new-disk', - type: 'keyword', - description: 'disk being added to vm', - }, - { - name: 'parent', - type: 'keyword', - description: 'the inode number of the parent file', - }, - { - name: 'len', - type: 'keyword', - description: 'length', - }, - { - name: 'oflag', - type: 'keyword', - description: 'open syscall flags', - }, - { - name: 'uuid', - type: 'keyword', - description: 'a UUID', - }, - { - name: 'code', - type: 'keyword', - description: 'seccomp action code', - }, - { - name: 'nlnk-grp', - type: 'keyword', - description: 'netlink group number', - }, - { - name: 'cap_fp', - type: 'keyword', - description: 'file permitted capability map', - }, - { - name: 'new-mem', - type: 'keyword', - description: 'new amount of memory in KB', - }, - { - name: 'seperm', - type: 'keyword', - description: 'SELinux permission being decided on', - }, - { - name: 'enforcing', - type: 'keyword', - description: 'new MAC enforcement status', - }, - { - name: 'new-chardev', - type: 'keyword', - description: 'new character device being assigned to vm', - }, - { - name: 'old-rng', - type: 'keyword', - description: 'device name of rng being removed from a vm', - }, - { - name: 'outif', - type: 'keyword', - description: 'out interface number', - }, - { - name: 'cmd', - type: 'keyword', - description: 'command being executed', - }, - { - name: 'hook', - type: 'keyword', - description: 'netfilter hook that packet came from', - }, - { - name: 'new-level', - type: 'keyword', - description: 'new run level', - }, - { - name: 'sauid', - type: 'keyword', - description: 'sent login user ID', - }, - { - name: 'sig', - type: 'keyword', - description: 'signal number', - }, - { - name: 'audit_backlog_wait_time', - type: 'keyword', - description: "audit system's backlog wait time", - }, - { - name: 'printer', - type: 'keyword', - description: 'printer name', - }, - { - name: 'old-mem', - type: 'keyword', - description: 'present amount of memory in KB', - }, - { - name: 'perm', - type: 'keyword', - description: 'the file permission being used', - }, - { - name: 'old_pi', - type: 'keyword', - description: 'old process inherited capability map', - }, - { - name: 'state', - type: 'keyword', - description: 'audit daemon configuration resulting state', - }, - { - name: 'format', - type: 'keyword', - description: "audit log's format", - }, - { - name: 'new_gid', - type: 'keyword', - description: 'new group ID being assigned', - }, - { - name: 'tcontext', - type: 'keyword', - description: "the target's or object's context string", - }, - { - name: 'maj', - type: 'keyword', - description: 'device major number', - }, - { - name: 'watch', - type: 'keyword', - description: 'file name in a watch record', - }, - { - name: 'device', - type: 'keyword', - description: 'device name', - }, - { - name: 'grp', - type: 'keyword', - description: 'group name', - }, - { - name: 'bool', - type: 'keyword', - description: 'name of SELinux boolean', - }, - { - name: 'icmp_type', - type: 'keyword', - description: 'type of icmp message', - }, - { - name: 'new_lock', - type: 'keyword', - description: 'new value of feature lock', - }, - { - name: 'old_prom', - type: 'keyword', - description: 'network promiscuity flag', - }, - { - name: 'acl', - type: 'keyword', - description: 'access mode of resource assigned to vm', - }, - { - name: 'ip', - type: 'keyword', - description: 'network address of a printer', - }, - { - name: 'new_pi', - type: 'keyword', - description: 'new process inherited capability map', - }, - { - name: 'default-context', - type: 'keyword', - description: 'default MAC context', - }, - { - name: 'inode_gid', - type: 'keyword', - description: "group ID of the inode's owner", - }, - { - name: 'new-log_passwd', - type: 'keyword', - description: 'new value for TTY password logging', - }, - { - name: 'new_pe', - type: 'keyword', - description: 'new process effective capability map', - }, - { - name: 'selected-context', - type: 'keyword', - description: 'new MAC context assigned to session', - }, - { - name: 'cap_fver', - type: 'keyword', - description: 'file system capabilities version number', - }, - { - name: 'file', - type: 'keyword', - description: 'file name', - }, - { - name: 'net', - type: 'keyword', - description: 'network MAC address', - }, - { - name: 'virt', - type: 'keyword', - description: 'kind of virtualization being referenced', - }, - { - name: 'cap_pp', - type: 'keyword', - description: 'process permitted capability map', - }, - { - name: 'old-range', - type: 'keyword', - description: 'present SELinux range', - }, - { - name: 'resrc', - type: 'keyword', - description: 'resource being assigned', - }, - { - name: 'new-range', - type: 'keyword', - description: 'new SELinux range', - }, - { - name: 'obj_gid', - type: 'keyword', - description: 'group ID of object', - }, - { - name: 'proto', - type: 'keyword', - description: 'network protocol', - }, - { - name: 'old-disk', - type: 'keyword', - description: 'disk being removed from vm', - }, - { - name: 'audit_failure', - type: 'keyword', - description: "audit system's failure mode", - }, - { - name: 'inif', - type: 'keyword', - description: 'in interface number', - }, - { - name: 'vm', - type: 'keyword', - description: 'virtual machine name', - }, - { - name: 'flags', - type: 'keyword', - description: 'mmap syscall flags', - }, - { - name: 'nlnk-fam', - type: 'keyword', - description: 'netlink protocol number', - }, - { - name: 'old-fs', - type: 'keyword', - description: 'file system being removed from vm', - }, - { - name: 'old-ses', - type: 'keyword', - description: 'previous ses value', - }, - { - name: 'seqno', - type: 'keyword', - description: 'sequence number', - }, - { - name: 'fver', - type: 'keyword', - description: 'file system capabilities version number', - }, - { - name: 'qbytes', - type: 'keyword', - description: 'ipc objects quantity of bytes', - }, - { - name: 'seuser', - type: 'keyword', - description: "user's SE Linux user acct", - }, - { - name: 'cap_fe', - type: 'keyword', - description: 'file assigned effective capability map', - }, - { - name: 'new-vcpu', - type: 'keyword', - description: 'new number of CPU cores', - }, - { - name: 'old-level', - type: 'keyword', - description: 'old run level', - }, - { - name: 'old_pp', - type: 'keyword', - description: 'old process permitted capability map', - }, - { - name: 'daddr', - type: 'keyword', - description: 'remote IP address', - }, - { - name: 'old-role', - type: 'keyword', - description: 'present SELinux role', - }, - { - name: 'ioctlcmd', - type: 'keyword', - description: 'The request argument to the ioctl syscall', - }, - { - name: 'smac', - type: 'keyword', - description: 'local MAC address', - }, - { - name: 'apparmor', - type: 'keyword', - description: 'apparmor event information', - }, - { - name: 'fe', - type: 'keyword', - description: 'file assigned effective capability map', - }, - { - name: 'perm_mask', - type: 'keyword', - description: 'file permission mask that triggered a watch event', - }, - { - name: 'ses', - type: 'keyword', - description: 'login session ID', - }, - { - name: 'cap_fi', - type: 'keyword', - description: 'file inherited capability map', - }, - { - name: 'obj_uid', - type: 'keyword', - description: 'user ID of object', - }, - { - name: 'reason', - type: 'keyword', - description: 'text string denoting a reason for the action', - }, - { - name: 'list', - type: 'keyword', - description: "the audit system's filter list number", - }, - { - name: 'old_lock', - type: 'keyword', - description: 'present value of feature lock', - }, - { - name: 'bus', - type: 'keyword', - description: 'name of subsystem bus a vm resource belongs to', - }, - { - name: 'old_pe', - type: 'keyword', - description: 'old process effective capability map', - }, - { - name: 'new-role', - type: 'keyword', - description: 'new SELinux role', - }, - { - name: 'prom', - type: 'keyword', - description: 'network promiscuity flag', - }, - { - name: 'uri', - type: 'keyword', - description: 'URI pointing to a printer', - }, - { - name: 'audit_enabled', - type: 'keyword', - description: "audit systems's enable/disable status", - }, - { - name: 'old-log_passwd', - type: 'keyword', - description: 'present value for TTY password logging', - }, - { - name: 'old-seuser', - type: 'keyword', - description: 'present SELinux user', - }, - { - name: 'per', - type: 'keyword', - description: 'linux personality', - }, - { - name: 'scontext', - type: 'keyword', - description: "the subject's context string", - }, - { - name: 'tclass', - type: 'keyword', - description: "target's object classification", - }, - { - name: 'ver', - type: 'keyword', - description: "audit daemon's version number", - }, - { - name: 'new', - type: 'keyword', - description: 'value being set in feature', - }, - { - name: 'val', - type: 'keyword', - description: 'generic value associated with the operation', - }, - { - name: 'img-ctx', - type: 'keyword', - description: "the vm's disk image context string", - }, - { - name: 'old-chardev', - type: 'keyword', - description: 'present character device assigned to vm', - }, - { - name: 'old_val', - type: 'keyword', - description: 'current value of SELinux boolean', - }, - { - name: 'success', - type: 'keyword', - description: 'whether the syscall was successful or not', - }, - { - name: 'inode_uid', - type: 'keyword', - description: "user ID of the inode's owner", - }, - { - name: 'removed', - type: 'keyword', - description: 'number of deleted files', - }, - { - name: 'socket', - type: 'group', - fields: [ - { - name: 'port', - type: 'keyword', - description: 'The port number.', - }, - { - name: 'saddr', - type: 'keyword', - description: 'The raw socket address structure.', - }, - { - name: 'addr', - type: 'keyword', - description: 'The remote address.', - }, - { - name: 'family', - type: 'keyword', - example: 'unix', - description: 'The socket family (unix, ipv4, ipv6, netlink).', - }, - { - name: 'path', - type: 'keyword', - description: 'This is the path associated with a unix socket.', - }, - ], - }, - ], - }, - { - name: 'messages', - type: 'alias', - migration: true, - path: 'event.original', - description: - 'An ordered list of the raw messages received from the kernel that were used to construct this document. This field is present if an error occurred processing the data or if `include_raw_message` is set in the config.\n', - }, - { - name: 'warnings', - type: 'alias', - migration: true, - path: 'error.message', - description: - 'The warnings generated by the Beat during the construction of the event. These are disabled by default and are used for development and debug purposes only.\n', - }, - ], - }, - { - name: 'geoip', - type: 'group', - description: - 'The geoip fields are defined as a convenience in case you decide to enrich the data using a geoip filter in Logstash or Ingest Node.\n', - fields: [ - { - name: 'continent_name', - type: 'keyword', - description: 'The name of the continent.\n', - }, - { - name: 'city_name', - type: 'keyword', - description: 'The name of the city.\n', - }, - { - name: 'region_name', - type: 'keyword', - description: 'The name of the region.\n', - }, - { - name: 'country_iso_code', - type: 'keyword', - description: 'Country ISO code.\n', - }, - { - name: 'location', - type: 'geo_point', - description: 'The longitude and latitude.\n', - }, - ], - }, - ], - }, - { - key: 'file_integrity', - title: 'File Integrity', - description: 'These are the fields generated by the file_integrity module.', - fields: [ - { - name: 'hash', - type: 'group', - description: - 'Hashes of the file. The keys are algorithm names and the values are the hex encoded digest values.\n', - fields: [ - { - name: 'blake2b_256', - type: 'keyword', - description: 'BLAKE2b-256 hash of the file.', - }, - { - name: 'blake2b_384', - type: 'keyword', - description: 'BLAKE2b-384 hash of the file.', - }, - { - name: 'blake2b_512', - type: 'keyword', - description: 'BLAKE2b-512 hash of the file.', - }, - { - name: 'md5', - overwrite: true, - type: 'keyword', - description: 'MD5 hash of the file.', - }, - { - name: 'sha1', - overwrite: true, - type: 'keyword', - description: 'SHA1 hash of the file.', - }, - { - name: 'sha224', - type: 'keyword', - description: 'SHA224 hash of the file.', - }, - { - name: 'sha256', - overwrite: true, - type: 'keyword', - description: 'SHA256 hash of the file.', - }, - { - name: 'sha384', - type: 'keyword', - description: 'SHA384 hash of the file.', - }, - { - name: 'sha3_224', - type: 'keyword', - description: 'SHA3_224 hash of the file.', - }, - { - name: 'sha3_256', - type: 'keyword', - description: 'SHA3_256 hash of the file.', - }, - { - name: 'sha3_384', - type: 'keyword', - description: 'SHA3_384 hash of the file.', - }, - { - name: 'sha3_512', - type: 'keyword', - description: 'SHA3_512 hash of the file.', - }, - { - name: 'sha512', - overwrite: true, - type: 'keyword', - description: 'SHA512 hash of the file.', - }, - { - name: 'sha512_224', - type: 'keyword', - description: 'SHA512/224 hash of the file.', - }, - { - name: 'sha512_256', - type: 'keyword', - description: 'SHA512/256 hash of the file.', - }, - { - name: 'xxh64', - type: 'keyword', - description: 'XX64 hash of the file.', - }, - ], - }, - ], - }, - { - key: 'system', - title: 'System', - description: 'These are the fields generated by the system module.\n', - release: 'beta', - fields: [ - { - name: 'event', - type: 'group', - fields: [ - { - name: 'origin', - type: 'keyword', - description: - 'Origin of the event. This can be a file path (e.g. `/var/log/log.1`), or the name of the system component that supplied the data (e.g. `netlink`).\n', - }, - ], - }, - { - name: 'user', - type: 'group', - fields: [ - { - name: 'entity_id', - type: 'keyword', - description: - 'ID uniquely identifying the user on a host. It is computed as a SHA-256 hash of the host ID, user ID, and user name.\n', - }, - { - name: 'terminal', - type: 'keyword', - description: 'Terminal of the user.\n', - }, - ], - }, - { - name: 'process', - type: 'group', - fields: [ - { - name: 'hash', - type: 'group', - description: - 'Hashes of the executable. The keys are algorithm names and the values are the hex encoded digest values.\n', - fields: [ - { - name: 'blake2b_256', - type: 'keyword', - description: 'BLAKE2b-256 hash of the executable.', - }, - { - name: 'blake2b_384', - type: 'keyword', - description: 'BLAKE2b-384 hash of the executable.', - }, - { - name: 'blake2b_512', - type: 'keyword', - description: 'BLAKE2b-512 hash of the executable.', - }, - { - name: 'sha224', - type: 'keyword', - description: 'SHA224 hash of the executable.', - }, - { - name: 'sha384', - type: 'keyword', - description: 'SHA384 hash of the executable.', - }, - { - name: 'sha3_224', - type: 'keyword', - description: 'SHA3_224 hash of the executable.', - }, - { - name: 'sha3_256', - type: 'keyword', - description: 'SHA3_256 hash of the executable.', - }, - { - name: 'sha3_384', - type: 'keyword', - description: 'SHA3_384 hash of the executable.', - }, - { - name: 'sha3_512', - type: 'keyword', - description: 'SHA3_512 hash of the executable.', - }, - { - name: 'sha512_224', - type: 'keyword', - description: 'SHA512/224 hash of the executable.', - }, - { - name: 'sha512_256', - type: 'keyword', - description: 'SHA512/256 hash of the executable.', - }, - { - name: 'xxh64', - type: 'keyword', - description: 'XX64 hash of the executable.', - }, - ], - }, - ], - }, - { - name: 'socket', - type: 'group', - fields: [ - { - name: 'entity_id', - type: 'keyword', - description: - 'ID uniquely identifying the socket. It is computed as a SHA-256 hash of the host ID, socket inode, local IP, local port, remote IP, and remote port.\n', - }, - ], - }, - { - name: 'system.audit', - type: 'group', - description: '\n', - fields: [ - { - name: 'host', - type: 'group', - description: '`host` contains general host information.\n', - release: 'beta', - fields: [ - { - name: 'uptime', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - output_format: 'asDays', - output_precision: 1, - description: 'Uptime in nanoseconds.\n', - }, - { - name: 'boottime', - type: 'date', - description: 'Boot time.\n', - }, - { - name: 'containerized', - type: 'boolean', - description: 'Set if host is a container.\n', - }, - { - name: 'timezone.name', - type: 'keyword', - description: 'Name of the timezone of the host, e.g. BST.\n', - }, - { - name: 'timezone.offset.sec', - type: 'long', - description: 'Timezone offset in seconds.\n', - }, - { - name: 'hostname', - type: 'keyword', - description: 'Hostname.\n', - }, - { - name: 'id', - type: 'keyword', - description: 'Host ID.\n', - }, - { - name: 'architecture', - type: 'keyword', - description: 'Host architecture (e.g. x86_64).\n', - }, - { - name: 'mac', - type: 'keyword', - description: 'MAC addresses.\n', - }, - { - name: 'ip', - type: 'ip', - description: 'IP addresses.\n', - }, - { - name: 'os', - type: 'group', - description: '`os` contains information about the operating system.\n', - fields: [ - { - name: 'codename', - type: 'keyword', - description: 'OS codename, if any (e.g. stretch).\n', - }, - { - name: 'platform', - type: 'keyword', - description: 'OS platform (e.g. centos, ubuntu, windows).\n', - }, - { - name: 'name', - type: 'keyword', - description: 'OS name (e.g. Mac OS X).\n', - }, - { - name: 'family', - type: 'keyword', - description: 'OS family (e.g. redhat, debian, freebsd, windows).\n', - }, - { - name: 'version', - type: 'keyword', - description: 'OS version.\n', - }, - { - name: 'kernel', - type: 'keyword', - description: "The operating system's kernel version.\n", - }, - ], - }, - ], - }, - { - name: 'package', - type: 'group', - description: '`package` contains information about an installed or removed package.\n', - release: 'beta', - fields: [ - { - name: 'entity_id', - type: 'keyword', - description: - 'ID uniquely identifying the package. It is computed as a SHA-256 hash of the host ID, package name, and package version.\n', - }, - { - name: 'name', - type: 'keyword', - description: 'Package name.\n', - }, - { - name: 'version', - type: 'keyword', - description: 'Package version.\n', - }, - { - name: 'release', - type: 'keyword', - description: 'Package release.\n', - }, - { - name: 'arch', - type: 'keyword', - description: 'Package architecture.\n', - }, - { - name: 'license', - type: 'keyword', - description: 'Package license.\n', - }, - { - name: 'installtime', - type: 'date', - description: 'Package install time.\n', - }, - { - name: 'size', - type: 'long', - description: 'Package size.\n', - }, - { - name: 'summary', - description: 'Package summary.\n', - }, - { - name: 'url', - type: 'keyword', - description: 'Package URL.\n', - }, - ], - }, - { - name: 'user', - type: 'group', - description: '`user` contains information about the users on a system.\n', - release: 'beta', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'User name.\n', - }, - { - name: 'uid', - type: 'keyword', - description: 'User ID.\n', - }, - { - name: 'gid', - type: 'keyword', - description: 'Group ID.\n', - }, - { - name: 'dir', - type: 'keyword', - description: "User's home directory.\n", - }, - { - name: 'shell', - type: 'keyword', - description: 'Program to run at login.\n', - }, - { - name: 'user_information', - type: 'keyword', - description: 'General user information. On Linux, this is the gecos field.\n', - }, - { - name: 'group', - type: 'object', - description: - "`group` contains information about any groups the user is part of (beyond the user's primary group).\n", - fields: [ - { - name: 'name', - type: 'keyword', - description: 'Group name.\n', - }, - { - name: 'gid', - type: 'integer', - description: 'Group ID.\n', - }, - ], - }, - { - name: 'password', - type: 'group', - description: - "`password` contains information about a user's password (not the password itself).\n", - fields: [ - { - name: 'type', - type: 'keyword', - description: - "A user's password type. Possible values are `shadow_password` (the password hash is in the shadow file), `password_disabled`, `no_password` (this is dangerous as anyone can log in), and `crypt_password` (when the password field in /etc/passwd seems to contain an encrypted password).\n", - }, - { - name: 'last_changed', - type: 'date', - description: "The day the user's password was last changed.\n", - }, - ], - }, - ], - }, - ], - }, - ], - }, -]; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/ecs.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/ecs.ts deleted file mode 100644 index a439d105d63df1..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/ecs.ts +++ /dev/null @@ -1,5675 +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. - */ - -/** - * An instance of the unmodified schema exported from https://github.com/elastic/ecs - * A map of `EcsNamespace.name` `->` `EcsNamespace` - * - * - NOTE: This instance does NOT include "virtual (non-spec)" ECS fields e.g `_id`. - * - NOTE: This instance does NOT include "mappings" from ECS fields, to `ECS` - * instances e.g. `@timestamp` to `timestamp` - */ - -import { Schema } from '../type'; - -export const ecsSchema: Schema = [ - { - key: 'ecs', - title: 'ECS', - description: 'ECS Fields.', - fields: [ - { - name: '@timestamp', - level: 'core', - required: true, - type: 'date', - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'labels', - level: 'core', - type: 'object', - object_type: 'keyword', - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - }, - { - name: 'tags', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - }, - { - name: 'agent', - title: 'Agent', - group: 2, - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - footnote: - 'Examples: In the case of Beats for logs, the agent.name is filebeat.\nFor APM, it is the agent running in the app/service. The agent information does\nnot change if data is sent through queuing systems like Kafka, Redis, or processing\nsystems such as Logstash or APM Server.', - type: 'group', - fields: [ - { - name: 'build.original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Extended build information for the agent.\n\nThis field is intended to contain any build information that a data source\nmay provide, no specific formatting is required.', - example: - 'metricbeat version 7.6.0 (amd64), libbeat 7.6.0 [6a23e8f8f30f5001ba344e4e54d8d9cb82cb107c\nbuilt 2020-02-05 23:10:10 +0000 UTC]', - default_field: false, - }, - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the agent.', - example: '6.0.0-rc2', - }, - ], - }, - { - name: 'as', - title: 'Autonomous System', - group: 2, - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - type: 'group', - fields: [ - { - name: 'number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - ], - }, - { - name: 'client', - title: 'Client', - group: 2, - description: - 'A client is defined as the initiator of a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the client is the initiator of the TCP connection that sends\nthe SYN packet(s). For other protocols, the client is generally the initiator\nor requestor in the network transaction. Some systems use the term "originator"\nto refer the client in TCP connections. The client fields describe details about\nthe system acting as the client in the network event. Client fields are usually\npopulated in conjunction with server fields. Client fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event client addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the client to the server.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Client domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP address of the client (IPv4 or IPv6).', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the client.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated IP of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the client to the server.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the client.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered client domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'cloud', - title: 'Cloud', - group: 2, - description: 'Fields related to the cloud or infrastructure the events are coming\nfrom.', - footnote: - 'Examples: If Metricbeat is running on an EC2 host and fetches data\nfrom its host, the cloud info contains the data about this machine. If Metricbeat\nruns on a remote machine outside the cloud and fetches data from a service running\nin the cloud, the field contains cloud data from the machine the service is\nrunning on.', - type: 'group', - fields: [ - { - name: 'account.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The cloud account or organization id used to identify different\nentities in a multi-tenant environment.\n\nExamples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: 666777888999, - }, - { - name: 'availability_zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - }, - { - name: 'instance.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance ID of the host machine.', - example: 'i-1234567890abcdef0', - }, - { - name: 'instance.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance name of the host machine.', - }, - { - name: 'machine.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Machine type of the host machine.', - example: 't2.medium', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the cloud provider. Example values are aws, azure, gcp,\nor digitalocean.', - example: 'aws', - }, - { - name: 'region', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Region in which this host is running.', - example: 'us-east-1', - }, - ], - }, - { - name: 'code_signature', - title: 'Code Signature', - group: 2, - description: 'These fields contain information about binary code signatures.', - type: 'group', - fields: [ - { - name: 'exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - ], - }, - { - name: 'container', - title: 'Container', - group: 2, - description: - 'Container fields are used for meta information about the specific\ncontainer that is the source of information.\n\nThese fields help correlate data based containers from any runtime.', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique container id.', - }, - { - name: 'image.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the image the container was built on.', - }, - { - name: 'image.tag', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container image tags.', - }, - { - name: 'labels', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: 'Image labels.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container name.', - }, - { - name: 'runtime', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Runtime managing this container.', - example: 'docker', - }, - ], - }, - { - name: 'destination', - title: 'Destination', - group: 2, - description: - 'Destination fields describe details about the destination of a packet/event.\n\nDestination fields are usually populated in conjunction with source fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event destination addresses are defined ambiguously. The\nevent will sometimes list an IP, a domain or a unix socket. You should always\nstore the raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the destination to the source.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Destination domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP address of the destination (IPv4 or IPv6).', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the destination.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Port the source session is translated to by NAT Device.\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the destination to the source.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the destination.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered destination domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'dll', - title: 'DLL', - group: 2, - description: - 'These fields contain information about code libraries dynamically\nloaded into processes.\n\n\nMany operating systems refer to "shared code libraries" with different names,\nbut this field set refers to all of the following:\n\n* Dynamic-link library (`.dll`) commonly used on Windows\n\n* Shared Object (`.so`) commonly used on Unix-like operating systems\n\n* Dynamic library (`.dylib`) commonly used on macOS', - type: 'group', - fields: [ - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the library.\n\nThis generally maps to the name of the file on disk.', - example: 'kernel32.dll', - default_field: false, - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Full file path of the library.', - example: 'C:\\Windows\\System32\\kernel32.dll', - default_field: false, - }, - { - name: 'pe.architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'CPU architecture target for the file.', - example: 'x64', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.imphash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of the imports in a PE file. An imphash -- or import hash\n-- can be used to fingerprint binaries even after recompilation or other code-level\ntransformations have occurred, which would change more traditional hash values.\n\nLearn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.', - example: '0c6803c4e922103c4dca5963aad36ddf', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'dns', - title: 'DNS', - group: 2, - description: - 'Fields describing DNS queries and answers.\n\nDNS events should either represent a single DNS query prior to getting answers\n(`dns.type:query`) or they should represent a full exchange and contain the\nquery details as well as all of the answers that were provided for this query\n(`dns.type:answer`).', - type: 'group', - fields: [ - { - name: 'answers', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'An array containing an object for each answer section returned\nby the server.\n\nThe main keys that should be present in these objects are defined by ECS.\nRecords that have more information may contain more keys than what ECS defines.\n\nNot all DNS data sources give all details about DNS answers. At minimum, answer\nobjects must contain the `data` key. If more information is available, map\nas much of it to ECS as possible, and add any additional fields to the answer\nobjects as custom fields.', - }, - { - name: 'answers.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of DNS data contained in this resource record.', - example: 'IN', - }, - { - name: 'answers.data', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The data describing the resource.\n\nThe meaning of this data depends on the type and class of the resource record.', - example: '10.10.10.10', - }, - { - name: 'answers.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The domain name to which this resource record pertains.\n\nIf a chain of CNAME is being resolved, each answer `name` should be the\none that corresponds with the answer `data`. It should not simply be the\noriginal `question.name` repeated.', - example: 'www.google.com', - }, - { - name: 'answers.ttl', - level: 'extended', - type: 'long', - description: - 'The time interval in seconds that this resource record may be cached\nbefore it should be discarded. Zero values mean that the data should not be\ncached.', - example: 180, - }, - { - name: 'answers.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of data contained in this resource record.', - example: 'CNAME', - }, - { - name: 'header_flags', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of 2 letter DNS header flags.\n\nExpected values are: AA, TC, RD, RA, AD, CD, DO.', - example: ['RD', 'RA'], - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS packet identifier assigned by the program that generated\nthe query. The identifier is copied to the response.', - example: 62111, - }, - { - name: 'op_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS operation code that specifies the kind of query in the\nmessage. This value is set by the originator of a query and copied into the\nresponse.', - example: 'QUERY', - }, - { - name: 'question.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of records being queried.', - example: 'IN', - }, - { - name: 'question.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name being queried.\n\nIf the name field contains non-printable characters (below 32 or above 126),\nthose characters should be represented as escaped base 10 integers (\\DDD).\nBack slashes and quotes should be escaped. Tabs, carriage returns, and line\nfeeds should be converted to \\t, \\r, and \\n respectively.', - example: 'www.google.com', - }, - { - name: 'question.registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'question.subdomain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The subdomain is all of the labels under the registered_domain.\n\nIf the domain has multiple levels of subdomain, such as "sub2.sub1.example.com",\nthe subdomain field should contain "sub2.sub1", with no trailing period.', - example: 'www', - }, - { - name: 'question.top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'question.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of record being queried.', - example: 'AAAA', - }, - { - name: 'resolved_ip', - level: 'extended', - type: 'ip', - description: - 'Array containing all IPs seen in `answers.data`.\n\nThe `answers` array can be difficult to use, because of the variety of data\nformats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip`\nmakes it possible to index them as IP addresses, and makes them easier to\nvisualize and query for.', - example: ['10.10.10.10', '10.10.10.11'], - }, - { - name: 'response_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The DNS response code.', - example: 'NOERROR', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of DNS event captured, query or answer.\n\nIf your source of DNS events only gives you DNS queries, you should only create\ndns events of type `dns.type:query`.\n\nIf your source of DNS events gives you answers as well, you should create\none event per query (optionally as soon as the query is seen). And a second\nevent containing all query details as well as an array of answers.', - example: 'answer', - }, - ], - }, - { - name: 'ecs', - title: 'ECS', - group: 2, - description: 'Meta-information specific to ECS.', - type: 'group', - fields: [ - { - name: 'version', - level: 'core', - required: true, - type: 'keyword', - ignore_above: 1024, - description: - 'ECS version this event conforms to. `ecs.version` is a required\nfield and must exist in all events.\n\nWhen querying across multiple indices -- which may conform to slightly different\nECS versions -- this field lets integrations adjust to the schema version\nof the events.', - example: '1.0.0', - }, - ], - }, - { - name: 'error', - title: 'Error', - group: 2, - description: - 'These fields can represent errors of any kind.\n\nUse them for errors that happen while fetching events or in cases where the\nevent itself contains an error.', - type: 'group', - fields: [ - { - name: 'code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Error code describing the error.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the error.', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: 'Error message.', - }, - { - name: 'stack_trace', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The stack trace of this error in plain text.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of the error, for example the class name of the exception.', - example: 'java.lang.NullPointerException', - }, - ], - }, - { - name: 'event', - title: 'Event', - group: 2, - description: - 'The event fields are used for context information about the log\nor metric event itself.\n\nA log is defined as an event containing details of something that happened.\nLog events must include the time at which the thing happened. Examples of log\nevents include a process starting on a host, a network packet being sent from\na source to a destination, or a network connection between a client and a server\nbeing initiated or closed. A metric is defined as an event containing one or\nmore numerical measurements and the time at which the measurement was taken.\nExamples of metric events include memory pressure measured on a host and device\ntemperature. See the `event.kind` definition in this section for additional\ndetails about metric and state events.', - type: 'group', - fields: [ - { - name: 'action', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.', - example: 'user-password-change', - }, - { - name: 'category', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nsecond level in the ECS category hierarchy.\n\n`event.category` represents the "big buckets" of ECS categories. For example,\nfiltering on `event.category:process` yields all events relating to process\nactivity. This field is closely related to `event.type`, which is used as\na subcategory.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple categories.', - example: 'authentication', - }, - { - name: 'code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Identification code for this event, if one exists.\n\nSome event sources use event codes to identify messages unambiguously, regardless\nof message language or wording adjustments over time. An example of this is\nthe Windows Event ID.', - example: 4648, - }, - { - name: 'created', - level: 'core', - type: 'date', - description: - 'event.created contains the date/time when the event was first\nread by an agent, or by your pipeline.\n\nThis field is distinct from @timestamp in that @timestamp typically contain\nthe time extracted from the original event.\n\nIn most situations, these two timestamps will be slightly different. The difference\ncan be used to calculate the delay between your source generating an event,\nand the time when your agent first processed it. This can be used to monitor\nyour agent or pipeline ability to keep up with your event source.\n\nIn case the two timestamps are identical, @timestamp should be used.', - example: '2016-05-23T08:05:34.857Z', - }, - { - name: 'dataset', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the dataset.\n\nIf an event source publishes more than one type of log or events (e.g. access\nlog, error log), the dataset is used to specify which one the event comes\nfrom.\n\nIt is recommended but not required to start the dataset name with the module\nname, followed by a dot, then the dataset name.', - example: 'apache.access', - }, - { - name: 'duration', - level: 'core', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - output_format: 'asMilliseconds', - output_precision: 1, - description: - 'Duration of the event in nanoseconds.\n\nIf event.start and event.end are known this value should be the difference\nbetween the end and start time.', - }, - { - name: 'end', - level: 'extended', - type: 'date', - description: - 'event.end contains the date when the event ended or when the activity\nwas last observed.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Hash (perhaps logstash fingerprint) of raw field to be able to\ndemonstrate log integrity.', - example: '123456789012345678901234567890ABCD', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique ID to describe the event.', - example: '8a4f500d', - }, - { - name: 'ingested', - level: 'core', - type: 'date', - description: - 'Timestamp when an event arrived in the central data store.\n\nThis is different from `@timestamp`, which is when the event originally occurred. It is\nalso different from `event.created`, which is meant to capture the first time\nan agent saw the event.\n\nIn normal conditions, assuming no tampering, the timestamps should chronologically\nlook like this: `@timestamp` < `event.created` < `event.ingested`.', - example: '2016-05-23T08:05:35.101Z', - default_field: false, - }, - { - name: 'kind', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nhighest level in the ECS category hierarchy.\n\n`event.kind` gives high-level information about what type of information the\nevent contains, without being specific to the contents of the event. For example,\nvalues of this field distinguish alert events from metric events.\n\nThe value of this field can be used to inform how these kinds of events should\nbe handled. They may warrant different retention, different access control,\nit may also help understand whether the data coming in at a regular interval\nor not.', - example: 'alert', - }, - { - name: 'module', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the module this data is coming from.\n\nIf your monitoring agent supports the concept of modules or plugins to process\nevents of a given source (e.g. Apache logs), `event.module` should contain\nthe name of this module.', - example: 'apache', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Raw text message of entire event. Used to demonstrate log integrity.\n\nThis field is not indexed and doc_values are disabled. It cannot be searched,\nbut it can be retrieved from `_source`.', - example: - 'Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100|\nworm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232', - }, - { - name: 'outcome', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nlowest level in the ECS category hierarchy.\n\n`event.outcome` simply denotes whether the event represents a success or a\nfailure from the perspective of the entity that produced the event.\n\nNote that when a single transaction is described in multiple events, each\nevent may populate different values of `event.outcome`, according to their\nperspective.\n\nAlso note that in the case of a compound event (a single event that contains\nmultiple logical events), this field should be populated with the value that\nbest captures the overall success or failure from the perspective of the event\nproducer.\n\nFurther note that not all events will have an associated outcome. For example,\nthis field is generally not populated for metric events, events with `event.type:info`,\nor any events for which an outcome does not make logical sense.', - example: 'success', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Source of the event.\n\nEvent transports such as Syslog or the Windows Event Log typically mention\nthe source of an event. It can be the name of the software that generated\nthe event (e.g. Sysmon, httpd), or of a subsystem of the operating system\n(kernel, Microsoft-Windows-Security-Auditing).', - example: 'kernel', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL linking to additional information about this event.\n\nThis URL links to a static definition of the this event. Alert events, indicated\nby `event.kind:alert`, are a common use case for this field.', - example: 'https://system.vendor.com/event/#0001234', - default_field: false, - }, - { - name: 'risk_score', - level: 'core', - type: 'float', - description: - "Risk score or priority of the event (e.g. security solutions).\nUse your system's original value here.", - }, - { - name: 'risk_score_norm', - level: 'extended', - type: 'float', - description: - 'Normalized risk score or priority of the event, on a scale of\n0 to 100.\n\nThis is mainly useful if you use more than one system that assigns risk scores,\nand you want to see a normalized value across all systems.', - }, - { - name: 'sequence', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Sequence number of the event.\n\nThe sequence number is a value published by some event sources, to make the\nexact ordering of events unambiguous, regardless of the timestamp precision.', - }, - { - name: 'severity', - level: 'core', - type: 'long', - format: 'string', - description: - 'The numeric severity of the event according to your event source.\n\nWhat the different severity values mean can be different between sources and\nuse cases. It is up to the implementer to make sure severities are consistent\nacross events from the same source.\n\nThe Syslog severity belongs in `log.syslog.severity.code`. `event.severity`\nis meant to represent the severity according to the event source (e.g. firewall,\nIDS). If the event source does not publish its own severity, you may optionally\ncopy the `log.syslog.severity.code` to `event.severity`.', - example: 7, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: - 'event.start contains the date when the event started or when the\nactivity was first observed.', - }, - { - name: 'timezone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'This field should be populated when the event timestamp does\nnot include timezone information already (e.g. default Syslog timestamps).\nIt is optional otherwise.\n\nAcceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"),\nabbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nthird level in the ECS category hierarchy.\n\n`event.type` represents a categorization "sub-bucket" that, when used along\nwith the `event.category` field values, enables filtering events down to a\nlevel appropriate for single visualization.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple event types.', - }, - { - name: 'url', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'URL linking to an external system to continue investigation of\nthis event.\n\nThis URL links to another system where in-depth investigation of the specific\noccurence of this event can take place. Alert events, indicated by `event.kind:alert`,\nare a common use case for this field.', - example: 'https://mysystem.mydomain.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe', - default_field: false, - }, - ], - }, - { - name: 'file', - title: 'File', - group: 2, - description: - 'A file is defined as a set of information that has been created\non, or has existed on a filesystem.\n\nFile objects can be associated with host events, network events, and/or file\nevents (e.g., those produced by File Integrity Monitoring [FIM] products or\nservices). File fields provide details about the affected file associated with\nthe event or metric.', - type: 'group', - fields: [ - { - name: 'accessed', - level: 'extended', - type: 'date', - description: - 'Last time the file was accessed.\n\nNote that not all filesystems keep track of access time.', - }, - { - name: 'attributes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of file attributes.\n\nAttributes names will vary by platform. Here is a non-exhaustive list of values\nthat are expected in this field: archive, compressed, directory, encrypted,\nexecute, hidden, read, readonly, system, write.', - example: '["readonly", "system"]', - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'created', - level: 'extended', - type: 'date', - description: - 'File creation time.\n\nNote that not all filesystems store the creation time.', - }, - { - name: 'ctime', - level: 'extended', - type: 'date', - description: - 'Last time the file attributes or metadata changed.\n\nNote that changes to the file content will update `mtime`. This implies `ctime`\nwill be adjusted at the same time, since `mtime` is an attribute of the file.', - }, - { - name: 'device', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Device that is the source of the file.', - example: 'sda', - }, - { - name: 'directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Directory where the file is located. It should include the drive\nletter, when appropriate.', - example: '/home/alice', - }, - { - name: 'drive_letter', - level: 'extended', - type: 'keyword', - ignore_above: 1, - description: - 'Drive letter where the file is located. This field is only relevant\non Windows.\n\nThe value should be uppercase, and not include the colon.', - example: 'C', - default_field: false, - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File extension.', - example: 'png', - }, - { - name: 'gid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group ID (GID) of the file.', - example: '1001', - }, - { - name: 'group', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group name of the file.', - example: 'alice', - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'inode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Inode representing the file in the filesystem.', - example: '256383', - }, - { - name: 'mime_type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'MIME type should identify the format of the file or stream of bytes\nusing https://www.iana.org/assignments/media-types/media-types.xhtml[IANA\nofficial types], where possible. When more than one type is applicable, the\nmost specific type should be used.', - default_field: false, - }, - { - name: 'mode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Mode of the file in octal representation.', - example: '0640', - }, - { - name: 'mtime', - level: 'extended', - type: 'date', - description: 'Last time the file content was modified.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the file including the extension, without the directory.', - example: 'example.png', - }, - { - name: 'owner', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: "File owner's username.", - example: 'alice', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Full path to the file, including the file name. It should include\nthe drive letter, when appropriate.', - example: '/home/alice/example.png', - }, - { - name: 'pe.architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'CPU architecture target for the file.', - example: 'x64', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.imphash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of the imports in a PE file. An imphash -- or import hash\n-- can be used to fingerprint binaries even after recompilation or other code-level\ntransformations have occurred, which would change more traditional hash values.\n\nLearn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.', - example: '0c6803c4e922103c4dca5963aad36ddf', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - description: 'File size in bytes.\n\nOnly relevant when `file.type` is "file".', - example: 16384, - }, - { - name: 'target_path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Target path for symlinks.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File type (file, dir, or symlink).', - example: 'file', - }, - { - name: 'uid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The user ID (UID) or security identifier (SID) of the file owner.', - example: '1001', - }, - ], - }, - { - name: 'geo', - title: 'Geo', - group: 2, - description: - 'Geo fields can carry data about a specific location related to an\nevent.\n\nThis geolocation information can be derived from techniques such as Geo IP,\nor be user-supplied.', - type: 'group', - fields: [ - { - name: 'city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - ], - }, - { - name: 'group', - title: 'Group', - group: 2, - description: - 'The group fields are meant to represent groups that are relevant\nto the event.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - ], - }, - { - name: 'hash', - title: 'Hash', - group: 2, - description: - 'The hash fields represent different hash algorithms and their values.\n\nField names for common hashes (e.g. MD5, SHA1) are predefined. Add fields for\nother hashes by lowercasing the hash algorithm name and using underscore separators\nas appropriate (snake case, e.g. sha3_512).', - type: 'group', - fields: [ - { - name: 'md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - ], - }, - { - name: 'host', - title: 'Host', - group: 2, - description: - 'A host is defined as a general computing instance.\n\nECS host.* fields should be populated with details about the host on which the\nevent happened, or from which the measurement was taken. Host types include\nhardware, virtual machines, Docker containers, and Kubernetes nodes.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system architecture.', - example: 'x86_64', - }, - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the domain of which the host is a member.\n\nFor example, on Windows this could be the host Active Directory domain\nor NetBIOS domain name. For Linux this could be the domain of the host\nLDAP provider.', - example: 'CONTOSO', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Hostname of the host.\n\nIt normally contains what the `hostname` command returns on the host machine.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique host id.\n\nAs hostname is not always unique, use values that are meaningful in your environment.\n\nExample: The current usage of `beat.name`.', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'Host ip addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Host mac addresses.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of host.\n\nFor Cloud providers this can be the machine type like `t2.medium`. If vm,\nthis could be the container, for example, or other information meaningful\nin your environment.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the host has been up.', - example: 1325, - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'http', - title: 'HTTP', - group: 2, - description: - 'Fields related to HTTP activity. Use the `url` field set to store\nthe url of the request.', - type: 'group', - fields: [ - { - name: 'request.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the request body.', - example: 887, - }, - { - name: 'request.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP request body.', - example: 'Hello world', - }, - { - name: 'request.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the request (body and headers).', - example: 1437, - }, - { - name: 'request.method', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'HTTP request method.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'get, post, put', - }, - { - name: 'request.referrer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Referrer for this HTTP request.', - example: 'https://blog.example.com/', - }, - { - name: 'response.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the response body.', - example: 887, - }, - { - name: 'response.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP response body.', - example: 'Hello world', - }, - { - name: 'response.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the response (body and headers).', - example: 1437, - }, - { - name: 'response.status_code', - level: 'extended', - type: 'long', - format: 'string', - description: 'HTTP response status code.', - example: 404, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'HTTP version.', - example: 1.1, - }, - ], - }, - { - name: 'interface', - title: 'Interface', - group: 2, - description: - 'The interface fields are used to record ingress and egress interface\ninformation when reported by an observer (e.g. firewall, router, load balancer)\nin the context of the observer handling a network connection. In the case of\na single observer interface (e.g. network sensor on a span port) only the observer.ingress\ninformation should be populated.', - type: 'group', - fields: [ - { - name: 'alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - ], - }, - { - name: 'log', - title: 'Log', - group: 2, - description: - 'Details about the event logging mechanism or logging transport.\n\nThe log.* fields are typically populated with details about the logging mechanism\nused to create and/or transport the event. For example, syslog details belong\nunder `log.syslog.*`.\n\nThe details specific to your event source are typically not logged under `log.*`,\nbut rather in `event.*` or in other ECS fields.', - type: 'group', - fields: [ - { - name: 'file.path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - "Full path to the log file this event came from, including the\nfile name. It should include the drive letter, when appropriate.\n\nIf the event wasn't read from a log file, do not populate this field.", - example: '/var/log/fun-times.log', - default_field: false, - }, - { - name: 'level', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Original log level of the log event.\n\nIf the source of the event provides a log level or textual severity, this\nis the one that goes in `log.level`. If your source does not specify one,\nyou may put your event transport severity here (e.g. Syslog severity).\n\nSome examples are `warn`, `err`, `i`, `informational`.', - example: 'error', - }, - { - name: 'logger', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the logger inside an application. This is usually the\nname of the class which initialized the logger, or can be a custom name.', - example: 'org.elasticsearch.bootstrap.Bootstrap', - }, - { - name: 'origin.file.line', - level: 'extended', - type: 'integer', - description: - 'The line number of the file containing the source code which originated\nthe log event.', - example: 42, - }, - { - name: 'origin.file.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the file containing the source code which originated\nthe log event.\n\nNote that this field is not meant to capture the log file. The correct field\nto capture the log file is `log.file.path`.', - example: 'Bootstrap.java', - }, - { - name: 'origin.function', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the function or method which originated the log event.', - example: 'init', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is the original log message and contains the full log message\nbefore splitting it up in multiple parts.\n\nIn contrast to the `message` field which can contain an extracted part of\nthe log message, this field contains the original, full log message. It can\nhave already some modifications applied like encoding or new lines removed\nto clean up the log message.\n\nThis field is not indexed and doc_values are disabled so it cannot be queried\nbut the value can be retrieved from `_source`.', - example: 'Sep 19 08:26:10 localhost My log', - }, - { - name: 'syslog', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'The Syslog metadata of the event, if the event was transmitted\nvia Syslog. Please see RFCs 5424 or 3164.', - }, - { - name: 'syslog.facility.code', - level: 'extended', - type: 'long', - format: 'string', - description: - 'The Syslog numeric facility of the log event, if available.\n\nAccording to RFCs 5424 and 3164, this value should be an integer between 0\nand 23.', - example: 23, - }, - { - name: 'syslog.facility.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The Syslog text-based facility of the log event, if available.', - example: 'local7', - }, - { - name: 'syslog.priority', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Syslog numeric priority of the event, if available.\n\nAccording to RFCs 5424 and 3164, the priority is 8 * facility + severity.\nThis number is therefore expected to contain a value between 0 and 191.', - example: 135, - }, - { - name: 'syslog.severity.code', - level: 'extended', - type: 'long', - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different numeric severity\nvalue (e.g. firewall, IDS), your source numeric severity should go to `event.severity`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `event.severity`.', - example: 3, - }, - { - name: 'syslog.severity.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different severity value\n(e.g. firewall, IDS), your source text severity should go to `log.level`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `log.level`.', - example: 'Error', - }, - ], - }, - { - name: 'network', - title: 'Network', - group: 2, - description: - 'The network is defined as the communication path over which a host\nor network event happens.\n\nThe network.* fields should be populated with details about the network activity\nassociated with an event.', - type: 'group', - fields: [ - { - name: 'application', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A name given to an application level protocol. This can be arbitrarily\nassigned for things like microservices, but also apply to things like skype,\nicq, facebook, twitter. This would be used in situations where the vendor\nor service can be decoded such as from the source/dest IP owners, ports, or\nwire format.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'aim', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: - 'Total bytes transferred in both directions.\n\nIf `source.bytes` and `destination.bytes` are known, `network.bytes` is their\nsum.', - example: 368, - }, - { - name: 'community_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of source and destination IPs and ports, as well as the\nprotocol used in a communication. This is a tool-agnostic standard to identify\nflows.\n\nLearn more at https://github.com/corelight/community-id-spec.', - example: '1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=', - }, - { - name: 'direction', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - "Direction of the network traffic.\nRecommended values are:\n * inbound\n * outbound\n * internal\n * external\n * unknown\n\nWhen mapping events from a host-based monitoring context, populate this field from the host's point of view.\nWhen mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of your network perimeter.", - example: 'inbound', - }, - { - name: 'forwarded_ip', - level: 'core', - type: 'ip', - description: 'Host IP address when the source IP address is the proxy.', - example: '192.1.1.2', - }, - { - name: 'iana_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).\nStandardized list of protocols. This aligns well with NetFlow and sFlow related\nlogs which use the IANA Protocol Number.', - example: 6, - }, - { - name: 'inner', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Network.inner fields are added in addition to network.vlan fields\nto describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed\nfields include vlan.id and vlan.name. Inner vlan fields are typically used\nwhen sending traffic with multiple 802.1q encapsulations to a network sensor\n(e.g. Zeek, Wireshark.)', - default_field: false, - }, - { - name: 'inner.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'inner.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name given by operators to sections of their network.', - example: 'Guest Wifi', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: - 'Total packets transferred in both directions.\n\nIf `source.packets` and `destination.packets` are known, `network.packets`\nis their sum.', - example: 24, - }, - { - name: 'protocol', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'L7 Network protocol name. ex. http, lumberjack, transport protocol.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'http', - }, - { - name: 'transport', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Same as network.iana_number, but instead using the Keyword name\nof the transport layer (udp, tcp, ipv6-icmp, etc.)\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'tcp', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'In the OSI Model this would be the Network Layer. ipv4, ipv6,\nipsec, pim, etc\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'ipv4', - }, - { - name: 'vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'observer', - title: 'Observer', - group: 2, - description: - 'An observer is defined as a special network, security, or application\ndevice used to detect, observe, or create network, security, or application-related\nevents and metrics.\n\nThis could be a custom hardware appliance or a server that has been configured\nto run special network, security, or application software. Examples include\nfirewalls, web proxies, intrusion detection/prevention systems, network monitoring\nsensors, web application firewalls, data loss prevention systems, and APM servers.\nThe observer.* fields shall be populated with details of the system, if any,\nthat detects, observes and/or creates a network, security, or application event\nor metric. Message queues and ETL components used in processing events or metrics\nare not considered observers in ECS.', - type: 'group', - fields: [ - { - name: 'egress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.egress holds information like interface number and name,\nvlan, and zone information to classify egress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'egress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'egress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'egress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'egress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of outbound traffic as reported by the observer to\ncategorize the destination area of egress traffic, e.g. Internal, External,\nDMZ, HR, Legal, etc.', - example: 'Public_Internet', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hostname of the observer.', - }, - { - name: 'ingress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.ingress holds information like interface number and name,\nvlan, and zone information to classify ingress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'ingress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'ingress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'ingress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'ingress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of incoming traffic as reported by the observer to\ncategorize the source area of ingress traffic. e.g. internal, External, DMZ,\nHR, Legal, etc.', - example: 'DMZ', - default_field: false, - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP addresses of the observer.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC addresses of the observer', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the observer.\n\nThis is a name that can be given to an observer. This can be helpful for example\nif multiple firewalls of the same model are used in an organization.\n\nIf no custom name is needed, the field can be left empty.', - example: '1_proxySG', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The product name of the observer.', - example: 's200', - }, - { - name: 'serial_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Observer serial number.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the observer the data is coming from.\n\nThere is no predefined list of observer types. Some examples are `forwarder`,\n`firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.', - example: 'firewall', - }, - { - name: 'vendor', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Vendor name of the observer.', - example: 'Symantec', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Observer version.', - }, - ], - }, - { - name: 'organization', - title: 'Organization', - group: 2, - description: - 'The organization fields enrich data with information about the company\nor entity the data is associated with.\n\nThese fields help you arrange or filter data stored in an index by one or multiple\norganizations.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the organization.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - }, - ], - }, - { - name: 'os', - title: 'Operating System', - group: 2, - description: 'The OS fields contain information about the operating system.', - type: 'group', - fields: [ - { - name: 'family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - ], - }, - { - name: 'package', - title: 'Package', - group: 2, - description: - 'These fields contain information about an installed software package.\nIt contains general information about a package, such as name, version or size.\nIt also contains installation details, such as time or location.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package architecture.', - example: 'x86_64', - }, - { - name: 'build_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the build version of the installed\npackage.\n\nFor example use the commit SHA of a non-released package.', - example: '36f4f7e89dd61b0988b12ee000b98966867710cd', - default_field: false, - }, - { - name: 'checksum', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Checksum of the installed package for verification.', - example: '68b329da9893e34099c7d8ad5cb9c940', - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Description of the package.', - example: - 'Open source programming language to build simple/reliable/efficient\nsoftware.', - }, - { - name: 'install_scope', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Indicating how the package was installed, e.g. user-local, global.', - example: 'global', - }, - { - name: 'installed', - level: 'extended', - type: 'date', - description: 'Time when package was installed.', - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'License under which the package was released.\n\nUse a short name, e.g. the license identifier from SPDX License List where\npossible (https://spdx.org/licenses/).', - example: 'Apache License 2.0', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package name', - example: 'go', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path where the package is installed.', - example: '/usr/local/Cellar/go/1.12.9/', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Home page or reference URL of the software in this package, if\navailable.', - example: 'https://golang.org', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - format: 'string', - description: 'Package size in bytes.', - example: 62231, - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of package.\n\nThis should contain the package file type, rather than the package manager\nname. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar.', - example: 'rpm', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package version', - example: '1.12.9', - }, - ], - }, - { - name: 'pe', - title: 'PE Header', - group: 2, - description: 'These fields contain Windows Portable Executable (PE) metadata.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'CPU architecture target for the file.', - example: 'x64', - default_field: false, - }, - { - name: 'company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'imphash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of the imports in a PE file. An imphash -- or import hash\n-- can be used to fingerprint binaries even after recompilation or other code-level\ntransformations have occurred, which would change more traditional hash values.\n\nLearn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.', - example: '0c6803c4e922103c4dca5963aad36ddf', - default_field: false, - }, - { - name: 'original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'process', - title: 'Process', - group: 2, - description: - 'These fields contain information about a process.\n\nThese fields can help you correlate metrics information with a process id/name\nfrom a log message. The `process.pid` often stays in the metric itself and\nis copied to the global field for correlation.', - type: 'group', - fields: [ - { - name: 'args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.', - example: ['/usr/bin/ssh', '-l', 'user', '10.0.0.16'], - }, - { - name: 'args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - }, - { - name: 'exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - }, - { - name: 'parent.args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments.\n\nMay be filtered to protect sensitive information.', - example: ['ssh', '-l', 'user', '10.0.0.16'], - default_field: false, - }, - { - name: 'parent.args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'parent.code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'parent.code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'parent.code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'parent.command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'parent.entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'parent.executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - default_field: false, - }, - { - name: 'parent.exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'parent.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'parent.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - default_field: false, - }, - { - name: 'parent.pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - default_field: false, - }, - { - name: 'parent.pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - default_field: false, - }, - { - name: 'parent.ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - default_field: false, - }, - { - name: 'parent.start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - default_field: false, - }, - { - name: 'parent.thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - default_field: false, - }, - { - name: 'parent.thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - default_field: false, - }, - { - name: 'parent.title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - default_field: false, - }, - { - name: 'parent.uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - default_field: false, - }, - { - name: 'parent.working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - default_field: false, - }, - { - name: 'pe.architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'CPU architecture target for the file.', - example: 'x64', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.imphash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of the imports in a PE file. An imphash -- or import hash\n-- can be used to fingerprint binaries even after recompilation or other code-level\ntransformations have occurred, which would change more traditional hash values.\n\nLearn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.', - example: '0c6803c4e922103c4dca5963aad36ddf', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - }, - { - name: 'pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - }, - { - name: 'ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - }, - { - name: 'thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - }, - { - name: 'title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - }, - { - name: 'working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - }, - ], - }, - { - name: 'registry', - title: 'Registry', - group: 2, - description: 'Fields related to Windows Registry operations.', - type: 'group', - fields: [ - { - name: 'data.bytes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Original bytes written with base64 encoding.\n\nFor Windows registry operations, such as SetValueEx and RegQueryValueEx, this\ncorresponds to the data pointed by `lp_data`. This is optional but provides\nbetter recoverability and should be populated for REG_BINARY encoded values.', - example: 'ZQBuAC0AVQBTAAAAZQBuAAAAAAA=', - default_field: false, - }, - { - name: 'data.strings', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Content when writing string types.\n\nPopulated as an array when writing string data to the registry. For single\nstring registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with\none string. For sequences of string with REG_MULTI_SZ, this array will be\nvariable length. For numeric data, such as REG_DWORD and REG_QWORD, this should\nbe populated with the decimal representation (e.g `"1"`).', - example: '["C:\\rta\\red_ttp\\bin\\myapp.exe"]', - default_field: false, - }, - { - name: 'data.type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Standard registry type for encoding contents', - example: 'REG_SZ', - default_field: false, - }, - { - name: 'hive', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Abbreviated name for the hive.', - example: 'HKLM', - default_field: false, - }, - { - name: 'key', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hive-relative path of keys.', - example: - 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe', - default_field: false, - }, - { - name: 'path', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Full path, including hive, key and value', - example: - 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution\nOptions\\winword.exe\\Debugger', - default_field: false, - }, - { - name: 'value', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the value written.', - example: 'Debugger', - default_field: false, - }, - ], - }, - { - name: 'related', - title: 'Related', - group: 2, - description: - 'This field set is meant to facilitate pivoting around a piece of\ndata.\n\nSome pieces of information can be seen in many places in an ECS event. To facilitate\nsearching for them, store an array of all seen values to their corresponding\nfield in `related.`.\n\nA concrete example is IP addresses, which can be under host, observer, source,\ndestination, client, server, and network.forwarded_ip. If you append all IPs\nto `related.ip`, you can then search for a given IP trivially, no matter where\nit appeared, by querying `related.ip:192.0.2.15`.', - type: 'group', - fields: [ - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - "All the hashes seen on your event. Populating this field, then\nusing it to search for hashes can help in situations where you're unsure what\nthe hash algorithm is (and therefore which key name to search).", - default_field: false, - }, - { - name: 'ip', - level: 'extended', - type: 'ip', - description: 'All of the IPs seen on your event.', - }, - { - name: 'user', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'All the user names seen on your event.', - default_field: false, - }, - ], - }, - { - name: 'rule', - title: 'Rule', - group: 2, - description: - 'Rule fields are used to capture the specifics of any observer or\nagent rules that generate alerts or other notable events.\n\nExamples of data sources that would populate the rule fields include: network\nadmission control platforms, network or host IDS/IPS, network firewalls, web\napplication firewalls, url filters, endpoint detection and response (EDR) systems,\netc.', - type: 'group', - fields: [ - { - name: 'author', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name, organization, or pseudonym of the author or authors who created\nthe rule used to generate this event.', - example: ['Star-Lord'], - default_field: false, - }, - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A categorization value keyword used by the entity using the rule\nfor detection of this event.', - example: 'Attempted Information Leak', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The description of the rule generating the event.', - example: 'Block requests to public DNS over HTTPS / TLS protocols', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of an agent, observer,\nor other entity using the rule for detection of this event.', - example: 101, - default_field: false, - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the license under which the rule used to generate this\nevent is made available.', - example: 'Apache 2.0', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the rule or signature generating the event.', - example: 'BLOCK_DNS_over_TLS', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL to additional information about the rule used to\ngenerate this event.\n\nThe URL can point to the vendor documentation about the rule. If that is\nnot available, it can also be a link to a more general page describing this\ntype of alert.', - example: 'https://en.wikipedia.org/wiki/DNS_over_TLS', - default_field: false, - }, - { - name: 'ruleset', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the ruleset, policy, group, or parent category in which\nthe rule used to generate this event is a member.', - example: 'Standard_Protocol_Filters', - default_field: false, - }, - { - name: 'uuid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of a set or group of\nagents, observers, or other entities using the rule for detection of this\nevent.', - example: 1100110011, - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The version / revision of the rule being used for analysis.', - example: 1.1, - default_field: false, - }, - ], - }, - { - name: 'search', - title: 'Search', - group: 2, - description: - 'The Search fields describe information about a search request event:\nquery or pagination. The fields that should be used with this field set include:\n`event.action` to describe the search action (e.g. `search.query`, `search.page`,\netc.), `event.duration` to describe the duration of a search request, `@timestamp`\nto record the event original timestamp and optionally the `source` fields\nto record context information such as `user.id` or `geo`.', - type: 'group', - fields: [ - { - name: 'query.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'An opaque query identifier. This identifier needs to be unique\nto a user query, and all subsequent events (pagination, clicks) need to have\nthe same query identifier.', - example: '2dc15175-de0d-44db-86d8-8a99f41b7a11', - default_field: false, - }, - { - name: 'query.page', - level: 'extended', - type: 'long', - description: - 'For search results that support pagination, this represents the\ncurrent page being requested. Initial search requests are `1` while subsequent\npage requests are incremental.', - example: 1, - default_field: false, - }, - { - name: 'query.value', - level: 'extended', - type: 'keyword', - ignore_above: 4096, - description: - 'The query string being searched on. This field is not analyzed\nand should not be pre-processed in any way in the event (e.g. normalization\nlist lowercasing). This is useful for search use-cases that use a one- box\nstyle search interface. Other interfaces will have to rely on additional custom\nfields or labels to represent things like filters applied, extra parameters,\nuser context, etc.', - example: 'where does the rain in Spain mainly fall', - default_field: false, - }, - { - name: 'results.ids', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - "A list of opaque document IDs representing the results that were\nshown to the user. This is effectively the impression list and it's size should\nbe equal to `results.size`. This field can be empty when there are no results\nto return.", - example: ['user:82375akja9f', 'issue:2782630'], - default_field: false, - }, - { - name: 'results.size', - level: 'extended', - type: 'long', - description: - 'The size of the result set displayed to the user. This should be\nequivalent to the length of the results in `results.ids`. This is also known\nas the page size or limit.', - example: 10, - default_field: false, - }, - { - name: 'results.total', - level: 'extended', - type: 'long', - description: - 'The total number of matches for this query. This number is always\ngreater than or equal to `results.size`. This is the `hits.total` field in\nthe query response.', - example: 134509, - default_field: false, - }, - ], - }, - { - name: 'server', - title: 'Server', - group: 2, - description: - 'A Server is defined as the responder in a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the server is the receiver of the initial SYN packet(s) of the\nTCP connection. For other protocols, the server is generally the responder in\nthe network transaction. Some systems actually use the term "responder" to refer\nthe server in TCP connections. The server fields describe details about the\nsystem acting as the server in the network event. Server fields are usually\npopulated in conjunction with client fields. Server fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event server addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the server to the client.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Server domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP address of the server (IPv4 or IPv6).', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the server.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the server to the client.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the server.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered server domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'service', - title: 'Service', - group: 2, - description: - 'The service fields describe the service for or from which the data\nwas collected.\n\nThese fields help you find and correlate logs for a specific service and version.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this service (if one exists).\n\nThis id normally changes across restarts, but `service.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the running service. If the service is comprised\nof many nodes, the `service.id` should be the same for all nodes.\n\nThis id should uniquely identify the service. This makes it possible to correlate\nlogs and metrics for one specific service, no matter which particular node\nemitted the event.\n\nNote that if you need to see the events from one specific host of the service,\nyou should filter on that `host.name` or `host.id` instead.', - example: 'd37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the service data is collected from.\n\nThe name of the service is normally user given. This allows for distributed\nservices that run on multiple hosts to correlate the related instances based\non the name.\n\nIn the case of Elasticsearch the `service.name` could contain the cluster\nname. For Beats the `service.name` is by default a copy of the `service.type`\nfield if no name is specified.', - example: 'elasticsearch-metrics', - }, - { - name: 'node.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of a service node.\n\nThis allows for two nodes of the same service running on the same host to\nbe differentiated. Therefore, `service.node.name` should typically be unique\nacross nodes of a given service.\n\nIn the case of Elasticsearch, the `service.node.name` could contain the unique\nnode name within the Elasticsearch cluster. In cases where the service does not\nhave the concept of a node name, the host name or container name can be used\nto distinguish running instances that make up this service. If those do not\nprovide uniqueness (e.g. multiple instances of the service running on the\nsame host) - the node name can be manually set.', - example: 'instance-0000000016', - }, - { - name: 'state', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Current state of the service.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the service data is collected from.\n\nThe type can be used to group and correlate logs and metrics from one service\ntype.\n\nExample: If logs or metrics are collected from Elasticsearch, `service.type`\nwould be `elasticsearch`.', - example: 'elasticsearch', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Version of the service the data was collected from.\n\nThis allows to look at a data set only for a specific version of a service.', - example: '3.2.4', - }, - ], - }, - { - name: 'source', - title: 'Source', - group: 2, - description: - 'Source fields describe details about the source of a packet/event.\n\nSource fields are usually populated in conjunction with destination fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event source addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the source to the destination.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Source domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP address of the source (IPv4 or IPv6).', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the source.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of source based NAT sessions (e.g. internal client\nto internet)\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions. (e.g. internal client\nto internet)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the source to the destination.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the source.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered source domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'threat', - title: 'Threat', - group: 2, - description: - 'Fields to classify events and alerts according to a threat taxonomy\nsuch as the Mitre ATT&CK framework.\n\nThese fields are for users to classify alerts from all of their sources (e.g.\nIDS, NGFW, etc.) within a common taxonomy. The threat.tactic.* are meant to\ncapture the high level category of the threat (e.g. "impact"). The threat.technique.*\nfields are meant to capture which kind of approach is used by this detected\nthreat, to accomplish the goal (e.g. "endpoint denial of service").', - type: 'group', - fields: [ - { - name: 'framework', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the threat framework used to further categorize and classify\nthe tactic and technique of the reported threat. Framework classification\ncan be provided by detecting systems, evaluated at ingest time, or retrospectively\ntagged to events.', - example: 'MITRE ATT&CK', - }, - { - name: 'tactic.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of tactic used by this threat. You can use the Mitre ATT&CK\nMatrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'TA0040', - }, - { - name: 'tactic.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the type of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'impact', - }, - { - name: 'tactic.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'https://attack.mitre.org/tactics/TA0040/', - }, - { - name: 'technique.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'T1499', - }, - { - name: 'technique.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'The name of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'endpoint denial of service', - }, - { - name: 'technique.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of technique used by this tactic. You can use\nthe Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'https://attack.mitre.org/techniques/T1499/', - }, - ], - }, - { - name: 'tls', - title: 'TLS', - group: 2, - description: - 'Fields related to a TLS connection. These fields focus on the TLS\nprotocol itself and intentionally avoids in-depth analysis of the related x.509\ncertificate files.', - type: 'group', - fields: [ - { - name: 'cipher', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the cipher used during the current connection.', - example: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', - default_field: false, - }, - { - name: 'client.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the client. This\nis usually mutually-exclusive of `client.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'client.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the client. This is usually mutually-exclusive of `client.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'client.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'client.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'client.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the client. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'client.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the issuer of the x.509 certificate\npresented by the client.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.ja3', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies clients based on how they perform an SSL/TLS\nhandshake.', - example: 'd4e5b18d6b55c71272893221c96ba240', - default_field: false, - }, - { - name: 'client.not_after', - level: 'extended', - type: 'date', - description: - 'Date/Time indicating when client certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.not_before', - level: 'extended', - type: 'date', - description: 'Date/Time indicating when client certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.server_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Also called an SNI, this tells the server which hostname to which\nthe client is attempting to connect. When this value is available, it should\nget copied to `destination.domain`.', - example: 'www.elastic.co', - default_field: false, - }, - { - name: 'client.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the x.509 certificate presented\nby the client.', - example: 'CN=myclient, OU=Documentation Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.supported_ciphers', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Array of ciphers offered by the client during the client hello.', - example: [ - 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', - 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', - '...', - ], - default_field: false, - }, - { - name: 'curve', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the curve used for the given cipher, when applicable.', - example: 'secp256r1', - default_field: false, - }, - { - name: 'established', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if the TLS negotiation was successful and\ntransitioned to an encrypted tunnel.', - default_field: false, - }, - { - name: 'next_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'String indicating the protocol being tunneled. Per the values in\nthe IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids),\nthis string should be lower case.', - example: 'http/1.1', - default_field: false, - }, - { - name: 'resumed', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if this TLS connection was resumed from\nan existing TLS negotiation.', - default_field: false, - }, - { - name: 'server.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the server. This\nis usually mutually-exclusive of `server.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'server.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the server. This is usually mutually-exclusive of `server.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'server.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'server.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'server.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the server. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'server.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the issuer of the x.509 certificate presented by the\nserver.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'server.ja3s', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies servers based on how they perform an SSL/TLS\nhandshake.', - example: '394441ab65754e2207b1e1b457b3641d', - default_field: false, - }, - { - name: 'server.not_after', - level: 'extended', - type: 'date', - description: - 'Timestamp indicating when server certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.not_before', - level: 'extended', - type: 'date', - description: 'Timestamp indicating when server certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the x.509 certificate presented by the server.', - example: 'CN=www.mydomain.com, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Numeric part of the version parsed from the original string.', - example: '1.2', - default_field: false, - }, - { - name: 'version_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Normalized lowercase protocol name parsed from original string.', - example: 'tls', - default_field: false, - }, - ], - }, - { - name: 'tracing', - title: 'Tracing', - group: 2, - description: - 'Distributed tracing makes it possible to analyze performance throughout\na microservice architecture all in one view. This is accomplished by tracing\nall of the requests - from the initial web request in the front-end service\n- to queries made through multiple back-end services.', - type: 'group', - fields: [ - { - name: 'trace.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the trace.\n\nA trace groups multiple events like transactions that belong together. For\nexample, a user request handled by multiple inter-connected services.', - example: '4bf92f3577b34da6a3ce929d0e0e4736', - }, - { - name: 'transaction.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the transaction.\n\nA transaction is the highest level of work measured within a service, such\nas a request to a server.', - example: '00f067aa0ba902b7', - }, - ], - }, - { - name: 'url', - title: 'URL', - group: 2, - description: - 'URL fields provide support for complete or partial URLs, and supports\nthe breaking down into scheme, domain, path, and so on.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Domain of the url, such as "www.elastic.co".\n\nIn some cases a URL may refer to an IP and/or port directly, without a domain\nname. In this case, the IP address would go to the `domain` field.', - example: 'www.elastic.co', - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The field contains the file extension from the original request\nurl.\n\nThe file extension is only set if it exists, as not every url has a file extension.\n\nThe leading period must not be included. For example, the value must be "png",\nnot ".png".', - example: 'png', - }, - { - name: 'fragment', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Portion of the url after the `#`, such as "top".\n\nThe `#` is not part of the fragment.', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'If full URLs are important to your use case, they should be stored\nin `url.full`, whether this field is reconstructed or present in the event\nsource.', - example: 'https://www.elastic.co:443/search?q=elasticsearch#top', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Unmodified original url as seen in the event source.\n\nNote that in network monitoring, the observed URL may be a full URL, whereas\nin access logs, the URL is often just represented as a path.\n\nThis field is meant to represent the URL as it was observed, complete or not.', - example: - 'https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch', - }, - { - name: 'password', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Password of the request.', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path of the request, such as "/search".', - }, - { - name: 'port', - level: 'extended', - type: 'long', - format: 'string', - description: 'Port of the request, such as 443.', - example: 443, - }, - { - name: 'query', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The query field describes the query string of the request, such\nas "q=elasticsearch".\n\nThe `?` is excluded from the query string. If a URL contains no `?`, there\nis no query field. If there is a `?` but no query, the query field exists\nwith an empty string. The `exists` query can be used to differentiate between\nthe two cases.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered url domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'scheme', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Scheme of the request, such as "https".\n\nNote: The `:` is not part of the scheme.', - example: 'https', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'username', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Username of the request.', - }, - ], - }, - { - name: 'user', - title: 'User', - group: 2, - description: - 'The user fields describe information about the user that is relevant\nto the event.\n\nFields can have one entry or multiple entries. If a user has more than one id,\nprovide an array that includes all of them.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier of the user.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'user_agent', - title: 'User agent', - group: 2, - description: - 'The user_agent fields normally come from a browser request.\n\nThey often show up in web service logs coming from the parsed user agent string.', - type: 'group', - fields: [ - { - name: 'device.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the device.', - example: 'iPhone', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the user agent.', - example: 'Safari', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Unparsed user_agent string.', - example: - 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15\n(KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the user agent.', - example: 12, - }, - ], - }, - { - name: 'vlan', - title: 'VLAN', - group: 2, - description: - 'The VLAN fields are used to identify 802.1q tag(s) of a packet,\nas well as ingress and egress VLAN associations of an observer in relation to\na specific packet or connection.\n\nNetwork.vlan fields are used to record a single VLAN tag, or the outer tag in\nthe case of q-in-q encapsulations, for a packet or connection as observed, typically\nprovided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic.\n\nNetwork.inner VLAN fields are used to report inner q-in-q 802.1q tags (multiple\n802.1q encapsulations) as observed, typically provided by a network sensor (e.g.\nZeek, Wireshark) passively reporting on traffic. Network.inner VLAN fields should\nonly be used in addition to network.vlan fields to indicate q-in-q tagging.\n\nObserver.ingress and observer.egress VLAN values are used to record observer\nspecific information when observer events contain discrete ingress and egress\nVLAN information, typically provided by firewalls, routers, or load balancers.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'vulnerability', - title: 'Vulnerability', - group: 2, - description: - 'The vulnerability fields describe information about a vulnerability\nthat is relevant to an event.', - type: 'group', - fields: [ - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of system or architecture that the vulnerability affects.\nThese may be platform-specific (for example, Debian or SUSE) or general (for\nexample, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys\nvulnerability categories])\n\nThis field must be an array.', - example: '["Firewall"]', - default_field: false, - }, - { - name: 'classification', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The classification of the vulnerability scoring system. For example\n(https://www.first.org/cvss/)', - example: 'CVSS', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'The description of the vulnerability that provides additional context\nof the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common\nVulnerabilities and Exposure CVE description])', - example: 'In macOS before 2.12.6, there is a vulnerability in the RPC...', - default_field: false, - }, - { - name: 'enumeration', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of identifier used for this vulnerability. For example\n(https://cve.mitre.org/about/)', - example: 'CVE', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The identification (ID) is the number portion of a vulnerability\nentry. It includes a unique identification number for the vulnerability. For\nexample (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities\nand Exposure CVE ID]', - example: 'CVE-2019-00001', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A resource that provides additional information, context, and mitigations\nfor the identified vulnerability.', - example: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111', - default_field: false, - }, - { - name: 'report_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The report or scan identification number.', - example: 20191018.0001, - default_field: false, - }, - { - name: 'scanner.vendor', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the vulnerability scanner vendor.', - example: 'Tenable', - default_field: false, - }, - { - name: 'score.base', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nBase scores cover an assessment for exploitability metrics (attack vector,\ncomplexity, privileges, and user interaction), impact metrics (confidentiality,\nintegrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.environmental', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nEnvironmental scores cover an assessment for any modified Base metrics, confidentiality,\nintegrity, and availability requirements. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.temporal', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nTemporal scores cover an assessment for code maturity, remediation level,\nand confidence. For example (https://www.first.org/cvss/specification-document)', - default_field: false, - }, - { - name: 'score.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The National Vulnerability Database (NVD) provides qualitative\nseverity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score\nranges in addition to the severity ratings for CVSS v3.0 as they are defined\nin the CVSS v3.0 specification.\n\nCVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit\norganization, whose mission is to help computer security incident response\nteams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 2, - default_field: false, - }, - { - name: 'severity', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The severity of the vulnerability can help with metrics and internal\nprioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 'Critical', - default_field: false, - }, - ], - }, - ], - }, -]; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/filebeat.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/filebeat.ts deleted file mode 100644 index 3b8c92ebba2694..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/filebeat.ts +++ /dev/null @@ -1,21243 +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. - */ - -/** - * An instance of the unmodified schema exported from filebeat-8.0.0-SNAPSHOT-darwin-x86_64.tar.gz - * - */ - -import { Schema } from '../type'; - -export const filebeatSchema: Schema = [ - { - key: 'ecs', - title: 'ECS', - description: 'ECS Fields.', - fields: [ - { - name: '@timestamp', - level: 'core', - required: true, - type: 'date', - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'labels', - level: 'core', - type: 'object', - object_type: 'keyword', - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - }, - { - name: 'tags', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - }, - { - name: 'agent', - title: 'Agent', - group: 2, - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - footnote: - 'Examples: In the case of Beats for logs, the agent.name is filebeat.\nFor APM, it is the agent running in the app/service. The agent information does\nnot change if data is sent through queuing systems like Kafka, Redis, or processing\nsystems such as Logstash or APM Server.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the agent.', - example: '6.0.0-rc2', - }, - ], - }, - { - name: 'as', - title: 'Autonomous System', - group: 2, - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - type: 'group', - fields: [ - { - name: 'number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - ], - }, - { - name: 'client', - title: 'Client', - group: 2, - description: - 'A client is defined as the initiator of a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the client is the initiator of the TCP connection that sends\nthe SYN packet(s). For other protocols, the client is generally the initiator\nor requestor in the network transaction. Some systems use the term "originator"\nto refer the client in TCP connections. The client fields describe details about\nthe system acting as the client in the network event. Client fields are usually\npopulated in conjunction with server fields. Client fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event client addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the client to the server.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Client domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the client.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the client.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated IP of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the client to the server.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the client.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered client domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'cloud', - title: 'Cloud', - group: 2, - description: 'Fields related to the cloud or infrastructure the events are coming\nfrom.', - footnote: - 'Examples: If Metricbeat is running on an EC2 host and fetches data\nfrom its host, the cloud info contains the data about this machine. If Metricbeat\nruns on a remote machine outside the cloud and fetches data from a service running\nin the cloud, the field contains cloud data from the machine the service is\nrunning on.', - type: 'group', - fields: [ - { - name: 'account.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The cloud account or organization id used to identify different\nentities in a multi-tenant environment.\n\nExamples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: 666777888999, - }, - { - name: 'availability_zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - }, - { - name: 'instance.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance ID of the host machine.', - example: 'i-1234567890abcdef0', - }, - { - name: 'instance.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance name of the host machine.', - }, - { - name: 'machine.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Machine type of the host machine.', - example: 't2.medium', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the cloud provider. Example values are aws, azure, gcp,\nor digitalocean.', - example: 'aws', - }, - { - name: 'region', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Region in which this host is running.', - example: 'us-east-1', - }, - ], - }, - { - name: 'code_signature', - title: 'Code Signature', - group: 2, - description: 'These fields contain information about binary code signatures.', - type: 'group', - fields: [ - { - name: 'exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - ], - }, - { - name: 'container', - title: 'Container', - group: 2, - description: - 'Container fields are used for meta information about the specific\ncontainer that is the source of information.\n\nThese fields help correlate data based containers from any runtime.', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique container id.', - }, - { - name: 'image.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the image the container was built on.', - }, - { - name: 'image.tag', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container image tags.', - }, - { - name: 'labels', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: 'Image labels.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container name.', - }, - { - name: 'runtime', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Runtime managing this container.', - example: 'docker', - }, - ], - }, - { - name: 'destination', - title: 'Destination', - group: 2, - description: - 'Destination fields describe details about the destination of a packet/event.\n\nDestination fields are usually populated in conjunction with source fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event destination addresses are defined ambiguously. The\nevent will sometimes list an IP, a domain or a unix socket. You should always\nstore the raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the destination to the source.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Destination domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the destination.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the destination.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Port the source session is translated to by NAT Device.\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the destination to the source.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the destination.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered destination domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'dll', - title: 'DLL', - group: 2, - description: - 'These fields contain information about code libraries dynamically\nloaded into processes.\n\n\nMany operating systems refer to "shared code libraries" with different names,\nbut this field set refers to all of the following:\n\n* Dynamic-link library (`.dll`) commonly used on Windows\n\n* Shared Object (`.so`) commonly used on Unix-like operating systems\n\n* Dynamic library (`.dylib`) commonly used on macOS', - type: 'group', - fields: [ - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the library.\n\nThis generally maps to the name of the file on disk.', - example: 'kernel32.dll', - default_field: false, - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Full file path of the library.', - example: 'C:\\Windows\\System32\\kernel32.dll', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'dns', - title: 'DNS', - group: 2, - description: - 'Fields describing DNS queries and answers.\n\nDNS events should either represent a single DNS query prior to getting answers\n(`dns.type:query`) or they should represent a full exchange and contain the\nquery details as well as all of the answers that were provided for this query\n(`dns.type:answer`).', - type: 'group', - fields: [ - { - name: 'answers', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'An array containing an object for each answer section returned\nby the server.\n\nThe main keys that should be present in these objects are defined by ECS.\nRecords that have more information may contain more keys than what ECS defines.\n\nNot all DNS data sources give all details about DNS answers. At minimum, answer\nobjects must contain the `data` key. If more information is available, map\nas much of it to ECS as possible, and add any additional fields to the answer\nobjects as custom fields.', - }, - { - name: 'answers.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of DNS data contained in this resource record.', - example: 'IN', - }, - { - name: 'answers.data', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The data describing the resource.\n\nThe meaning of this data depends on the type and class of the resource record.', - example: '10.10.10.10', - }, - { - name: 'answers.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The domain name to which this resource record pertains.\n\nIf a chain of CNAME is being resolved, each answer `name` should be the\none that corresponds with the answer `data`. It should not simply be the\noriginal `question.name` repeated.', - example: 'www.google.com', - }, - { - name: 'answers.ttl', - level: 'extended', - type: 'long', - description: - 'The time interval in seconds that this resource record may be cached\nbefore it should be discarded. Zero values mean that the data should not be\ncached.', - example: 180, - }, - { - name: 'answers.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of data contained in this resource record.', - example: 'CNAME', - }, - { - name: 'header_flags', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of 2 letter DNS header flags.\n\nExpected values are: AA, TC, RD, RA, AD, CD, DO.', - example: ['RD', 'RA'], - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS packet identifier assigned by the program that generated\nthe query. The identifier is copied to the response.', - example: 62111, - }, - { - name: 'op_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS operation code that specifies the kind of query in the\nmessage. This value is set by the originator of a query and copied into the\nresponse.', - example: 'QUERY', - }, - { - name: 'question.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of records being queried.', - example: 'IN', - }, - { - name: 'question.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name being queried.\n\nIf the name field contains non-printable characters (below 32 or above 126),\nthose characters should be represented as escaped base 10 integers (\\DDD).\nBack slashes and quotes should be escaped. Tabs, carriage returns, and line\nfeeds should be converted to \\t, \\r, and \\n respectively.', - example: 'www.google.com', - }, - { - name: 'question.registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'question.subdomain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The subdomain is all of the labels under the registered_domain.\n\nIf the domain has multiple levels of subdomain, such as "sub2.sub1.example.com",\nthe subdomain field should contain "sub2.sub1", with no trailing period.', - example: 'www', - }, - { - name: 'question.top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'question.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of record being queried.', - example: 'AAAA', - }, - { - name: 'resolved_ip', - level: 'extended', - type: 'ip', - description: - 'Array containing all IPs seen in `answers.data`.\n\nThe `answers` array can be difficult to use, because of the variety of data\nformats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip`\nmakes it possible to index them as IP addresses, and makes them easier to\nvisualize and query for.', - example: ['10.10.10.10', '10.10.10.11'], - }, - { - name: 'response_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The DNS response code.', - example: 'NOERROR', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of DNS event captured, query or answer.\n\nIf your source of DNS events only gives you DNS queries, you should only create\ndns events of type `dns.type:query`.\n\nIf your source of DNS events gives you answers as well, you should create\none event per query (optionally as soon as the query is seen). And a second\nevent containing all query details as well as an array of answers.', - example: 'answer', - }, - ], - }, - { - name: 'ecs', - title: 'ECS', - group: 2, - description: 'Meta-information specific to ECS.', - type: 'group', - fields: [ - { - name: 'version', - level: 'core', - required: true, - type: 'keyword', - ignore_above: 1024, - description: - 'ECS version this event conforms to. `ecs.version` is a required\nfield and must exist in all events.\n\nWhen querying across multiple indices -- which may conform to slightly different\nECS versions -- this field lets integrations adjust to the schema version\nof the events.', - example: '1.0.0', - }, - ], - }, - { - name: 'error', - title: 'Error', - group: 2, - description: - 'These fields can represent errors of any kind.\n\nUse them for errors that happen while fetching events or in cases where the\nevent itself contains an error.', - type: 'group', - fields: [ - { - name: 'code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Error code describing the error.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the error.', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: 'Error message.', - }, - { - name: 'stack_trace', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The stack trace of this error in plain text.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of the error, for example the class name of the exception.', - example: 'java.lang.NullPointerException', - }, - ], - }, - { - name: 'event', - title: 'Event', - group: 2, - description: - 'The event fields are used for context information about the log\nor metric event itself.\n\nA log is defined as an event containing details of something that happened.\nLog events must include the time at which the thing happened. Examples of log\nevents include a process starting on a host, a network packet being sent from\na source to a destination, or a network connection between a client and a server\nbeing initiated or closed. A metric is defined as an event containing one or\nmore numerical measurements and the time at which the measurement was taken.\nExamples of metric events include memory pressure measured on a host and device\ntemperature. See the `event.kind` definition in this section for additional\ndetails about metric and state events.', - type: 'group', - fields: [ - { - name: 'action', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.', - example: 'user-password-change', - }, - { - name: 'category', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nsecond level in the ECS category hierarchy.\n\n`event.category` represents the "big buckets" of ECS categories. For example,\nfiltering on `event.category:process` yields all events relating to process\nactivity. This field is closely related to `event.type`, which is used as\na subcategory.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple categories.', - example: 'authentication', - }, - { - name: 'code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Identification code for this event, if one exists.\n\nSome event sources use event codes to identify messages unambiguously, regardless\nof message language or wording adjustments over time. An example of this is\nthe Windows Event ID.', - example: 4648, - }, - { - name: 'created', - level: 'core', - type: 'date', - description: - 'event.created contains the date/time when the event was first\nread by an agent, or by your pipeline.\n\nThis field is distinct from @timestamp in that @timestamp typically contain\nthe time extracted from the original event.\n\nIn most situations, these two timestamps will be slightly different. The difference\ncan be used to calculate the delay between your source generating an event,\nand the time when your agent first processed it. This can be used to monitor\nyour agent or pipeline ability to keep up with your event source.\n\nIn case the two timestamps are identical, @timestamp should be used.', - example: '2016-05-23T08:05:34.857Z', - }, - { - name: 'dataset', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the dataset.\n\nIf an event source publishes more than one type of log or events (e.g. access\nlog, error log), the dataset is used to specify which one the event comes\nfrom.\n\nIt is recommended but not required to start the dataset name with the module\nname, followed by a dot, then the dataset name.', - example: 'apache.access', - }, - { - name: 'duration', - level: 'core', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - output_format: 'asMilliseconds', - output_precision: 1, - description: - 'Duration of the event in nanoseconds.\n\nIf event.start and event.end are known this value should be the difference\nbetween the end and start time.', - }, - { - name: 'end', - level: 'extended', - type: 'date', - description: - 'event.end contains the date when the event ended or when the activity\nwas last observed.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Hash (perhaps logstash fingerprint) of raw field to be able to\ndemonstrate log integrity.', - example: '123456789012345678901234567890ABCD', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique ID to describe the event.', - example: '8a4f500d', - }, - { - name: 'ingested', - level: 'core', - type: 'date', - description: - 'Timestamp when an event arrived in the central data store.\n\nThis is different from `@timestamp`, which is when the event originally occurred. It is\nalso different from `event.created`, which is meant to capture the first time\nan agent saw the event.\n\nIn normal conditions, assuming no tampering, the timestamps should chronologically\nlook like this: `@timestamp` < `event.created` < `event.ingested`.', - example: '2016-05-23T08:05:35.101Z', - default_field: false, - }, - { - name: 'kind', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nhighest level in the ECS category hierarchy.\n\n`event.kind` gives high-level information about what type of information the\nevent contains, without being specific to the contents of the event. For example,\nvalues of this field distinguish alert events from metric events.\n\nThe value of this field can be used to inform how these kinds of events should\nbe handled. They may warrant different retention, different access control,\nit may also help understand whether the data coming in at a regular interval\nor not.', - example: 'alert', - }, - { - name: 'module', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the module this data is coming from.\n\nIf your monitoring agent supports the concept of modules or plugins to process\nevents of a given source (e.g. Apache logs), `event.module` should contain\nthe name of this module.', - example: 'apache', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Raw text message of entire event. Used to demonstrate log integrity.\n\nThis field is not indexed and doc_values are disabled. It cannot be searched,\nbut it can be retrieved from `_source`.', - example: - 'Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100|\nworm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232', - }, - { - name: 'outcome', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nlowest level in the ECS category hierarchy.\n\n`event.outcome` simply denotes whether the event represents a success or a\nfailure from the perspective of the entity that produced the event.\n\nNote that when a single transaction is described in multiple events, each\nevent may populate different values of `event.outcome`, according to their\nperspective.\n\nAlso note that in the case of a compound event (a single event that contains\nmultiple logical events), this field should be populated with the value that\nbest captures the overall success or failure from the perspective of the event\nproducer.\n\nFurther note that not all events will have an associated outcome. For example,\nthis field is generally not populated for metric events, events with `event.type:info`,\nor any events for which an outcome does not make logical sense.', - example: 'success', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Source of the event.\n\nEvent transports such as Syslog or the Windows Event Log typically mention\nthe source of an event. It can be the name of the software that generated\nthe event (e.g. Sysmon, httpd), or of a subsystem of the operating system\n(kernel, Microsoft-Windows-Security-Auditing).', - example: 'kernel', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL linking to additional information about this event.\n\nThis URL links to a static definition of the this event. Alert events, indicated\nby `event.kind:alert`, are a common use case for this field.', - example: 'https://system.vendor.com/event/#0001234', - default_field: false, - }, - { - name: 'risk_score', - level: 'core', - type: 'float', - description: - "Risk score or priority of the event (e.g. security solutions).\nUse your system's original value here.", - }, - { - name: 'risk_score_norm', - level: 'extended', - type: 'float', - description: - 'Normalized risk score or priority of the event, on a scale of\n0 to 100.\n\nThis is mainly useful if you use more than one system that assigns risk scores,\nand you want to see a normalized value across all systems.', - }, - { - name: 'sequence', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Sequence number of the event.\n\nThe sequence number is a value published by some event sources, to make the\nexact ordering of events unambiguous, regardless of the timestamp precision.', - }, - { - name: 'severity', - level: 'core', - type: 'long', - format: 'string', - description: - 'The numeric severity of the event according to your event source.\n\nWhat the different severity values mean can be different between sources and\nuse cases. It is up to the implementer to make sure severities are consistent\nacross events from the same source.\n\nThe Syslog severity belongs in `log.syslog.severity.code`. `event.severity`\nis meant to represent the severity according to the event source (e.g. firewall,\nIDS). If the event source does not publish its own severity, you may optionally\ncopy the `log.syslog.severity.code` to `event.severity`.', - example: 7, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: - 'event.start contains the date when the event started or when the\nactivity was first observed.', - }, - { - name: 'timezone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'This field should be populated when the event timestamp does\nnot include timezone information already (e.g. default Syslog timestamps).\nIt is optional otherwise.\n\nAcceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"),\nabbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nthird level in the ECS category hierarchy.\n\n`event.type` represents a categorization "sub-bucket" that, when used along\nwith the `event.category` field values, enables filtering events down to a\nlevel appropriate for single visualization.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple event types.', - }, - { - name: 'url', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'URL linking to an external system to continue investigation of\nthis event.\n\nThis URL links to another system where in-depth investigation of the specific\noccurence of this event can take place. Alert events, indicated by `event.kind:alert`,\nare a common use case for this field.', - example: 'https://mysystem.mydomain.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe', - default_field: false, - }, - ], - }, - { - name: 'file', - title: 'File', - group: 2, - description: - 'A file is defined as a set of information that has been created\non, or has existed on a filesystem.\n\nFile objects can be associated with host events, network events, and/or file\nevents (e.g., those produced by File Integrity Monitoring [FIM] products or\nservices). File fields provide details about the affected file associated with\nthe event or metric.', - type: 'group', - fields: [ - { - name: 'accessed', - level: 'extended', - type: 'date', - description: - 'Last time the file was accessed.\n\nNote that not all filesystems keep track of access time.', - }, - { - name: 'attributes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of file attributes.\n\nAttributes names will vary by platform. Here is a non-exhaustive list of values\nthat are expected in this field: archive, compressed, directory, encrypted,\nexecute, hidden, read, readonly, system, write.', - example: '["readonly", "system"]', - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'created', - level: 'extended', - type: 'date', - description: - 'File creation time.\n\nNote that not all filesystems store the creation time.', - }, - { - name: 'ctime', - level: 'extended', - type: 'date', - description: - 'Last time the file attributes or metadata changed.\n\nNote that changes to the file content will update `mtime`. This implies `ctime`\nwill be adjusted at the same time, since `mtime` is an attribute of the file.', - }, - { - name: 'device', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Device that is the source of the file.', - example: 'sda', - }, - { - name: 'directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Directory where the file is located. It should include the drive\nletter, when appropriate.', - example: '/home/alice', - }, - { - name: 'drive_letter', - level: 'extended', - type: 'keyword', - ignore_above: 1, - description: - 'Drive letter where the file is located. This field is only relevant\non Windows.\n\nThe value should be uppercase, and not include the colon.', - example: 'C', - default_field: false, - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File extension.', - example: 'png', - }, - { - name: 'gid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group ID (GID) of the file.', - example: '1001', - }, - { - name: 'group', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group name of the file.', - example: 'alice', - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'inode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Inode representing the file in the filesystem.', - example: '256383', - }, - { - name: 'mime_type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'MIME type should identify the format of the file or stream of bytes\nusing https://www.iana.org/assignments/media-types/media-types.xhtml[IANA\nofficial types], where possible. When more than one type is applicable, the\nmost specific type should be used.', - default_field: false, - }, - { - name: 'mode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Mode of the file in octal representation.', - example: '0640', - }, - { - name: 'mtime', - level: 'extended', - type: 'date', - description: 'Last time the file content was modified.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the file including the extension, without the directory.', - example: 'example.png', - }, - { - name: 'owner', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: "File owner's username.", - example: 'alice', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Full path to the file, including the file name. It should include\nthe drive letter, when appropriate.', - example: '/home/alice/example.png', - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - description: 'File size in bytes.\n\nOnly relevant when `file.type` is "file".', - example: 16384, - }, - { - name: 'target_path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Target path for symlinks.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File type (file, dir, or symlink).', - example: 'file', - }, - { - name: 'uid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The user ID (UID) or security identifier (SID) of the file owner.', - example: '1001', - }, - ], - }, - { - name: 'geo', - title: 'Geo', - group: 2, - description: - 'Geo fields can carry data about a specific location related to an\nevent.\n\nThis geolocation information can be derived from techniques such as Geo IP,\nor be user-supplied.', - type: 'group', - fields: [ - { - name: 'city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - ], - }, - { - name: 'group', - title: 'Group', - group: 2, - description: - 'The group fields are meant to represent groups that are relevant\nto the event.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - ], - }, - { - name: 'hash', - title: 'Hash', - group: 2, - description: - 'The hash fields represent different hash algorithms and their values.\n\nField names for common hashes (e.g. MD5, SHA1) are predefined. Add fields for\nother hashes by lowercasing the hash algorithm name and using underscore separators\nas appropriate (snake case, e.g. sha3_512).', - type: 'group', - fields: [ - { - name: 'md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - ], - }, - { - name: 'host', - title: 'Host', - group: 2, - description: - 'A host is defined as a general computing instance.\n\nECS host.* fields should be populated with details about the host on which the\nevent happened, or from which the measurement was taken. Host types include\nhardware, virtual machines, Docker containers, and Kubernetes nodes.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system architecture.', - example: 'x86_64', - }, - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the domain of which the host is a member.\n\nFor example, on Windows this could be the host Active Directory domain\nor NetBIOS domain name. For Linux this could be the domain of the host\nLDAP provider.', - example: 'CONTOSO', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Hostname of the host.\n\nIt normally contains what the `hostname` command returns on the host machine.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique host id.\n\nAs hostname is not always unique, use values that are meaningful in your environment.\n\nExample: The current usage of `beat.name`.', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'Host ip addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Host mac addresses.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of host.\n\nFor Cloud providers this can be the machine type like `t2.medium`. If vm,\nthis could be the container, for example, or other information meaningful\nin your environment.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the host has been up.', - example: 1325, - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'http', - title: 'HTTP', - group: 2, - description: - 'Fields related to HTTP activity. Use the `url` field set to store\nthe url of the request.', - type: 'group', - fields: [ - { - name: 'request.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the request body.', - example: 887, - }, - { - name: 'request.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP request body.', - example: 'Hello world', - }, - { - name: 'request.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the request (body and headers).', - example: 1437, - }, - { - name: 'request.method', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'HTTP request method.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'get, post, put', - }, - { - name: 'request.referrer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Referrer for this HTTP request.', - example: 'https://blog.example.com/', - }, - { - name: 'response.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the response body.', - example: 887, - }, - { - name: 'response.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP response body.', - example: 'Hello world', - }, - { - name: 'response.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the response (body and headers).', - example: 1437, - }, - { - name: 'response.status_code', - level: 'extended', - type: 'long', - format: 'string', - description: 'HTTP response status code.', - example: 404, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'HTTP version.', - example: 1.1, - }, - ], - }, - { - name: 'interface', - title: 'Interface', - group: 2, - description: - 'The interface fields are used to record ingress and egress interface\ninformation when reported by an observer (e.g. firewall, router, load balancer)\nin the context of the observer handling a network connection. In the case of\na single observer interface (e.g. network sensor on a span port) only the observer.ingress\ninformation should be populated.', - type: 'group', - fields: [ - { - name: 'alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - ], - }, - { - name: 'log', - title: 'Log', - group: 2, - description: - 'Details about the event logging mechanism or logging transport.\n\nThe log.* fields are typically populated with details about the logging mechanism\nused to create and/or transport the event. For example, syslog details belong\nunder `log.syslog.*`.\n\nThe details specific to your event source are typically not logged under `log.*`,\nbut rather in `event.*` or in other ECS fields.', - type: 'group', - fields: [ - { - name: 'level', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Original log level of the log event.\n\nIf the source of the event provides a log level or textual severity, this\nis the one that goes in `log.level`. If your source does not specify one,\nyou may put your event transport severity here (e.g. Syslog severity).\n\nSome examples are `warn`, `err`, `i`, `informational`.', - example: 'error', - }, - { - name: 'logger', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the logger inside an application. This is usually the\nname of the class which initialized the logger, or can be a custom name.', - example: 'org.elasticsearch.bootstrap.Bootstrap', - }, - { - name: 'origin.file.line', - level: 'extended', - type: 'integer', - description: - 'The line number of the file containing the source code which originated\nthe log event.', - example: 42, - }, - { - name: 'origin.file.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the file containing the source code which originated\nthe log event. Note that this is not the name of the log file.', - example: 'Bootstrap.java', - }, - { - name: 'origin.function', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the function or method which originated the log event.', - example: 'init', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is the original log message and contains the full log message\nbefore splitting it up in multiple parts.\n\nIn contrast to the `message` field which can contain an extracted part of\nthe log message, this field contains the original, full log message. It can\nhave already some modifications applied like encoding or new lines removed\nto clean up the log message.\n\nThis field is not indexed and doc_values are disabled so it cannot be queried\nbut the value can be retrieved from `_source`.', - example: 'Sep 19 08:26:10 localhost My log', - }, - { - name: 'syslog', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'The Syslog metadata of the event, if the event was transmitted\nvia Syslog. Please see RFCs 5424 or 3164.', - }, - { - name: 'syslog.facility.code', - level: 'extended', - type: 'long', - format: 'string', - description: - 'The Syslog numeric facility of the log event, if available.\n\nAccording to RFCs 5424 and 3164, this value should be an integer between 0\nand 23.', - example: 23, - }, - { - name: 'syslog.facility.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The Syslog text-based facility of the log event, if available.', - example: 'local7', - }, - { - name: 'syslog.priority', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Syslog numeric priority of the event, if available.\n\nAccording to RFCs 5424 and 3164, the priority is 8 * facility + severity.\nThis number is therefore expected to contain a value between 0 and 191.', - example: 135, - }, - { - name: 'syslog.severity.code', - level: 'extended', - type: 'long', - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different numeric severity\nvalue (e.g. firewall, IDS), your source numeric severity should go to `event.severity`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `event.severity`.', - example: 3, - }, - { - name: 'syslog.severity.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different severity value\n(e.g. firewall, IDS), your source text severity should go to `log.level`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `log.level`.', - example: 'Error', - }, - ], - }, - { - name: 'network', - title: 'Network', - group: 2, - description: - 'The network is defined as the communication path over which a host\nor network event happens.\n\nThe network.* fields should be populated with details about the network activity\nassociated with an event.', - type: 'group', - fields: [ - { - name: 'application', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A name given to an application level protocol. This can be arbitrarily\nassigned for things like microservices, but also apply to things like skype,\nicq, facebook, twitter. This would be used in situations where the vendor\nor service can be decoded such as from the source/dest IP owners, ports, or\nwire format.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'aim', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: - 'Total bytes transferred in both directions.\n\nIf `source.bytes` and `destination.bytes` are known, `network.bytes` is their\nsum.', - example: 368, - }, - { - name: 'community_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of source and destination IPs and ports, as well as the\nprotocol used in a communication. This is a tool-agnostic standard to identify\nflows.\n\nLearn more at https://github.com/corelight/community-id-spec.', - example: '1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=', - }, - { - name: 'direction', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - "Direction of the network traffic.\nRecommended values are:\n * inbound\n * outbound\n * internal\n * external\n * unknown\n\nWhen mapping events from a host-based monitoring context, populate this field from the host's point of view.\nWhen mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of your network perimeter.", - example: 'inbound', - }, - { - name: 'forwarded_ip', - level: 'core', - type: 'ip', - description: 'Host IP address when the source IP address is the proxy.', - example: '192.1.1.2', - }, - { - name: 'iana_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).\nStandardized list of protocols. This aligns well with NetFlow and sFlow related\nlogs which use the IANA Protocol Number.', - example: 6, - }, - { - name: 'inner', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Network.inner fields are added in addition to network.vlan fields\nto describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed\nfields include vlan.id and vlan.name. Inner vlan fields are typically used\nwhen sending traffic with multiple 802.1q encapsulations to a network sensor\n(e.g. Zeek, Wireshark.)', - default_field: false, - }, - { - name: 'inner.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'inner.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name given by operators to sections of their network.', - example: 'Guest Wifi', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: - 'Total packets transferred in both directions.\n\nIf `source.packets` and `destination.packets` are known, `network.packets`\nis their sum.', - example: 24, - }, - { - name: 'protocol', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'L7 Network protocol name. ex. http, lumberjack, transport protocol.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'http', - }, - { - name: 'transport', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Same as network.iana_number, but instead using the Keyword name\nof the transport layer (udp, tcp, ipv6-icmp, etc.)\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'tcp', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'In the OSI Model this would be the Network Layer. ipv4, ipv6,\nipsec, pim, etc\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'ipv4', - }, - { - name: 'vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'observer', - title: 'Observer', - group: 2, - description: - 'An observer is defined as a special network, security, or application\ndevice used to detect, observe, or create network, security, or application-related\nevents and metrics.\n\nThis could be a custom hardware appliance or a server that has been configured\nto run special network, security, or application software. Examples include\nfirewalls, web proxies, intrusion detection/prevention systems, network monitoring\nsensors, web application firewalls, data loss prevention systems, and APM servers.\nThe observer.* fields shall be populated with details of the system, if any,\nthat detects, observes and/or creates a network, security, or application event\nor metric. Message queues and ETL components used in processing events or metrics\nare not considered observers in ECS.', - type: 'group', - fields: [ - { - name: 'egress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.egress holds information like interface number and name,\nvlan, and zone information to classify egress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'egress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'egress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'egress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'egress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of outbound traffic as reported by the observer to\ncategorize the destination area of egress traffic, e.g. Internal, External,\nDMZ, HR, Legal, etc.', - example: 'Public_Internet', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hostname of the observer.', - }, - { - name: 'ingress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.ingress holds information like interface number and name,\nvlan, and zone information to classify ingress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'ingress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'ingress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'ingress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'ingress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of incoming traffic as reported by the observer to\ncategorize the source area of ingress traffic. e.g. internal, External, DMZ,\nHR, Legal, etc.', - example: 'DMZ', - default_field: false, - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP addresses of the observer.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC addresses of the observer', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the observer.\n\nThis is a name that can be given to an observer. This can be helpful for example\nif multiple firewalls of the same model are used in an organization.\n\nIf no custom name is needed, the field can be left empty.', - example: '1_proxySG', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The product name of the observer.', - example: 's200', - }, - { - name: 'serial_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Observer serial number.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the observer the data is coming from.\n\nThere is no predefined list of observer types. Some examples are `forwarder`,\n`firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.', - example: 'firewall', - }, - { - name: 'vendor', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Vendor name of the observer.', - example: 'Symantec', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Observer version.', - }, - ], - }, - { - name: 'organization', - title: 'Organization', - group: 2, - description: - 'The organization fields enrich data with information about the company\nor entity the data is associated with.\n\nThese fields help you arrange or filter data stored in an index by one or multiple\norganizations.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the organization.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - }, - ], - }, - { - name: 'os', - title: 'Operating System', - group: 2, - description: 'The OS fields contain information about the operating system.', - type: 'group', - fields: [ - { - name: 'family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - ], - }, - { - name: 'package', - title: 'Package', - group: 2, - description: - 'These fields contain information about an installed software package.\nIt contains general information about a package, such as name, version or size.\nIt also contains installation details, such as time or location.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package architecture.', - example: 'x86_64', - }, - { - name: 'build_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the build version of the installed\npackage.\n\nFor example use the commit SHA of a non-released package.', - example: '36f4f7e89dd61b0988b12ee000b98966867710cd', - default_field: false, - }, - { - name: 'checksum', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Checksum of the installed package for verification.', - example: '68b329da9893e34099c7d8ad5cb9c940', - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Description of the package.', - example: - 'Open source programming language to build simple/reliable/efficient\nsoftware.', - }, - { - name: 'install_scope', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Indicating how the package was installed, e.g. user-local, global.', - example: 'global', - }, - { - name: 'installed', - level: 'extended', - type: 'date', - description: 'Time when package was installed.', - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'License under which the package was released.\n\nUse a short name, e.g. the license identifier from SPDX License List where\npossible (https://spdx.org/licenses/).', - example: 'Apache License 2.0', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package name', - example: 'go', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path where the package is installed.', - example: '/usr/local/Cellar/go/1.12.9/', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Home page or reference URL of the software in this package, if\navailable.', - example: 'https://golang.org', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - format: 'string', - description: 'Package size in bytes.', - example: 62231, - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of package.\n\nThis should contain the package file type, rather than the package manager\nname. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar.', - example: 'rpm', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package version', - example: '1.12.9', - }, - ], - }, - { - name: 'pe', - title: 'PE Header', - group: 2, - description: 'These fields contain Windows Portable Executable (PE) metadata.', - type: 'group', - fields: [ - { - name: 'company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'process', - title: 'Process', - group: 2, - description: - 'These fields contain information about a process.\n\nThese fields can help you correlate metrics information with a process id/name\nfrom a log message. The `process.pid` often stays in the metric itself and\nis copied to the global field for correlation.', - type: 'group', - fields: [ - { - name: 'args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.', - example: ['/usr/bin/ssh', '-l', 'user', '10.0.0.16'], - }, - { - name: 'args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - }, - { - name: 'exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - }, - { - name: 'parent.args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments.\n\nMay be filtered to protect sensitive information.', - example: ['ssh', '-l', 'user', '10.0.0.16'], - default_field: false, - }, - { - name: 'parent.args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'parent.code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'parent.code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'parent.code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'parent.command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'parent.entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'parent.executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - default_field: false, - }, - { - name: 'parent.exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'parent.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'parent.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - default_field: false, - }, - { - name: 'parent.pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - default_field: false, - }, - { - name: 'parent.pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - default_field: false, - }, - { - name: 'parent.ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - default_field: false, - }, - { - name: 'parent.start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - default_field: false, - }, - { - name: 'parent.thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - default_field: false, - }, - { - name: 'parent.thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - default_field: false, - }, - { - name: 'parent.title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - default_field: false, - }, - { - name: 'parent.uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - default_field: false, - }, - { - name: 'parent.working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - }, - { - name: 'pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - }, - { - name: 'ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - }, - { - name: 'thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - }, - { - name: 'title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - }, - { - name: 'working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - }, - ], - }, - { - name: 'registry', - title: 'Registry', - group: 2, - description: 'Fields related to Windows Registry operations.', - type: 'group', - fields: [ - { - name: 'data.bytes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Original bytes written with base64 encoding.\n\nFor Windows registry operations, such as SetValueEx and RegQueryValueEx, this\ncorresponds to the data pointed by `lp_data`. This is optional but provides\nbetter recoverability and should be populated for REG_BINARY encoded values.', - example: 'ZQBuAC0AVQBTAAAAZQBuAAAAAAA=', - default_field: false, - }, - { - name: 'data.strings', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Content when writing string types.\n\nPopulated as an array when writing string data to the registry. For single\nstring registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with\none string. For sequences of string with REG_MULTI_SZ, this array will be\nvariable length. For numeric data, such as REG_DWORD and REG_QWORD, this should\nbe populated with the decimal representation (e.g `"1"`).', - example: '["C:\\rta\\red_ttp\\bin\\myapp.exe"]', - default_field: false, - }, - { - name: 'data.type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Standard registry type for encoding contents', - example: 'REG_SZ', - default_field: false, - }, - { - name: 'hive', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Abbreviated name for the hive.', - example: 'HKLM', - default_field: false, - }, - { - name: 'key', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hive-relative path of keys.', - example: - 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe', - default_field: false, - }, - { - name: 'path', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Full path, including hive, key and value', - example: - 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution\nOptions\\winword.exe\\Debugger', - default_field: false, - }, - { - name: 'value', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the value written.', - example: 'Debugger', - default_field: false, - }, - ], - }, - { - name: 'related', - title: 'Related', - group: 2, - description: - 'This field set is meant to facilitate pivoting around a piece of\ndata.\n\nSome pieces of information can be seen in many places in an ECS event. To facilitate\nsearching for them, store an array of all seen values to their corresponding\nfield in `related.`.\n\nA concrete example is IP addresses, which can be under host, observer, source,\ndestination, client, server, and network.forwarded_ip. If you append all IPs\nto `related.ip`, you can then search for a given IP trivially, no matter where\nit appeared, by querying `related.ip:192.0.2.15`.', - type: 'group', - fields: [ - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - "All the hashes seen on your event. Populating this field, then\nusing it to search for hashes can help in situations where you're unsure what\nthe hash algorithm is (and therefore which key name to search).", - default_field: false, - }, - { - name: 'ip', - level: 'extended', - type: 'ip', - description: 'All of the IPs seen on your event.', - }, - { - name: 'user', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'All the user names seen on your event.', - default_field: false, - }, - ], - }, - { - name: 'rule', - title: 'Rule', - group: 2, - description: - 'Rule fields are used to capture the specifics of any observer or\nagent rules that generate alerts or other notable events.\n\nExamples of data sources that would populate the rule fields include: network\nadmission control platforms, network or host IDS/IPS, network firewalls, web\napplication firewalls, url filters, endpoint detection and response (EDR) systems,\netc.', - type: 'group', - fields: [ - { - name: 'author', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name, organization, or pseudonym of the author or authors who created\nthe rule used to generate this event.', - example: ['Star-Lord'], - default_field: false, - }, - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A categorization value keyword used by the entity using the rule\nfor detection of this event.', - example: 'Attempted Information Leak', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The description of the rule generating the event.', - example: 'Block requests to public DNS over HTTPS / TLS protocols', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of an agent, observer,\nor other entity using the rule for detection of this event.', - example: 101, - default_field: false, - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the license under which the rule used to generate this\nevent is made available.', - example: 'Apache 2.0', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the rule or signature generating the event.', - example: 'BLOCK_DNS_over_TLS', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL to additional information about the rule used to\ngenerate this event.\n\nThe URL can point to the vendor documentation about the rule. If that is\nnot available, it can also be a link to a more general page describing this\ntype of alert.', - example: 'https://en.wikipedia.org/wiki/DNS_over_TLS', - default_field: false, - }, - { - name: 'ruleset', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the ruleset, policy, group, or parent category in which\nthe rule used to generate this event is a member.', - example: 'Standard_Protocol_Filters', - default_field: false, - }, - { - name: 'uuid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of a set or group of\nagents, observers, or other entities using the rule for detection of this\nevent.', - example: 1100110011, - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The version / revision of the rule being used for analysis.', - example: 1.1, - default_field: false, - }, - ], - }, - { - name: 'server', - title: 'Server', - group: 2, - description: - 'A Server is defined as the responder in a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the server is the receiver of the initial SYN packet(s) of the\nTCP connection. For other protocols, the server is generally the responder in\nthe network transaction. Some systems actually use the term "responder" to refer\nthe server in TCP connections. The server fields describe details about the\nsystem acting as the server in the network event. Server fields are usually\npopulated in conjunction with client fields. Server fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event server addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the server to the client.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Server domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the server.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the server.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the server to the client.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the server.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered server domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'service', - title: 'Service', - group: 2, - description: - 'The service fields describe the service for or from which the data\nwas collected.\n\nThese fields help you find and correlate logs for a specific service and version.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this service (if one exists).\n\nThis id normally changes across restarts, but `service.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the running service. If the service is comprised\nof many nodes, the `service.id` should be the same for all nodes.\n\nThis id should uniquely identify the service. This makes it possible to correlate\nlogs and metrics for one specific service, no matter which particular node\nemitted the event.\n\nNote that if you need to see the events from one specific host of the service,\nyou should filter on that `host.name` or `host.id` instead.', - example: 'd37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the service data is collected from.\n\nThe name of the service is normally user given. This allows for distributed\nservices that run on multiple hosts to correlate the related instances based\non the name.\n\nIn the case of Elasticsearch the `service.name` could contain the cluster\nname. For Beats the `service.name` is by default a copy of the `service.type`\nfield if no name is specified.', - example: 'elasticsearch-metrics', - }, - { - name: 'node.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of a service node.\n\nThis allows for two nodes of the same service running on the same host to\nbe differentiated. Therefore, `service.node.name` should typically be unique\nacross nodes of a given service.\n\nIn the case of Elasticsearch, the `service.node.name` could contain the unique\nnode name within the Elasticsearch cluster. In cases where the service does not\nhave the concept of a node name, the host name or container name can be used\nto distinguish running instances that make up this service. If those do not\nprovide uniqueness (e.g. multiple instances of the service running on the\nsame host) - the node name can be manually set.', - example: 'instance-0000000016', - }, - { - name: 'state', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Current state of the service.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the service data is collected from.\n\nThe type can be used to group and correlate logs and metrics from one service\ntype.\n\nExample: If logs or metrics are collected from Elasticsearch, `service.type`\nwould be `elasticsearch`.', - example: 'elasticsearch', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Version of the service the data was collected from.\n\nThis allows to look at a data set only for a specific version of a service.', - example: '3.2.4', - }, - ], - }, - { - name: 'source', - title: 'Source', - group: 2, - description: - 'Source fields describe details about the source of a packet/event.\n\nSource fields are usually populated in conjunction with destination fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event source addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the source to the destination.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Source domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the source.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the source.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of source based NAT sessions (e.g. internal client\nto internet)\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions. (e.g. internal client\nto internet)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the source to the destination.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the source.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered source domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'threat', - title: 'Threat', - group: 2, - description: - 'Fields to classify events and alerts according to a threat taxonomy\nsuch as the Mitre ATT&CK framework.\n\nThese fields are for users to classify alerts from all of their sources (e.g.\nIDS, NGFW, etc.) within a common taxonomy. The threat.tactic.* are meant to\ncapture the high level category of the threat (e.g. "impact"). The threat.technique.*\nfields are meant to capture which kind of approach is used by this detected\nthreat, to accomplish the goal (e.g. "endpoint denial of service").', - type: 'group', - fields: [ - { - name: 'framework', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the threat framework used to further categorize and classify\nthe tactic and technique of the reported threat. Framework classification\ncan be provided by detecting systems, evaluated at ingest time, or retrospectively\ntagged to events.', - example: 'MITRE ATT&CK', - }, - { - name: 'tactic.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of tactic used by this threat. You can use the Mitre ATT&CK\nMatrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'TA0040', - }, - { - name: 'tactic.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the type of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'impact', - }, - { - name: 'tactic.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'https://attack.mitre.org/tactics/TA0040/', - }, - { - name: 'technique.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'T1499', - }, - { - name: 'technique.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'The name of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'endpoint denial of service', - }, - { - name: 'technique.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of technique used by this tactic. You can use\nthe Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'https://attack.mitre.org/techniques/T1499/', - }, - ], - }, - { - name: 'tls', - title: 'TLS', - group: 2, - description: - 'Fields related to a TLS connection. These fields focus on the TLS\nprotocol itself and intentionally avoids in-depth analysis of the related x.509\ncertificate files.', - type: 'group', - fields: [ - { - name: 'cipher', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the cipher used during the current connection.', - example: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', - default_field: false, - }, - { - name: 'client.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the client. This\nis usually mutually-exclusive of `client.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'client.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the client. This is usually mutually-exclusive of `client.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'client.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'client.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'client.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the client. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'client.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the issuer of the x.509 certificate\npresented by the client.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.ja3', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies clients based on how they perform an SSL/TLS\nhandshake.', - example: 'd4e5b18d6b55c71272893221c96ba240', - default_field: false, - }, - { - name: 'client.not_after', - level: 'extended', - type: 'date', - description: - 'Date/Time indicating when client certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.not_before', - level: 'extended', - type: 'date', - description: 'Date/Time indicating when client certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.server_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Also called an SNI, this tells the server which hostname to which\nthe client is attempting to connect. When this value is available, it should\nget copied to `destination.domain`.', - example: 'www.elastic.co', - default_field: false, - }, - { - name: 'client.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the x.509 certificate presented\nby the client.', - example: 'CN=myclient, OU=Documentation Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.supported_ciphers', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Array of ciphers offered by the client during the client hello.', - example: [ - 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', - 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', - '...', - ], - default_field: false, - }, - { - name: 'curve', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the curve used for the given cipher, when applicable.', - example: 'secp256r1', - default_field: false, - }, - { - name: 'established', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if the TLS negotiation was successful and\ntransitioned to an encrypted tunnel.', - default_field: false, - }, - { - name: 'next_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'String indicating the protocol being tunneled. Per the values in\nthe IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids),\nthis string should be lower case.', - example: 'http/1.1', - default_field: false, - }, - { - name: 'resumed', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if this TLS connection was resumed from\nan existing TLS negotiation.', - default_field: false, - }, - { - name: 'server.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the server. This\nis usually mutually-exclusive of `server.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'server.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the server. This is usually mutually-exclusive of `server.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'server.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'server.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'server.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the server. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'server.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the issuer of the x.509 certificate presented by the\nserver.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'server.ja3s', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies servers based on how they perform an SSL/TLS\nhandshake.', - example: '394441ab65754e2207b1e1b457b3641d', - default_field: false, - }, - { - name: 'server.not_after', - level: 'extended', - type: 'date', - description: - 'Timestamp indicating when server certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.not_before', - level: 'extended', - type: 'date', - description: 'Timestamp indicating when server certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the x.509 certificate presented by the server.', - example: 'CN=www.mydomain.com, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Numeric part of the version parsed from the original string.', - example: '1.2', - default_field: false, - }, - { - name: 'version_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Normalized lowercase protocol name parsed from original string.', - example: 'tls', - default_field: false, - }, - ], - }, - { - name: 'tracing', - title: 'Tracing', - group: 2, - description: - 'Distributed tracing makes it possible to analyze performance throughout\na microservice architecture all in one view. This is accomplished by tracing\nall of the requests - from the initial web request in the front-end service\n- to queries made through multiple back-end services.', - type: 'group', - fields: [ - { - name: 'trace.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the trace.\n\nA trace groups multiple events like transactions that belong together. For\nexample, a user request handled by multiple inter-connected services.', - example: '4bf92f3577b34da6a3ce929d0e0e4736', - }, - { - name: 'transaction.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the transaction.\n\nA transaction is the highest level of work measured within a service, such\nas a request to a server.', - example: '00f067aa0ba902b7', - }, - ], - }, - { - name: 'url', - title: 'URL', - group: 2, - description: - 'URL fields provide support for complete or partial URLs, and supports\nthe breaking down into scheme, domain, path, and so on.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Domain of the url, such as "www.elastic.co".\n\nIn some cases a URL may refer to an IP and/or port directly, without a domain\nname. In this case, the IP address would go to the `domain` field.', - example: 'www.elastic.co', - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The field contains the file extension from the original request\nurl.\n\nThe file extension is only set if it exists, as not every url has a file extension.\n\nThe leading period must not be included. For example, the value must be "png",\nnot ".png".', - example: 'png', - }, - { - name: 'fragment', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Portion of the url after the `#`, such as "top".\n\nThe `#` is not part of the fragment.', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'If full URLs are important to your use case, they should be stored\nin `url.full`, whether this field is reconstructed or present in the event\nsource.', - example: 'https://www.elastic.co:443/search?q=elasticsearch#top', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Unmodified original url as seen in the event source.\n\nNote that in network monitoring, the observed URL may be a full URL, whereas\nin access logs, the URL is often just represented as a path.\n\nThis field is meant to represent the URL as it was observed, complete or not.', - example: - 'https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch', - }, - { - name: 'password', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Password of the request.', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path of the request, such as "/search".', - }, - { - name: 'port', - level: 'extended', - type: 'long', - format: 'string', - description: 'Port of the request, such as 443.', - example: 443, - }, - { - name: 'query', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The query field describes the query string of the request, such\nas "q=elasticsearch".\n\nThe `?` is excluded from the query string. If a URL contains no `?`, there\nis no query field. If there is a `?` but no query, the query field exists\nwith an empty string. The `exists` query can be used to differentiate between\nthe two cases.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered url domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'scheme', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Scheme of the request, such as "https".\n\nNote: The `:` is not part of the scheme.', - example: 'https', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'username', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Username of the request.', - }, - ], - }, - { - name: 'user', - title: 'User', - group: 2, - description: - 'The user fields describe information about the user that is relevant\nto the event.\n\nFields can have one entry or multiple entries. If a user has more than one id,\nprovide an array that includes all of them.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'user_agent', - title: 'User agent', - group: 2, - description: - 'The user_agent fields normally come from a browser request.\n\nThey often show up in web service logs coming from the parsed user agent string.', - type: 'group', - fields: [ - { - name: 'device.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the device.', - example: 'iPhone', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the user agent.', - example: 'Safari', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Unparsed user_agent string.', - example: - 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15\n(KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the user agent.', - example: 12, - }, - ], - }, - { - name: 'vlan', - title: 'VLAN', - group: 2, - description: - 'The VLAN fields are used to identify 802.1q tag(s) of a packet,\nas well as ingress and egress VLAN associations of an observer in relation to\na specific packet or connection.\n\nNetwork.vlan fields are used to record a single VLAN tag, or the outer tag in\nthe case of q-in-q encapsulations, for a packet or connection as observed, typically\nprovided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic.\n\nNetwork.inner VLAN fields are used to report inner q-in-q 802.1q tags (multiple\n802.1q encapsulations) as observed, typically provided by a network sensor (e.g.\nZeek, Wireshark) passively reporting on traffic. Network.inner VLAN fields should\nonly be used in addition to network.vlan fields to indicate q-in-q tagging.\n\nObserver.ingress and observer.egress VLAN values are used to record observer\nspecific information when observer events contain discrete ingress and egress\nVLAN information, typically provided by firewalls, routers, or load balancers.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'vulnerability', - title: 'Vulnerability', - group: 2, - description: - 'The vulnerability fields describe information about a vulnerability\nthat is relevant to an event.', - type: 'group', - fields: [ - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of system or architecture that the vulnerability affects.\nThese may be platform-specific (for example, Debian or SUSE) or general (for\nexample, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys\nvulnerability categories])\n\nThis field must be an array.', - example: '["Firewall"]', - default_field: false, - }, - { - name: 'classification', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The classification of the vulnerability scoring system. For example\n(https://www.first.org/cvss/)', - example: 'CVSS', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'The description of the vulnerability that provides additional context\nof the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common\nVulnerabilities and Exposure CVE description])', - example: 'In macOS before 2.12.6, there is a vulnerability in the RPC...', - default_field: false, - }, - { - name: 'enumeration', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of identifier used for this vulnerability. For example\n(https://cve.mitre.org/about/)', - example: 'CVE', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The identification (ID) is the number portion of a vulnerability\nentry. It includes a unique identification number for the vulnerability. For\nexample (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities\nand Exposure CVE ID]', - example: 'CVE-2019-00001', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A resource that provides additional information, context, and mitigations\nfor the identified vulnerability.', - example: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111', - default_field: false, - }, - { - name: 'report_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The report or scan identification number.', - example: 20191018.0001, - default_field: false, - }, - { - name: 'scanner.vendor', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the vulnerability scanner vendor.', - example: 'Tenable', - default_field: false, - }, - { - name: 'score.base', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nBase scores cover an assessment for exploitability metrics (attack vector,\ncomplexity, privileges, and user interaction), impact metrics (confidentiality,\nintegrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.environmental', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nEnvironmental scores cover an assessment for any modified Base metrics, confidentiality,\nintegrity, and availability requirements. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.temporal', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nTemporal scores cover an assessment for code maturity, remediation level,\nand confidence. For example (https://www.first.org/cvss/specification-document)', - default_field: false, - }, - { - name: 'score.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The National Vulnerability Database (NVD) provides qualitative\nseverity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score\nranges in addition to the severity ratings for CVSS v3.0 as they are defined\nin the CVSS v3.0 specification.\n\nCVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit\norganization, whose mission is to help computer security incident response\nteams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 2, - default_field: false, - }, - { - name: 'severity', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The severity of the vulnerability can help with metrics and internal\nprioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 'Critical', - default_field: false, - }, - ], - }, - ], - }, - { - key: 'beat', - anchor: 'beat-common', - title: 'Beat', - description: 'Contains common beat fields available in all event types.\n', - fields: [ - { - name: 'agent.hostname', - type: 'keyword', - description: 'Hostname of the agent.', - }, - { - name: 'beat.timezone', - type: 'alias', - path: 'event.timezone', - migration: true, - }, - { - name: 'fields', - type: 'object', - object_type: 'keyword', - description: 'Contains user configurable fields.\n', - }, - { - name: 'beat.name', - type: 'alias', - path: 'host.name', - migration: true, - }, - { - name: 'beat.hostname', - type: 'alias', - path: 'agent.hostname', - migration: true, - }, - { - name: 'timeseries.instance', - type: 'keyword', - description: 'Time series instance id', - }, - ], - }, - { - key: 'cloud', - title: 'Cloud provider metadata', - description: 'Metadata from cloud providers added by the add_cloud_metadata processor.\n', - fields: [ - { - name: 'cloud.project.id', - example: 'project-x', - description: 'Name of the project in Google Cloud.\n', - }, - { - name: 'cloud.image.id', - example: 'ami-abcd1234', - description: 'Image ID for the cloud instance.\n', - }, - { - name: 'meta.cloud.provider', - type: 'alias', - path: 'cloud.provider', - migration: true, - }, - { - name: 'meta.cloud.instance_id', - type: 'alias', - path: 'cloud.instance.id', - migration: true, - }, - { - name: 'meta.cloud.instance_name', - type: 'alias', - path: 'cloud.instance.name', - migration: true, - }, - { - name: 'meta.cloud.machine_type', - type: 'alias', - path: 'cloud.machine.type', - migration: true, - }, - { - name: 'meta.cloud.availability_zone', - type: 'alias', - path: 'cloud.availability_zone', - migration: true, - }, - { - name: 'meta.cloud.project_id', - type: 'alias', - path: 'cloud.project.id', - migration: true, - }, - { - name: 'meta.cloud.region', - type: 'alias', - path: 'cloud.region', - migration: true, - }, - ], - }, - { - key: 'docker', - title: 'Docker', - description: 'Docker stats collected from Docker.\n', - short_config: false, - anchor: 'docker-processor', - fields: [ - { - name: 'docker', - type: 'group', - fields: [ - { - name: 'container.id', - type: 'alias', - path: 'container.id', - migration: true, - }, - { - name: 'container.image', - type: 'alias', - path: 'container.image.name', - migration: true, - }, - { - name: 'container.name', - type: 'alias', - path: 'container.name', - migration: true, - }, - { - name: 'container.labels', - type: 'object', - object_type: 'keyword', - description: 'Image labels.\n', - }, - ], - }, - ], - }, - { - key: 'host', - title: 'Host', - description: 'Info collected for the host machine.\n', - anchor: 'host-processor', - fields: [ - { - name: 'host', - type: 'group', - fields: [ - { - name: 'containerized', - type: 'boolean', - description: 'If the host is a container.\n', - }, - { - name: 'os.build', - type: 'keyword', - example: '18D109', - description: 'OS build information.\n', - }, - { - name: 'os.codename', - type: 'keyword', - example: 'stretch', - description: 'OS codename, if any.\n', - }, - ], - }, - ], - }, - { - key: 'kubernetes', - title: 'Kubernetes', - description: 'Kubernetes metadata added by the kubernetes processor\n', - short_config: false, - anchor: 'kubernetes-processor', - fields: [ - { - name: 'kubernetes', - type: 'group', - fields: [ - { - name: 'pod.name', - type: 'keyword', - description: 'Kubernetes pod name\n', - }, - { - name: 'pod.uid', - type: 'keyword', - description: 'Kubernetes Pod UID\n', - }, - { - name: 'namespace', - type: 'keyword', - description: 'Kubernetes namespace\n', - }, - { - name: 'node.name', - type: 'keyword', - description: 'Kubernetes node name\n', - }, - { - name: 'labels.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Kubernetes labels map\n', - }, - { - name: 'annotations.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Kubernetes annotations map\n', - }, - { - name: 'replicaset.name', - type: 'keyword', - description: 'Kubernetes replicaset name\n', - }, - { - name: 'deployment.name', - type: 'keyword', - description: 'Kubernetes deployment name\n', - }, - { - name: 'statefulset.name', - type: 'keyword', - description: 'Kubernetes statefulset name\n', - }, - { - name: 'container.name', - type: 'keyword', - description: 'Kubernetes container name\n', - }, - { - name: 'container.image', - type: 'keyword', - description: 'Kubernetes container image\n', - }, - ], - }, - ], - }, - { - key: 'process', - title: 'Process', - description: 'Process metadata fields\n', - fields: [ - { - name: 'process', - type: 'group', - fields: [ - { - name: 'exe', - type: 'alias', - path: 'process.executable', - migration: true, - }, - ], - }, - ], - }, - { - key: 'jolokia-autodiscover', - title: 'Jolokia Discovery autodiscover provider', - description: 'Metadata from Jolokia Discovery added by the jolokia provider.\n', - fields: [ - { - name: 'jolokia.agent.version', - type: 'keyword', - description: 'Version number of jolokia agent.\n', - }, - { - name: 'jolokia.agent.id', - type: 'keyword', - description: - 'Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type.\n', - }, - { - name: 'jolokia.server.product', - type: 'keyword', - description: 'The container product if detected.\n', - }, - { - name: 'jolokia.server.version', - type: 'keyword', - description: "The container's version (if detected).\n", - }, - { - name: 'jolokia.server.vendor', - type: 'keyword', - description: 'The vendor of the container the agent is running in.\n', - }, - { - name: 'jolokia.url', - type: 'keyword', - description: 'The URL how this agent can be contacted.\n', - }, - { - name: 'jolokia.secured', - type: 'boolean', - description: 'Whether the agent was configured for authentication or not.\n', - }, - ], - }, - { - key: 'log', - title: 'Log file content', - description: 'Contains log file lines.\n', - fields: [ - { - name: 'log.file.path', - type: 'keyword', - required: false, - description: - 'The file from which the line was read. This field contains the absolute path to the file. For example: `/var/log/system.log`.\n', - }, - { - name: 'log.source.address', - type: 'keyword', - required: false, - description: 'Source address from which the log event was read / sent from.\n', - }, - { - name: 'log.offset', - type: 'long', - required: false, - description: 'The file offset the reported line starts at.\n', - }, - { - name: 'stream', - type: 'keyword', - required: false, - description: "Log stream when reading container logs, can be 'stdout' or 'stderr'\n", - }, - { - name: 'input.type', - required: true, - description: - 'The input type from which the event was generated. This field is set to the value specified for the `type` option in the input section of the Filebeat config file.\n', - }, - { - name: 'syslog.facility', - type: 'long', - required: false, - description: 'The facility extracted from the priority.\n', - }, - { - name: 'syslog.priority', - type: 'long', - required: false, - description: 'The priority of the syslog event.\n', - }, - { - name: 'syslog.severity_label', - type: 'keyword', - required: false, - description: 'The human readable severity.\n', - }, - { - name: 'syslog.facility_label', - type: 'keyword', - required: false, - description: 'The human readable facility.\n', - }, - { - name: 'process.program', - type: 'keyword', - required: false, - description: 'The name of the program.\n', - }, - { - name: 'log.flags', - description: 'This field contains the flags of the event.\n', - }, - { - name: 'http.response.content_length', - type: 'alias', - path: 'http.response.body.bytes', - migration: true, - }, - { - name: 'user_agent', - type: 'group', - fields: [ - { - name: 'os', - type: 'group', - fields: [ - { - name: 'full_name', - type: 'keyword', - }, - ], - }, - ], - }, - { - name: 'fileset.name', - type: 'keyword', - description: 'The Filebeat fileset that generated this event.\n', - }, - { - name: 'fileset.module', - type: 'alias', - path: 'event.module', - migration: true, - }, - { - name: 'read_timestamp', - type: 'alias', - path: 'event.created', - migration: true, - }, - { - name: 'docker.attrs', - type: 'object', - object_type: 'keyword', - description: - "docker.attrs contains labels and environment variables written by docker's JSON File logging driver. These fields are only available when they are configured in the logging driver options.\n", - }, - { - name: 'icmp.code', - type: 'keyword', - description: 'ICMP code.\n', - }, - { - name: 'icmp.type', - type: 'keyword', - description: 'ICMP type.\n', - }, - { - name: 'igmp.type', - type: 'keyword', - description: 'IGMP type.\n', - }, - { - name: 'azure', - type: 'group', - fields: [ - { - name: 'eventhub', - type: 'keyword', - description: 'Name of the eventhub.\n', - }, - { - name: 'offset', - type: 'long', - description: 'The offset.\n', - }, - { - name: 'enqueued_time', - type: 'date', - description: 'The enqueued time.\n', - }, - { - name: 'partition_id', - type: 'long', - description: 'The partition id.\n', - }, - { - name: 'consumer_group', - type: 'keyword', - description: 'The consumer group.\n', - }, - { - name: 'sequence_number', - type: 'long', - description: 'The sequence number.\n', - }, - ], - }, - { - name: 'kafka', - type: 'group', - fields: [ - { - name: 'topic', - type: 'keyword', - description: 'Kafka topic\n', - }, - { - name: 'partition', - type: 'long', - description: 'Kafka partition number\n', - }, - { - name: 'offset', - type: 'long', - description: 'Kafka offset of this message\n', - }, - { - name: 'key', - type: 'keyword', - description: 'Kafka key, corresponding to the Kafka value stored in the message\n', - }, - { - name: 'block_timestamp', - type: 'date', - description: 'Kafka outer (compressed) block timestamp\n', - }, - { - name: 'headers', - type: 'array', - description: - 'An array of Kafka header strings for this message, in the form ": ".\n', - }, - ], - }, - ], - }, - { - key: 'apache', - title: 'Apache', - description: 'Apache Module\n', - short_config: true, - fields: [ - { - name: 'apache2', - type: 'group', - description: 'Aliases for backward compatibility with old apache2 fields\n', - fields: [ - { - name: 'access', - type: 'group', - fields: [ - { - name: 'remote_ip', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'ssl.protocol', - type: 'alias', - path: 'apache.access.ssl.protocol', - migration: true, - }, - { - name: 'ssl.cipher', - type: 'alias', - path: 'apache.access.ssl.cipher', - migration: true, - }, - { - name: 'body_sent.bytes', - type: 'alias', - path: 'http.response.body.bytes', - migration: true, - }, - { - name: 'user_name', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - { - name: 'url', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'http_version', - type: 'alias', - path: 'http.version', - migration: true, - }, - { - name: 'response_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'referrer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'agent', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - { - name: 'user_agent', - type: 'group', - fields: [ - { - name: 'device', - type: 'alias', - path: 'user_agent.device.name', - migration: true, - }, - { - name: 'name', - type: 'alias', - path: 'user_agent.name', - migration: true, - }, - { - name: 'os', - type: 'alias', - path: 'user_agent.os.full_name', - migration: true, - }, - { - name: 'os_name', - type: 'alias', - path: 'user_agent.os.name', - migration: true, - }, - { - name: 'original', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - ], - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - ], - }, - { - name: 'error', - type: 'group', - fields: [ - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'tid', - type: 'alias', - path: 'process.thread.id', - migration: true, - }, - { - name: 'module', - type: 'alias', - path: 'apache.error.module', - migration: true, - }, - ], - }, - ], - }, - { - name: 'apache', - type: 'group', - description: 'Apache fields.\n', - fields: [ - { - name: 'access', - type: 'group', - description: 'Contains fields for the Apache HTTP Server access logs.\n', - fields: [ - { - name: 'ssl.protocol', - type: 'keyword', - description: 'SSL protocol version.\n', - }, - { - name: 'ssl.cipher', - type: 'keyword', - description: 'SSL cipher name.\n', - }, - ], - }, - { - name: 'error', - type: 'group', - description: 'Fields from the Apache error logs.\n', - fields: [ - { - name: 'module', - type: 'keyword', - description: 'The module producing the logged message.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'auditd', - title: 'Auditd', - description: 'Module for parsing auditd logs.\n', - short_config: true, - fields: [ - { - name: 'user', - type: 'group', - fields: [ - { - name: 'terminal', - type: 'keyword', - description: - 'Terminal or tty device on which the user is performing the observed activity.\n', - }, - { - name: 'audit', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.\n', - }, - { - name: 'name', - type: 'keyword', - example: 'albert', - description: 'Short name or login of the user.\n', - }, - { - name: 'group.id', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.\n', - }, - { - name: 'group.name', - type: 'keyword', - description: 'Name of the group.\n', - }, - ], - }, - { - name: 'effective', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.\n', - }, - { - name: 'name', - type: 'keyword', - example: 'albert', - description: 'Short name or login of the user.\n', - }, - { - name: 'group.id', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.\n', - }, - { - name: 'group.name', - type: 'keyword', - description: 'Name of the group.\n', - }, - ], - }, - { - name: 'filesystem', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.\n', - }, - { - name: 'name', - type: 'keyword', - example: 'albert', - description: 'Short name or login of the user.\n', - }, - { - name: 'group.id', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.\n', - }, - { - name: 'group.name', - type: 'keyword', - description: 'Name of the group.\n', - }, - ], - }, - { - name: 'owner', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.\n', - }, - { - name: 'name', - type: 'keyword', - example: 'albert', - description: 'Short name or login of the user.\n', - }, - { - name: 'group.id', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.\n', - }, - { - name: 'group.name', - type: 'keyword', - description: 'Name of the group.\n', - }, - ], - }, - { - name: 'saved', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.\n', - }, - { - name: 'name', - type: 'keyword', - example: 'albert', - description: 'Short name or login of the user.\n', - }, - { - name: 'group.id', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.\n', - }, - { - name: 'group.name', - type: 'keyword', - description: 'Name of the group.\n', - }, - ], - }, - ], - }, - { - name: 'auditd', - type: 'group', - description: 'Fields from the auditd logs.\n', - fields: [ - { - name: 'log', - type: 'group', - description: - 'Fields from the Linux audit log. Not all fields are documented here because they are dynamic and vary by audit event type.\n', - fields: [ - { - name: 'old_auid', - description: - 'For login events this is the old audit ID used for the user prior to this login.\n', - }, - { - name: 'new_auid', - description: - 'For login events this is the new audit ID. The audit ID can be used to trace future events to the user even if their identity changes (like becoming root).\n', - }, - { - name: 'old_ses', - description: - 'For login events this is the old session ID used for the user prior to this login.\n', - }, - { - name: 'new_ses', - description: - 'For login events this is the new session ID. It can be used to tie a user to future events by session ID.\n', - }, - { - name: 'sequence', - type: 'long', - description: 'The audit event sequence number.\n', - }, - { - name: 'items', - description: 'The number of items in an event.\n', - }, - { - name: 'item', - description: - 'The item field indicates which item out of the total number of items. This number is zero-based; a value of 0 means it is the first item.\n', - }, - { - name: 'tty', - type: 'keyword', - definition: 'TTY udevice the user is running programs on.\n', - }, - { - name: 'a0', - description: 'The first argument to the system call.\n', - }, - { - name: 'addr', - type: 'ip', - definition: 'Remote address that the user is connecting from.\n', - }, - { - name: 'rport', - type: 'long', - definition: 'Remote port number.\n', - }, - { - name: 'laddr', - type: 'ip', - definition: 'Local network address.\n', - }, - { - name: 'lport', - type: 'long', - definition: 'Local port number.\n', - }, - { - name: 'acct', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'ppid', - type: 'alias', - path: 'process.ppid', - migration: true, - }, - { - name: 'res', - type: 'alias', - path: 'event.outcome', - migration: true, - }, - { - name: 'record_type', - type: 'alias', - path: 'event.action', - migration: true, - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - { - name: 'arch', - type: 'alias', - path: 'host.architecture', - migration: true, - }, - { - name: 'gid', - type: 'alias', - path: 'user.group.id', - migration: true, - }, - { - name: 'uid', - type: 'alias', - path: 'user.id', - migration: true, - }, - { - name: 'agid', - type: 'alias', - path: 'user.audit.group.id', - migration: true, - }, - { - name: 'auid', - type: 'alias', - path: 'user.audit.id', - migration: true, - }, - { - name: 'fsgid', - type: 'alias', - path: 'user.filesystem.group.id', - migration: true, - }, - { - name: 'fsuid', - type: 'alias', - path: 'user.filesystem.id', - migration: true, - }, - { - name: 'egid', - type: 'alias', - path: 'user.effective.group.id', - migration: true, - }, - { - name: 'euid', - type: 'alias', - path: 'user.effective.id', - migration: true, - }, - { - name: 'sgid', - type: 'alias', - path: 'user.saved.group.id', - migration: true, - }, - { - name: 'suid', - type: 'alias', - path: 'user.saved.id', - migration: true, - }, - { - name: 'ogid', - type: 'alias', - path: 'user.owner.group.id', - migration: true, - }, - { - name: 'ouid', - type: 'alias', - path: 'user.owner.id', - migration: true, - }, - { - name: 'comm', - type: 'alias', - path: 'process.name', - migration: true, - }, - { - name: 'exe', - type: 'alias', - path: 'process.executable', - migration: true, - }, - { - name: 'terminal', - type: 'alias', - path: 'user.terminal', - migration: true, - }, - { - name: 'msg', - type: 'alias', - path: 'message', - migration: true, - }, - { - name: 'src', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'dst', - type: 'alias', - path: 'destination.address', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'elasticsearch', - title: 'elasticsearch', - description: 'elasticsearch Module\n', - fields: [ - { - name: 'elasticsearch', - type: 'group', - description: '\n', - fields: [ - { - name: 'component', - description: 'Elasticsearch component from where the log event originated', - example: 'o.e.c.m.MetaDataCreateIndexService', - type: 'keyword', - }, - { - name: 'cluster.uuid', - description: 'UUID of the cluster', - example: 'GmvrbHlNTiSVYiPf8kxg9g', - type: 'keyword', - }, - { - name: 'cluster.name', - description: 'Name of the cluster', - example: 'docker-cluster', - type: 'keyword', - }, - { - name: 'node.id', - description: 'ID of the node', - example: 'DSiWcTyeThWtUXLB9J0BMw', - type: 'keyword', - }, - { - name: 'node.name', - description: 'Name of the node', - example: 'vWNJsZ3', - type: 'keyword', - }, - { - name: 'index.name', - description: 'Index name', - example: 'filebeat-test-input', - type: 'keyword', - }, - { - name: 'index.id', - description: 'Index id', - example: 'aOGgDwbURfCV57AScqbCgw', - type: 'keyword', - }, - { - name: 'shard.id', - description: 'Id of the shard', - example: '0', - type: 'keyword', - }, - { - name: 'audit', - type: 'group', - description: '\n', - fields: [ - { - name: 'layer', - description: - 'The layer from which this event originated: rest, transport or ip_filter', - example: 'rest', - type: 'keyword', - }, - { - name: 'event_type', - description: - 'The type of event that occurred: anonymous_access_denied, authentication_failed, access_denied, access_granted, connection_granted, connection_denied, tampered_request, run_as_granted, run_as_denied', - example: 'access_granted', - type: 'keyword', - }, - { - name: 'origin.type', - description: - 'Where the request originated: rest (request originated from a REST API request), transport (request was received on the transport channel), local_node (the local node issued the request)', - example: 'local_node', - type: 'keyword', - }, - { - name: 'realm', - description: 'The authentication realm the authentication was validated against', - example: 'default_file', - type: 'keyword', - }, - { - name: 'user.realm', - description: "The user's authentication realm, if authenticated", - example: 'active_directory', - type: 'keyword', - }, - { - name: 'user.roles', - description: 'Roles to which the principal belongs', - example: ['kibana_user', 'beats_admin'], - type: 'keyword', - }, - { - name: 'action', - description: 'The name of the action that was executed', - example: 'cluster:monitor/main', - type: 'keyword', - }, - { - name: 'url.params', - description: 'REST URI parameters', - example: '{username=jacknich2}', - }, - { - name: 'indices', - description: 'Indices accessed by action', - example: ['foo-2019.01.04', 'foo-2019.01.03', 'foo-2019.01.06'], - type: 'keyword', - }, - { - name: 'request.id', - description: 'Unique ID of request', - example: 'WzL_kb6VSvOhAq0twPvHOQ', - type: 'keyword', - }, - { - name: 'request.name', - description: 'The type of request that was executed', - example: 'ClearScrollRequest', - type: 'keyword', - }, - { - name: 'request_body', - type: 'alias', - path: 'http.request.body.content', - migration: true, - }, - { - name: 'origin_address', - type: 'alias', - path: 'source.ip', - migration: true, - }, - { - name: 'uri', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'principal', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'message', - type: 'text', - }, - ], - }, - { - name: 'gc', - type: 'group', - description: 'GC fileset fields.\n', - fields: [ - { - name: 'phase', - type: 'group', - description: 'Fields specific to GC phase.\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'Name of the GC collection phase.\n', - }, - { - name: 'duration_sec', - type: 'float', - description: - 'Collection phase duration according to the Java virtual machine.\n', - }, - { - name: 'scrub_symbol_table_time_sec', - type: 'float', - description: 'Pause time in seconds cleaning up symbol tables.\n', - }, - { - name: 'scrub_string_table_time_sec', - type: 'float', - description: 'Pause time in seconds cleaning up string tables.\n', - }, - { - name: 'weak_refs_processing_time_sec', - type: 'float', - description: 'Time spent processing weak references in seconds.\n', - }, - { - name: 'parallel_rescan_time_sec', - type: 'float', - description: - 'Time spent in seconds marking live objects while application is stopped.\n', - }, - { - name: 'class_unload_time_sec', - type: 'float', - description: 'Time spent unloading unused classes in seconds.\n', - }, - { - name: 'cpu_time', - type: 'group', - description: 'Process CPU time spent performing collections.\n', - fields: [ - { - name: 'user_sec', - type: 'float', - description: 'CPU time spent outside the kernel.\n', - }, - { - name: 'sys_sec', - type: 'float', - description: 'CPU time spent inside the kernel.\n', - }, - { - name: 'real_sec', - type: 'float', - description: - 'Total elapsed CPU time spent to complete the collection from start to finish.\n', - }, - ], - }, - ], - }, - { - name: 'jvm_runtime_sec', - type: 'float', - description: 'The time from JVM start up in seconds, as a floating point number.\n', - }, - { - name: 'threads_total_stop_time_sec', - type: 'float', - description: 'Garbage collection threads total stop time seconds.\n', - }, - { - name: 'stopping_threads_time_sec', - type: 'float', - description: 'Time took to stop threads seconds.\n', - }, - { - name: 'tags', - type: 'keyword', - description: 'GC logging tags.\n', - }, - { - name: 'heap', - type: 'group', - description: 'Heap allocation and total size.\n', - fields: [ - { - name: 'size_kb', - type: 'integer', - description: 'Total heap size in kilobytes.\n', - }, - { - name: 'used_kb', - type: 'integer', - description: 'Used heap in kilobytes.\n', - }, - ], - }, - { - name: 'old_gen', - type: 'group', - description: 'Old generation occupancy and total size.\n', - fields: [ - { - name: 'size_kb', - type: 'integer', - description: 'Total size of old generation in kilobytes.\n', - }, - { - name: 'used_kb', - type: 'integer', - description: 'Old generation occupancy in kilobytes.\n', - }, - ], - }, - { - name: 'young_gen', - type: 'group', - description: 'Young generation occupancy and total size.\n', - fields: [ - { - name: 'size_kb', - type: 'integer', - description: 'Total size of young generation in kilobytes.\n', - }, - { - name: 'used_kb', - type: 'integer', - description: 'Young generation occupancy in kilobytes.\n', - }, - ], - }, - ], - }, - { - name: 'server', - description: 'Server log file', - type: 'group', - fields: [ - { - name: 'stacktrace', - description: 'Stack trace in case of errors', - index: false, - }, - { - name: 'gc', - description: 'GC log', - type: 'group', - fields: [ - { - name: 'young', - description: 'Young GC', - example: '', - type: 'group', - fields: [ - { - name: 'one', - description: '', - example: '', - type: 'long', - }, - { - name: 'two', - description: '', - example: '', - type: 'long', - }, - ], - }, - { - name: 'overhead_seq', - description: 'Sequence number', - example: 3449992, - type: 'long', - }, - { - name: 'collection_duration.ms', - description: 'Time spent in GC, in milliseconds', - example: 1600, - type: 'float', - }, - { - name: 'observation_duration.ms', - description: 'Total time over which collection was observed, in milliseconds', - example: 1800, - type: 'float', - }, - ], - }, - ], - }, - { - name: 'slowlog', - description: 'Slowlog events from Elasticsearch', - example: - '[2018-06-29T10:06:14,933][INFO ][index.search.slowlog.query] [v_VJhjV] [metricbeat-6.3.0-2018.06.26][0] took[4.5ms], took_millis[4], total_hits[19435], types[], stats[], search_type[QUERY_THEN_FETCH], total_shards[1], source[{"query":{"match_all":{"boost":1.0}}}],', - type: 'group', - fields: [ - { - name: 'logger', - description: 'Logger name', - example: 'index.search.slowlog.fetch', - type: 'keyword', - }, - { - name: 'took', - description: 'Time it took to execute the query', - example: '300ms', - type: 'keyword', - }, - { - name: 'types', - description: 'Types', - example: '', - type: 'keyword', - }, - { - name: 'stats', - description: 'Stats groups', - example: 'group1', - type: 'keyword', - }, - { - name: 'search_type', - description: 'Search type', - example: 'QUERY_THEN_FETCH', - type: 'keyword', - }, - { - name: 'source_query', - description: 'Slow query', - example: '{"query":{"match_all":{"boost":1.0}}}', - type: 'keyword', - }, - { - name: 'extra_source', - description: 'Extra source information', - example: '', - type: 'keyword', - }, - { - name: 'total_hits', - description: 'Total hits', - example: 42, - type: 'keyword', - }, - { - name: 'total_shards', - description: 'Total queried shards', - example: 22, - type: 'keyword', - }, - { - name: 'routing', - description: 'Routing', - example: 's01HZ2QBk9jw4gtgaFtn', - type: 'keyword', - }, - { - name: 'id', - description: 'Id', - example: '', - type: 'keyword', - }, - { - name: 'type', - description: 'Type', - example: 'doc', - type: 'keyword', - }, - { - name: 'source', - description: 'Source of document that was indexed', - type: 'keyword', - }, - ], - }, - ], - }, - ], - }, - { - key: 'haproxy', - title: 'haproxy', - description: 'haproxy Module\n', - fields: [ - { - name: 'haproxy', - type: 'group', - description: '\n', - fields: [ - { - name: 'frontend_name', - description: - 'Name of the frontend (or listener) which received and processed the connection.', - }, - { - name: 'backend_name', - description: - 'Name of the backend (or listener) which was selected to manage the connection to the server.', - }, - { - name: 'server_name', - description: 'Name of the last server to which the connection was sent.', - }, - { - name: 'total_waiting_time_ms', - description: 'Total time in milliseconds spent waiting in the various queues', - type: 'long', - }, - { - name: 'connection_wait_time_ms', - description: - 'Total time in milliseconds spent waiting for the connection to establish to the final server', - type: 'long', - }, - { - name: 'bytes_read', - description: 'Total number of bytes transmitted to the client when the log is emitted.', - type: 'long', - }, - { - name: 'time_queue', - description: 'Total time in milliseconds spent waiting in the various queues.', - type: 'long', - }, - { - name: 'time_backend_connect', - description: - 'Total time in milliseconds spent waiting for the connection to establish to the final server, including retries.', - type: 'long', - }, - { - name: 'server_queue', - description: - 'Total number of requests which were processed before this one in the server queue.', - type: 'long', - }, - { - name: 'backend_queue', - description: - "Total number of requests which were processed before this one in the backend's global queue.", - type: 'long', - }, - { - name: 'bind_name', - description: 'Name of the listening address which received the connection.', - }, - { - name: 'error_message', - description: 'Error message logged by HAProxy in case of error.', - type: 'text', - }, - { - name: 'source', - type: 'keyword', - description: 'The HAProxy source of the log', - }, - { - name: 'termination_state', - description: 'Condition the session was in when the session ended.', - }, - { - name: 'mode', - type: 'keyword', - description: 'mode that the frontend is operating (TCP or HTTP)', - }, - { - name: 'connections', - description: 'Contains various counts of connections active in the process.', - type: 'group', - fields: [ - { - name: 'active', - description: - 'Total number of concurrent connections on the process when the session was logged.', - type: 'long', - }, - { - name: 'frontend', - description: - 'Total number of concurrent connections on the frontend when the session was logged.', - type: 'long', - }, - { - name: 'backend', - description: - 'Total number of concurrent connections handled by the backend when the session was logged.', - type: 'long', - }, - { - name: 'server', - description: - 'Total number of concurrent connections still active on the server when the session was logged.', - type: 'long', - }, - { - name: 'retries', - description: - 'Number of connection retries experienced by this session when trying to connect to the server.', - type: 'long', - }, - ], - }, - { - name: 'client', - description: 'Information about the client doing the request', - type: 'group', - fields: [ - { - name: 'ip', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'port', - type: 'alias', - path: 'source.port', - migration: true, - }, - ], - }, - { - name: 'process_name', - type: 'alias', - path: 'process.name', - migration: true, - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'destination', - description: 'Destination information', - type: 'group', - fields: [ - { - name: 'port', - type: 'alias', - path: 'destination.port', - migration: true, - }, - { - name: 'ip', - type: 'alias', - path: 'destination.ip', - migration: true, - }, - ], - }, - { - name: 'geoip', - type: 'group', - description: - 'Contains GeoIP information gathered based on the client.ip field. Only present if the GeoIP Elasticsearch plugin is available and used.\n', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - { - name: 'http', - description: 'Please add description', - type: 'group', - fields: [ - { - name: 'response', - description: 'Fields related to the HTTP response', - type: 'group', - fields: [ - { - name: 'captured_cookie', - description: - 'Optional "name=value" entry indicating that the client had this cookie in the response.\n', - }, - { - name: 'captured_headers', - description: - 'List of headers captured in the response due to the presence of the "capture response header" statement in the frontend.\n', - type: 'keyword', - }, - { - name: 'status_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - ], - }, - { - name: 'request', - description: 'Fields related to the HTTP request', - type: 'group', - fields: [ - { - name: 'captured_cookie', - description: - 'Optional "name=value" entry indicating that the server has returned a cookie with its request.\n', - }, - { - name: 'captured_headers', - description: - 'List of headers captured in the request due to the presence of the "capture request header" statement in the frontend.\n', - type: 'keyword', - }, - { - name: 'raw_request_line', - description: - 'Complete HTTP request line, including the method, request and HTTP version string.', - type: 'keyword', - }, - { - name: 'time_wait_without_data_ms', - description: - 'Total time in milliseconds spent waiting for the server to send a full HTTP response, not counting data.', - type: 'long', - }, - { - name: 'time_wait_ms', - description: - 'Total time in milliseconds spent waiting for a full HTTP request from the client (not counting body) after the first byte was received.', - type: 'long', - }, - ], - }, - ], - }, - { - name: 'tcp', - description: 'TCP log format', - type: 'group', - fields: [ - { - name: 'connection_waiting_time_ms', - type: 'long', - description: - 'Total time in milliseconds elapsed between the accept and the last close', - }, - ], - }, - ], - }, - ], - }, - { - key: 'icinga', - title: 'Icinga', - description: 'Icinga Module\n', - fields: [ - { - name: 'icinga', - type: 'group', - description: '\n', - fields: [ - { - name: 'debug', - type: 'group', - description: 'Contains fields for the Icinga debug logs.\n', - fields: [ - { - name: 'facility', - type: 'keyword', - description: 'Specifies what component of Icinga logged the message.\n', - }, - { - name: 'severity', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - { - name: 'main', - type: 'group', - description: 'Contains fields for the Icinga main logs.\n', - fields: [ - { - name: 'facility', - type: 'keyword', - description: 'Specifies what component of Icinga logged the message.\n', - }, - { - name: 'severity', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - { - name: 'startup', - type: 'group', - description: 'Contains fields for the Icinga startup logs.\n', - fields: [ - { - name: 'facility', - type: 'keyword', - description: 'Specifies what component of Icinga logged the message.\n', - }, - { - name: 'severity', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'iis', - title: 'IIS', - description: 'Module for parsing IIS log files.\n', - fields: [ - { - name: 'iis', - type: 'group', - description: 'Fields from IIS log files.\n', - fields: [ - { - name: 'access', - type: 'group', - description: 'Contains fields for IIS access logs.\n', - fields: [ - { - name: 'sub_status', - type: 'long', - description: 'The HTTP substatus code.\n', - }, - { - name: 'win32_status', - type: 'long', - description: 'The Windows status code.\n', - }, - { - name: 'site_name', - type: 'keyword', - description: 'The site name and instance number.\n', - }, - { - name: 'server_name', - type: 'keyword', - description: 'The name of the server on which the log file entry was generated.\n', - }, - { - name: 'cookie', - type: 'keyword', - description: 'The content of the cookie sent or received, if any.\n', - }, - { - name: 'body_received.bytes', - type: 'alias', - path: 'http.request.body.bytes', - migration: true, - }, - { - name: 'body_sent.bytes', - type: 'alias', - path: 'http.response.body.bytes', - migration: true, - }, - { - name: 'server_ip', - type: 'alias', - path: 'destination.address', - migration: true, - }, - { - name: 'method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - { - name: 'url', - type: 'alias', - path: 'url.path', - migration: true, - }, - { - name: 'query_string', - type: 'alias', - path: 'url.query', - migration: true, - }, - { - name: 'port', - type: 'alias', - path: 'destination.port', - migration: true, - }, - { - name: 'user_name', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'remote_ip', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'referrer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'response_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'http_version', - type: 'alias', - path: 'http.version', - migration: true, - }, - { - name: 'hostname', - type: 'alias', - path: 'host.hostname', - migration: true, - }, - { - name: 'user_agent', - type: 'group', - fields: [ - { - name: 'device', - type: 'alias', - path: 'user_agent.device.name', - migration: true, - }, - { - name: 'name', - type: 'alias', - path: 'user_agent.name', - migration: true, - }, - { - name: 'os', - type: 'alias', - path: 'user_agent.os.full_name', - migration: true, - }, - { - name: 'os_name', - type: 'alias', - path: 'user_agent.os.name', - migration: true, - }, - { - name: 'original', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - ], - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - ], - }, - { - name: 'error', - type: 'group', - description: 'Contains fields for IIS error logs.\n', - fields: [ - { - name: 'reason_phrase', - type: 'keyword', - description: 'The HTTP reason phrase.\n', - }, - { - name: 'queue_name', - type: 'keyword', - description: 'The IIS application pool name.\n', - }, - { - name: 'remote_ip', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'remote_port', - type: 'alias', - path: 'source.port', - migration: true, - }, - { - name: 'server_ip', - type: 'alias', - path: 'destination.address', - migration: true, - }, - { - name: 'server_port', - type: 'alias', - path: 'destination.port', - migration: true, - }, - { - name: 'http_version', - type: 'alias', - path: 'http.version', - migration: true, - }, - { - name: 'method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - { - name: 'url', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'response_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'kafka', - title: 'Kafka', - description: 'Kafka module\n', - fields: [ - { - name: 'kafka', - type: 'group', - description: '\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'Kafka log lines.\n', - fields: [ - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - { - name: 'component', - type: 'keyword', - description: 'Component the log is coming from.\n', - }, - { - name: 'class', - type: 'keyword', - description: 'Java class the log is coming from.\n', - }, - { - name: 'trace', - type: 'group', - description: 'Trace in the log line.\n', - fields: [ - { - name: 'class', - type: 'keyword', - description: 'Java class the trace is coming from.\n', - }, - { - name: 'message', - type: 'text', - description: 'Message part of the trace.\n', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'kibana', - title: 'kibana', - description: 'kibana Module\n', - fields: [ - { - name: 'kibana', - type: 'group', - description: '\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'Kafka log lines.\n', - fields: [ - { - name: 'tags', - type: 'keyword', - description: 'Kibana logging tags.\n', - }, - { - name: 'state', - type: 'keyword', - description: 'Current state of Kibana.\n', - }, - { - name: 'meta', - type: 'object', - object_type: 'keyword', - }, - { - name: 'kibana.log.meta.req.headers.referer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'kibana.log.meta.req.referer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'kibana.log.meta.req.headers.user-agent', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - { - name: 'kibana.log.meta.req.remoteAddress', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'kibana.log.meta.req.url', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'kibana.log.meta.statusCode', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'kibana.log.meta.method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'logstash', - title: 'logstash', - description: 'logstash Module\n', - fields: [ - { - name: 'logstash', - type: 'group', - description: '\n', - fields: [ - { - name: 'log', - title: 'Logstash', - type: 'group', - description: 'Fields from the Logstash logs.\n', - fields: [ - { - name: 'module', - type: 'keyword', - description: 'The module or class where the event originate.\n', - }, - { - name: 'thread', - type: 'keyword', - description: 'Information about the running thread where the log originate.\n', - multi_fields: [ - { - name: 'text', - type: 'text', - }, - ], - }, - { - name: 'log_event', - type: 'object', - description: 'key and value debugging information.\n', - }, - { - name: 'pipeline_id', - type: 'keyword', - example: 'main', - description: 'The ID of the pipeline.\n', - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - ], - }, - { - name: 'slowlog', - type: 'group', - description: 'slowlog\n', - fields: [ - { - name: 'module', - type: 'keyword', - description: 'The module or class where the event originate.\n', - }, - { - name: 'thread', - type: 'keyword', - description: 'Information about the running thread where the log originate.\n', - multi_fields: [ - { - name: 'text', - type: 'text', - }, - ], - }, - { - name: 'event', - type: 'keyword', - description: 'Raw dump of the original event\n', - multi_fields: [ - { - name: 'text', - type: 'text', - }, - ], - }, - { - name: 'plugin_name', - type: 'keyword', - description: 'Name of the plugin\n', - }, - { - name: 'plugin_type', - type: 'keyword', - description: 'Type of the plugin: Inputs, Filters, Outputs or Codecs.\n', - }, - { - name: 'took_in_millis', - type: 'long', - description: 'Execution time for the plugin in milliseconds.\n', - }, - { - name: 'plugin_params', - type: 'keyword', - description: 'String value of the plugin configuration\n', - multi_fields: [ - { - name: 'text', - type: 'text', - }, - ], - }, - { - name: 'plugin_params_object', - type: 'object', - description: 'key -> value of the configuration used by the plugin.\n', - }, - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'took_in_nanos', - type: 'alias', - path: 'event.duration', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'mongodb', - title: 'mongodb', - description: 'Module for parsing MongoDB log files.\n', - fields: [ - { - name: 'mongodb', - type: 'group', - description: 'Fields from MongoDB logs.\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'Contains fields from MongoDB logs.\n', - fields: [ - { - name: 'component', - description: 'Functional categorization of message\n', - example: 'COMMAND', - type: 'keyword', - }, - { - name: 'context', - description: 'Context of message\n', - example: 'initandlisten', - type: 'keyword', - }, - { - name: 'severity', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'mysql', - title: 'MySQL', - description: 'Module for parsing the MySQL log files.\n', - short_config: true, - fields: [ - { - name: 'mysql', - type: 'group', - description: 'Fields from the MySQL log files.\n', - fields: [ - { - name: 'thread_id', - type: 'long', - description: 'The connection or thread ID for the query.\n', - }, - { - name: 'error', - type: 'group', - description: 'Contains fields from the MySQL error logs.\n', - fields: [ - { - name: 'thread_id', - type: 'alias', - path: 'mysql.thread_id', - migration: true, - }, - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - { - name: 'slowlog', - type: 'group', - description: 'Contains fields from the MySQL slow logs.\n', - fields: [ - { - name: 'lock_time.sec', - type: 'float', - description: - 'The amount of time the query waited for the lock to be available. The value is in seconds, as a floating point number.\n', - }, - { - name: 'rows_sent', - type: 'long', - description: 'The number of rows returned by the query.\n', - }, - { - name: 'rows_examined', - type: 'long', - description: 'The number of rows scanned by the query.\n', - }, - { - name: 'rows_affected', - type: 'long', - description: 'The number of rows modified by the query.\n', - }, - { - name: 'bytes_sent', - type: 'long', - format: 'bytes', - description: 'The number of bytes sent to client.\n', - }, - { - name: 'bytes_received', - type: 'long', - format: 'bytes', - description: 'The number of bytes received from client.\n', - }, - { - name: 'query', - description: 'The slow query.\n', - }, - { - name: 'id', - type: 'alias', - path: 'mysql.thread_id', - migration: true, - }, - { - name: 'schema', - type: 'keyword', - description: 'The schema where the slow query was executed.\n', - }, - { - name: 'current_user', - type: 'keyword', - description: - 'Current authenticated user, used to determine access privileges. Can differ from the value for user.\n', - }, - { - name: 'last_errno', - type: 'keyword', - description: 'Last SQL error seen.\n', - }, - { - name: 'killed', - type: 'keyword', - description: 'Code of the reason if the query was killed.\n', - }, - { - name: 'query_cache_hit', - type: 'boolean', - description: 'Whether the query cache was hit.\n', - }, - { - name: 'tmp_table', - type: 'boolean', - description: 'Whether a temporary table was used to resolve the query.\n', - }, - { - name: 'tmp_table_on_disk', - type: 'boolean', - description: 'Whether the query needed temporary tables on disk.\n', - }, - { - name: 'tmp_tables', - type: 'long', - description: 'Number of temporary tables created for this query\n', - }, - { - name: 'tmp_disk_tables', - type: 'long', - description: 'Number of temporary tables created on disk for this query.\n', - }, - { - name: 'tmp_table_sizes', - type: 'long', - format: 'bytes', - description: 'Size of temporary tables created for this query.', - }, - { - name: 'filesort', - type: 'boolean', - description: 'Whether filesort optimization was used.\n', - }, - { - name: 'filesort_on_disk', - type: 'boolean', - description: - 'Whether filesort optimization was used and it needed temporary tables on disk.\n', - }, - { - name: 'priority_queue', - type: 'boolean', - description: 'Whether a priority queue was used for filesort.\n', - }, - { - name: 'full_scan', - type: 'boolean', - description: 'Whether a full table scan was needed for the slow query.\n', - }, - { - name: 'full_join', - type: 'boolean', - description: - 'Whether a full join was needed for the slow query (no indexes were used for joins).\n', - }, - { - name: 'merge_passes', - type: 'long', - description: 'Number of merge passes executed for the query.\n', - }, - { - name: 'sort_merge_passes', - type: 'long', - description: 'Number of merge passes that the sort algorithm has had to do.\n', - }, - { - name: 'sort_range_count', - type: 'long', - description: 'Number of sorts that were done using ranges.\n', - }, - { - name: 'sort_rows', - type: 'long', - description: 'Number of sorted rows.\n', - }, - { - name: 'sort_scan_count', - type: 'long', - description: 'Number of sorts that were done by scanning the table.\n', - }, - { - name: 'log_slow_rate_type', - type: 'keyword', - description: - 'Type of slow log rate limit, it can be `session` if the rate limit is applied per session, or `query` if it applies per query.\n', - }, - { - name: 'log_slow_rate_limit', - type: 'keyword', - description: - 'Slow log rate limit, a value of 100 means that one in a hundred queries or sessions are being logged.\n', - }, - { - name: 'read_first', - type: 'long', - description: 'The number of times the first entry in an index was read.\n', - }, - { - name: 'read_last', - type: 'long', - description: 'The number of times the last key in an index was read.\n', - }, - { - name: 'read_key', - type: 'long', - description: 'The number of requests to read a row based on a key.\n', - }, - { - name: 'read_next', - type: 'long', - description: 'The number of requests to read the next row in key order.\n', - }, - { - name: 'read_prev', - type: 'long', - description: 'The number of requests to read the previous row in key order.\n', - }, - { - name: 'read_rnd', - type: 'long', - description: 'The number of requests to read a row based on a fixed position.\n', - }, - { - name: 'read_rnd_next', - type: 'long', - description: 'The number of requests to read the next row in the data file.\n', - }, - { - name: 'innodb', - type: 'group', - description: 'Contains fields relative to InnoDB engine\n', - fields: [ - { - name: 'trx_id', - type: 'keyword', - description: 'Transaction ID\n', - }, - { - name: 'io_r_ops', - type: 'long', - description: 'Number of page read operations.\n', - }, - { - name: 'io_r_bytes', - type: 'long', - format: 'bytes', - description: 'Bytes read during page read operations.\n', - }, - { - name: 'io_r_wait.sec', - type: 'long', - description: 'How long it took to read all needed data from storage.\n', - }, - { - name: 'rec_lock_wait.sec', - type: 'long', - description: 'How long the query waited for locks.\n', - }, - { - name: 'queue_wait.sec', - type: 'long', - description: - 'How long the query waited to enter the InnoDB queue and to be executed once in the queue.\n', - }, - { - name: 'pages_distinct', - type: 'long', - description: 'Approximated count of pages accessed to execute the query.\n', - }, - ], - }, - { - name: 'user', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'host', - type: 'alias', - path: 'source.domain', - migration: true, - }, - { - name: 'ip', - type: 'alias', - path: 'source.ip', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'nats', - title: 'nats', - description: 'Module for parsing NATS log files.\n', - release: 'beta', - fields: [ - { - name: 'nats', - type: 'group', - description: 'Fields from NATS logs.\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'Nats log files\n', - release: 'beta', - fields: [ - { - name: 'client', - type: 'group', - description: 'Fields from NATS logs client.\n', - fields: [ - { - name: 'id', - type: 'integer', - description: 'The id of the client\n', - }, - ], - }, - { - name: 'msg', - type: 'group', - description: 'Fields from NATS logs message.\n', - fields: [ - { - name: 'bytes', - type: 'long', - format: 'bytes', - description: 'Size of the payload in bytes\n', - }, - { - name: 'type', - type: 'keyword', - description: 'The protocol message type\n', - }, - { - name: 'subject', - type: 'keyword', - description: 'Subject name this message was received on\n', - }, - { - name: 'sid', - type: 'integer', - description: 'The unique alphanumeric subscription ID of the subject\n', - }, - { - name: 'reply_to', - type: 'keyword', - description: - 'The inbox subject on which the publisher is listening for responses\n', - }, - { - name: 'max_messages', - type: 'integer', - description: - 'An optional number of messages to wait for before automatically unsubscribing\n', - }, - { - name: 'error.message', - type: 'text', - description: 'Details about the error occurred\n', - }, - { - name: 'queue_group', - type: 'text', - description: 'The queue group which subscriber will join\n', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'nginx', - title: 'Nginx', - description: 'Module for parsing the Nginx log files.\n', - short_config: true, - fields: [ - { - name: 'nginx', - type: 'group', - description: 'Fields from the Nginx log files.\n', - fields: [ - { - name: 'access', - type: 'group', - description: 'Contains fields for the Nginx access logs.\n', - fields: [ - { - name: 'remote_ip_list', - type: 'array', - description: - 'An array of remote IP addresses. It is a list because it is common to include, besides the client IP address, IP addresses from headers like `X-Forwarded-For`. Real source IP is restored to `source.ip`.\n', - }, - { - name: 'body_sent.bytes', - type: 'alias', - path: 'http.response.body.bytes', - migration: true, - }, - { - name: 'user_name', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - { - name: 'url', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'http_version', - type: 'alias', - path: 'http.version', - migration: true, - }, - { - name: 'response_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'referrer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'agent', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - { - name: 'user_agent', - type: 'group', - fields: [ - { - name: 'device', - type: 'alias', - path: 'user_agent.device.name', - migration: true, - }, - { - name: 'name', - type: 'alias', - path: 'user_agent.name', - migration: true, - }, - { - name: 'os', - type: 'alias', - path: 'user_agent.os.full_name', - migration: true, - }, - { - name: 'os_name', - type: 'alias', - path: 'user_agent.os.name', - migration: true, - }, - { - name: 'original', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - ], - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - ], - }, - { - name: 'error', - type: 'group', - description: 'Contains fields for the Nginx error logs.\n', - fields: [ - { - name: 'connection_id', - type: 'long', - description: 'Connection identifier.\n', - }, - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'tid', - type: 'alias', - path: 'process.thread.id', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - { - name: 'ingress_controller', - type: 'group', - description: 'Contains fields for the Ingress Nginx controller access logs.\n', - fields: [ - { - name: 'remote_ip_list', - type: 'array', - description: - 'An array of remote IP addresses. It is a list because it is common to include, besides the client IP address, IP addresses from headers like `X-Forwarded-For`. Real source IP is restored to `source.ip`.\n', - }, - { - name: 'http.request.length', - type: 'long', - format: 'bytes', - description: - 'The request length (including request line, header, and request body)\n', - }, - { - name: 'http.request.time', - type: 'double', - format: 'duration', - description: 'Time elapsed since the first bytes were read from the client\n', - }, - { - name: 'upstream.name', - type: 'text', - description: 'The name of the upstream.\n', - }, - { - name: 'upstream.alternative_name', - type: 'text', - description: 'The name of the alternative upstream.\n', - }, - { - name: 'upstream.response.length', - type: 'long', - format: 'bytes', - description: 'The length of the response obtained from the upstream server\n', - }, - { - name: 'upstream.response.time', - type: 'double', - format: 'duration', - description: - 'The time spent on receiving the response from the upstream server as seconds with millisecond resolution\n', - }, - { - name: 'upstream.response.status_code', - type: 'long', - description: 'The status code of the response obtained from the upstream server\n', - }, - { - name: 'http.request.id', - type: 'text', - description: 'The randomly generated ID of the request\n', - }, - { - name: 'upstream.ip', - type: 'ip', - description: - 'The IP address of the upstream server. If several servers were contacted during request processing, their addresses are separated by commas.\n', - }, - { - name: 'upstream.port', - type: 'long', - description: 'The port of the upstream server.\n', - }, - { - name: 'body_sent.bytes', - type: 'alias', - path: 'http.response.body.bytes', - migration: true, - }, - { - name: 'user_name', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - { - name: 'url', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'http_version', - type: 'alias', - path: 'http.version', - migration: true, - }, - { - name: 'response_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'referrer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'agent', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - { - name: 'user_agent', - type: 'group', - fields: [ - { - name: 'device', - type: 'alias', - path: 'user_agent.device.name', - migration: true, - }, - { - name: 'name', - type: 'alias', - path: 'user_agent.name', - migration: true, - }, - { - name: 'os', - type: 'alias', - path: 'user_agent.os.full_name', - migration: true, - }, - { - name: 'os_name', - type: 'alias', - path: 'user_agent.os.name', - migration: true, - }, - { - name: 'original', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - ], - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'osquery', - title: 'Osquery', - description: 'Fields exported by the `osquery` module\n', - fields: [ - { - name: 'osquery', - type: 'group', - description: '\n', - fields: [ - { - name: 'result', - type: 'group', - description: 'Common fields exported by the result metricset.\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'The name of the query that generated this event.\n', - }, - { - name: 'action', - type: 'keyword', - description: - 'For incremental data, marks whether the entry was added or removed. It can be one of "added", "removed", or "snapshot".\n', - }, - { - name: 'host_identifier', - type: 'keyword', - description: - 'The identifier for the host on which the osquery agent is running. Normally the hostname.\n', - }, - { - name: 'unix_time', - type: 'long', - description: - 'Unix timestamp of the event, in seconds since the epoch. Used for computing the `@timestamp` column.\n', - }, - { - name: 'calendar_time', - type: 'keyword', - description: - 'String representation of the collection time, as formatted by osquery.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'postgresql', - title: 'PostgreSQL', - description: 'Module for parsing the PostgreSQL log files.\n', - short_config: true, - fields: [ - { - name: 'postgresql', - type: 'group', - description: 'Fields from PostgreSQL logs.\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'Fields from the PostgreSQL log files.\n', - fields: [ - { - name: 'timestamp', - deprecated: '7.3.0', - description: 'The timestamp from the log line.\n', - }, - { - name: 'core_id', - type: 'long', - description: 'Core id\n', - }, - { - name: 'database', - example: 'mydb', - description: 'Name of database\n', - }, - { - name: 'query', - example: 'SELECT * FROM users;', - description: 'Query statement.\n', - }, - { - name: 'query_step', - example: 'parse', - description: - 'Statement step when using extended query protocol (one of statement, parse, bind or execute)\n', - }, - { - name: 'query_name', - example: 'pdo_stmt_00000001', - description: - 'Name given to a query when using extended query protocol. If it is "", or not present, this field is ignored.\n', - }, - { - name: 'error.code', - type: 'long', - description: 'Error code returned by Postgres (if any)', - }, - { - name: 'timezone', - type: 'alias', - path: 'event.timezone', - migration: true, - }, - { - name: 'thread_id', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'user', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'redis', - title: 'Redis', - description: 'Redis Module\n', - fields: [ - { - name: 'redis', - type: 'group', - description: '\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'Redis log files\n', - fields: [ - { - name: 'role', - type: 'keyword', - description: - 'The role of the Redis instance. Can be one of `master`, `slave`, `child` (for RDF/AOF writing child), or `sentinel`.\n', - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'level', - type: 'alias', - path: 'log.level', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - { - name: 'slowlog', - type: 'group', - description: 'Slow logs are retrieved from Redis via a network connection.\n', - fields: [ - { - name: 'cmd', - type: 'keyword', - description: 'The command executed.\n', - }, - { - name: 'duration.us', - type: 'long', - description: 'How long it took to execute the command in microseconds.\n', - }, - { - name: 'id', - type: 'long', - description: 'The ID of the query.\n', - }, - { - name: 'key', - type: 'keyword', - description: 'The key on which the command was executed.\n', - }, - { - name: 'args', - type: 'keyword', - description: 'The arguments with which the command was called.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'santa', - title: 'Google Santa', - description: 'Santa Module\n', - fields: [ - { - name: 'santa', - type: 'group', - description: '\n', - fields: [ - { - name: 'action', - type: 'keyword', - example: 'EXEC', - description: 'Action', - }, - { - name: 'decision', - type: 'keyword', - example: 'ALLOW', - description: 'Decision that santad took.', - }, - { - name: 'reason', - type: 'keyword', - example: 'CERT', - description: 'Reason for the decsision.', - }, - { - name: 'mode', - type: 'keyword', - example: 'M', - description: 'Operating mode of Santa.', - }, - { - name: 'disk', - type: 'group', - description: 'Fields for DISKAPPEAR actions.', - fields: [ - { - name: 'volume', - description: 'The volume name.', - }, - { - name: 'bus', - description: 'The disk bus protocol.', - }, - { - name: 'serial', - description: 'The disk serial number.', - }, - { - name: 'bsdname', - example: 'disk1s3', - description: 'The disk BSD name.', - }, - { - name: 'model', - example: 'APPLE SSD SM0512L', - description: 'The disk model.', - }, - { - name: 'fs', - example: 'apfs', - description: 'The disk volume kind (filesystem type).', - }, - { - name: 'mount', - description: 'The disk volume path.', - }, - ], - }, - ], - }, - { - name: 'certificate.common_name', - type: 'keyword', - description: 'Common name from code signing certificate.', - }, - { - name: 'certificate.sha256', - type: 'keyword', - description: 'SHA256 hash of code signing certificate.', - }, - ], - }, - { - key: 'system', - title: 'System', - description: 'Module for parsing system log files.\n', - short_config: true, - fields: [ - { - name: 'system', - type: 'group', - description: 'Fields from the system log files.\n', - fields: [ - { - name: 'auth', - type: 'group', - description: 'Fields from the Linux authorization logs.\n', - fields: [ - { - name: 'timestamp', - type: 'alias', - path: '@timestamp', - migration: true, - }, - { - name: 'hostname', - type: 'alias', - path: 'host.hostname', - migration: true, - }, - { - name: 'program', - type: 'alias', - path: 'process.name', - migration: true, - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - { - name: 'user', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'ssh', - type: 'group', - fields: [ - { - name: 'method', - description: - 'The SSH authentication method. Can be one of "password" or "publickey".\n', - }, - { - name: 'signature', - description: 'The signature of the client public key.\n', - }, - { - name: 'dropped_ip', - type: 'ip', - description: - 'The client IP from SSH connections that are open and immediately dropped.\n', - }, - { - name: 'event', - example: 'Accepted', - description: - 'The SSH event as found in the logs (Accepted, Invalid, Failed, etc.)\n', - }, - { - name: 'ip', - type: 'alias', - path: 'source.ip', - migration: true, - }, - { - name: 'port', - type: 'alias', - path: 'source.port', - migration: true, - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - migration: true, - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - migration: true, - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - migration: true, - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - migration: true, - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - migration: true, - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - migration: true, - }, - ], - }, - ], - }, - { - name: 'sudo', - type: 'group', - description: 'Fields specific to events created by the `sudo` command.\n', - fields: [ - { - name: 'error', - example: 'user NOT in sudoers', - description: 'The error message in case the sudo command failed.\n', - }, - { - name: 'tty', - description: 'The TTY where the sudo command is executed.\n', - }, - { - name: 'pwd', - description: 'The current directory where the sudo command is executed.\n', - }, - { - name: 'user', - example: 'root', - description: 'The target user to which the sudo command is switching.\n', - }, - { - name: 'command', - description: 'The command executed via sudo.\n', - }, - ], - }, - { - name: 'useradd', - type: 'group', - description: 'Fields specific to events created by the `useradd` command.\n', - fields: [ - { - name: 'home', - description: 'The home folder for the new user.', - }, - { - name: 'shell', - description: 'The default shell for the new user.', - }, - { - name: 'name', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'uid', - type: 'alias', - path: 'user.id', - migration: true, - }, - { - name: 'gid', - type: 'alias', - path: 'group.id', - migration: true, - }, - ], - }, - { - name: 'groupadd', - type: 'group', - description: 'Fields specific to events created by the `groupadd` command.\n', - fields: [ - { - name: 'name', - type: 'alias', - path: 'group.name', - migration: true, - }, - { - name: 'gid', - type: 'alias', - path: 'group.id', - migration: true, - }, - ], - }, - ], - }, - { - name: 'syslog', - type: 'group', - description: 'Contains fields from the syslog system logs.\n', - fields: [ - { - name: 'timestamp', - type: 'alias', - path: '@timestamp', - migration: true, - }, - { - name: 'hostname', - type: 'alias', - path: 'host.hostname', - migration: true, - }, - { - name: 'program', - type: 'alias', - path: 'process.name', - migration: true, - }, - { - name: 'pid', - type: 'alias', - path: 'process.pid', - migration: true, - }, - { - name: 'message', - type: 'alias', - path: 'message', - migration: true, - }, - ], - }, - ], - }, - ], - }, - { - key: 'traefik', - title: 'Traefik', - description: 'Module for parsing the Traefik log files.\n', - fields: [ - { - name: 'traefik', - type: 'group', - description: 'Fields from the Traefik log files.\n', - fields: [ - { - name: 'access', - type: 'group', - description: 'Contains fields for the Traefik access logs.\n', - fields: [ - { - name: 'user_identifier', - type: 'keyword', - description: 'Is the RFC 1413 identity of the client\n', - }, - { - name: 'request_count', - type: 'long', - description: 'The number of requests\n', - }, - { - name: 'frontend_name', - type: 'keyword', - description: 'The name of the frontend used\n', - }, - { - name: 'backend_url', - type: 'keyword', - description: 'The url of the backend where request is forwarded', - }, - { - name: 'body_sent.bytes', - type: 'alias', - path: 'http.response.body.bytes', - migration: true, - }, - { - name: 'remote_ip', - type: 'alias', - path: 'source.address', - migration: true, - }, - { - name: 'user_name', - type: 'alias', - path: 'user.name', - migration: true, - }, - { - name: 'method', - type: 'alias', - path: 'http.request.method', - migration: true, - }, - { - name: 'url', - type: 'alias', - path: 'url.original', - migration: true, - }, - { - name: 'http_version', - type: 'alias', - path: 'http.version', - migration: true, - }, - { - name: 'response_code', - type: 'alias', - path: 'http.response.status_code', - migration: true, - }, - { - name: 'referrer', - type: 'alias', - path: 'http.request.referrer', - migration: true, - }, - { - name: 'agent', - type: 'alias', - path: 'user_agent.original', - migration: true, - }, - { - name: 'user_agent', - type: 'group', - fields: [ - { - name: 'device', - type: 'alias', - path: 'user_agent.device.name', - }, - { - name: 'name', - type: 'alias', - path: 'user_agent.name', - }, - { - name: 'os', - type: 'alias', - path: 'user_agent.os.full_name', - }, - { - name: 'os_name', - type: 'alias', - path: 'user_agent.os.name', - }, - { - name: 'original', - type: 'alias', - path: 'user_agent.original', - }, - ], - }, - { - name: 'geoip', - type: 'group', - fields: [ - { - name: 'continent_name', - type: 'alias', - path: 'source.geo.continent_name', - }, - { - name: 'country_iso_code', - type: 'alias', - path: 'source.geo.country_iso_code', - }, - { - name: 'location', - type: 'alias', - path: 'source.geo.location', - }, - { - name: 'region_name', - type: 'alias', - path: 'source.geo.region_name', - }, - { - name: 'city_name', - type: 'alias', - path: 'source.geo.city_name', - }, - { - name: 'region_iso_code', - type: 'alias', - path: 'source.geo.region_iso_code', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'activemq', - title: 'activemq', - release: 'ga', - description: 'Module for parsing ActiveMQ log files.\n', - fields: [ - { - name: 'activemq', - type: 'group', - description: '\n', - fields: [ - { - name: 'caller', - type: 'keyword', - description: 'Name of the caller issuing the logging request (class or resource).\n', - }, - { - name: 'thread', - type: 'keyword', - description: 'Thread that generated the logging event.\n', - }, - { - name: 'user', - type: 'keyword', - description: 'User that generated the logging event.\n', - }, - { - name: 'audit', - type: 'group', - description: 'Fields from ActiveMQ audit logs.\n', - fields: [], - }, - { - name: 'log', - type: 'group', - description: 'Fields from ActiveMQ application logs.\n', - fields: [ - { - name: 'stack_trace', - type: 'keyword', - }, - ], - }, - ], - }, - ], - }, - { - key: 'aws', - title: 'AWS', - release: 'beta', - description: 'Module for handling logs from AWS.\n', - fields: [ - { - name: 'aws', - type: 'group', - description: 'Fields from AWS logs.\n', - fields: [ - { - name: 'cloudtrail', - type: 'group', - release: 'beta', - default_field: false, - description: 'Fields for AWS CloudTrail logs.\n', - fields: [ - { - name: 'event_version', - type: 'keyword', - description: 'The CloudTrail version of the log event format.\n', - }, - { - name: 'user_identity', - type: 'group', - description: - 'The userIdentity element contains details about the type of IAM identity that made the request, and which credentials were used. If temporary credentials were used, the element shows how the credentials were obtained.', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'The type of the identity\n', - }, - { - name: 'arn', - type: 'keyword', - description: - 'The Amazon Resource Name (ARN) of the principal that made the call.', - }, - { - name: 'access_key_id', - type: 'keyword', - description: 'The access key ID that was used to sign the request.', - }, - { - name: 'session_context', - type: 'group', - description: - 'If the request was made with temporary security credentials, an element that provides information about the session that was created for those credentials', - fields: [ - { - name: 'mfa_authenticated', - type: 'keyword', - description: - 'The value is true if the root user or IAM user whose credentials were used for the request also was authenticated with an MFA device; otherwise, false.', - }, - { - name: 'creation_date', - type: 'date', - description: - 'The date and time when the temporary security credentials were issued.', - }, - ], - }, - { - name: 'invoked_by', - type: 'keyword', - description: - 'The name of the AWS service that made the request, such as Amazon EC2 Auto Scaling or AWS Elastic Beanstalk.', - }, - { - name: 'session_issuer', - type: 'group', - description: - 'If the request was made with temporary security credentials, an element that provides information about how the credentials were obtained.', - fields: [ - { - name: 'type', - type: 'keyword', - description: - 'The source of the temporary security credentials, such as Root, IAMUser, or Role.', - }, - { - name: 'principal_id', - type: 'keyword', - description: - 'The internal ID of the entity that was used to get credentials.', - }, - { - name: 'arn', - type: 'keyword', - description: - 'The ARN of the source (account, IAM user, or role) that was used to get temporary security credentials.', - }, - { - name: 'account_id', - type: 'keyword', - description: - 'The account that owns the entity that was used to get credentials.', - }, - ], - }, - ], - }, - { - name: 'error_code', - type: 'keyword', - description: 'The AWS service error if the request returns an error.', - }, - { - name: 'error_message', - type: 'keyword', - description: 'If the request returns an error, the description of the error.', - }, - { - name: 'request_parameters', - type: 'keyword', - description: 'The parameters, if any, that were sent with the request.', - }, - { - name: 'response_elements', - type: 'keyword', - description: - 'The response element for actions that make changes (create, update, or delete actions).', - }, - { - name: 'additional_eventdata', - type: 'keyword', - description: - 'Additional data about the event that was not part of the request or response.', - }, - { - name: 'request_id', - type: 'keyword', - description: - 'The value that identifies the request. The service being called generates this value.', - }, - { - name: 'event_type', - type: 'keyword', - description: 'Identifies the type of event that generated the event record.', - }, - { - name: 'api_version', - type: 'keyword', - description: - 'Identifies the API version associated with the AwsApiCall eventType value.', - }, - { - name: 'management_event', - type: 'keyword', - description: - 'A Boolean value that identifies whether the event is a management event.', - }, - { - name: 'read_only', - type: 'keyword', - description: 'Identifies whether this operation is a read-only operation.', - }, - { - name: 'resources', - type: 'group', - description: 'A list of resources accessed in the event.', - fields: [ - { - name: 'arn', - type: 'keyword', - description: 'Resource ARNs', - }, - { - name: 'account_id', - type: 'keyword', - description: 'Account ID of the resource owner', - }, - { - name: 'type', - type: 'keyword', - description: - 'Resource type identifier in the format: AWS::aws-service-name::data-type-name', - }, - ], - }, - { - name: 'recipient_account_id', - type: 'keyword', - description: 'Represents the account ID that received this event.', - }, - { - name: 'service_event_details', - type: 'keyword', - description: - 'Identifies the service event, including what triggered the event and the result.', - }, - { - name: 'shared_event_id', - type: 'keyword', - description: - 'GUID generated by CloudTrail to uniquely identify CloudTrail events from the same AWS action that is sent to different AWS accounts.', - }, - { - name: 'vpc_endpoint_id', - type: 'keyword', - description: - 'Identifies the VPC endpoint in which requests were made from a VPC to another AWS service, such as Amazon S3.', - }, - { - name: 'console_login', - type: 'group', - description: 'Fields specific to ConsoleLogin events', - fields: [ - { - name: 'additional_eventdata', - type: 'group', - description: 'Additional Event Data for ConsoleLogin events\n', - fields: [ - { - name: 'mobile_version', - type: 'boolean', - description: 'Identifies whether ConsoleLogin was from mobile version', - }, - { - name: 'login_to', - type: 'keyword', - description: 'URL for ConsoleLogin', - }, - { - name: 'mfa_used', - type: 'boolean', - description: - 'Identifies whether multi factor authentication was used during ConsoleLogin', - }, - ], - }, - ], - }, - ], - }, - { - name: 'cloudwatch', - type: 'group', - release: 'beta', - default_field: false, - description: 'Fields for AWS CloudWatch logs.\n', - fields: [], - }, - { - name: 'ec2', - type: 'group', - release: 'beta', - default_field: false, - description: 'Fields for AWS EC2 logs in CloudWatch.\n', - fields: [ - { - name: 'ip_address', - type: 'keyword', - description: 'The internet address of the requester.\n', - }, - ], - }, - { - name: 'elb', - type: 'group', - release: 'ga', - description: 'Fields for AWS ELB logs.\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'The name of the load balancer.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'The type of the load balancer for v2 Load Balancers.\n', - }, - { - name: 'target_group.arn', - type: 'keyword', - description: 'The ARN of the target group handling the request.\n', - }, - { - name: 'listener', - type: 'keyword', - description: 'The ELB listener that received the connection.\n', - }, - { - name: 'protocol', - type: 'keyword', - description: 'The protocol of the load balancer (http or tcp).\n', - }, - { - name: 'request_processing_time.sec', - type: 'float', - description: - 'The total time in seconds since the connection or request is received until it is sent to a registered backend.\n', - }, - { - name: 'backend_processing_time.sec', - type: 'float', - description: - 'The total time in seconds since the connection is sent to the backend till the backend starts responding.\n', - }, - { - name: 'response_processing_time.sec', - type: 'float', - description: - 'The total time in seconds since the response is received from the backend till it is sent to the client.\n', - }, - { - name: 'connection_time.ms', - type: 'long', - description: - 'The total time of the connection in milliseconds, since it is opened till it is closed.\n', - }, - { - name: 'tls_handshake_time.ms', - type: 'long', - description: - 'The total time for the TLS handshake to complete in milliseconds once the connection has been established.\n', - }, - { - name: 'backend.ip', - type: 'keyword', - description: 'The IP address of the backend processing this connection.\n', - }, - { - name: 'backend.port', - type: 'keyword', - description: 'The port in the backend processing this connection.\n', - }, - { - name: 'backend.http.response.status_code', - type: 'keyword', - description: - 'The status code from the backend (status code sent to the client from ELB is stored in `http.response.status_code`\n', - }, - { - name: 'ssl_cipher', - type: 'keyword', - description: 'The SSL cipher used in TLS/SSL connections.\n', - }, - { - name: 'ssl_protocol', - type: 'keyword', - description: 'The SSL protocol used in TLS/SSL connections.\n', - }, - { - name: 'chosen_cert.arn', - type: 'keyword', - description: - 'The ARN of the chosen certificate presented to the client in TLS/SSL connections.\n', - }, - { - name: 'chosen_cert.serial', - type: 'keyword', - description: - 'The serial number of the chosen certificate presented to the client in TLS/SSL connections.\n', - }, - { - name: 'incoming_tls_alert', - type: 'keyword', - description: - 'The integer value of TLS alerts received by the load balancer from the client, if present.\n', - }, - { - name: 'tls_named_group', - type: 'keyword', - description: 'The TLS named group.\n', - }, - { - name: 'trace_id', - type: 'keyword', - description: 'The contents of the `X-Amzn-Trace-Id` header.\n', - }, - { - name: 'matched_rule_priority', - type: 'keyword', - description: - 'The priority value of the rule that matched the request, if a rule matched.\n', - }, - { - name: 'action_executed', - type: 'keyword', - description: - 'The action executed when processing the request (forward, fixed-response, authenticate...). It can contain several values.\n', - }, - { - name: 'redirect_url', - type: 'keyword', - description: 'The URL used if a redirection action was executed.\n', - }, - { - name: 'error.reason', - type: 'keyword', - description: 'The error reason if the executed action failed.', - }, - ], - }, - { - name: 's3access', - type: 'group', - release: 'ga', - description: 'Fields for AWS S3 server access logs.\n', - fields: [ - { - name: 'bucket_owner', - type: 'keyword', - description: 'The canonical user ID of the owner of the source bucket.\n', - }, - { - name: 'bucket', - type: 'keyword', - description: 'The name of the bucket that the request was processed against.\n', - }, - { - name: 'remote_ip', - type: 'ip', - description: 'The apparent internet address of the requester.\n', - }, - { - name: 'requester', - type: 'keyword', - description: - 'The canonical user ID of the requester, or a - for unauthenticated requests.\n', - }, - { - name: 'request_id', - type: 'keyword', - description: 'A string generated by Amazon S3 to uniquely identify each request.\n', - }, - { - name: 'operation', - type: 'keyword', - description: - 'The operation listed here is declared as SOAP.operation, REST.HTTP_method.resource_type, WEBSITE.HTTP_method.resource_type, or BATCH.DELETE.OBJECT.\n', - }, - { - name: 'key', - type: 'keyword', - description: - 'The "key" part of the request, URL encoded, or "-" if the operation does not take a key parameter.\n', - }, - { - name: 'request_uri', - type: 'keyword', - description: 'The Request-URI part of the HTTP request message.\n', - }, - { - name: 'http_status', - type: 'long', - description: 'The numeric HTTP status code of the response.\n', - }, - { - name: 'error_code', - type: 'keyword', - description: 'The Amazon S3 Error Code, or "-" if no error occurred.\n', - }, - { - name: 'bytes_sent', - type: 'long', - description: - 'The number of response bytes sent, excluding HTTP protocol overhead, or "-" if zero.\n', - }, - { - name: 'object_size', - type: 'long', - description: 'The total size of the object in question.\n', - }, - { - name: 'total_time', - type: 'long', - description: - "The number of milliseconds the request was in flight from the server's perspective.\n", - }, - { - name: 'turn_around_time', - type: 'long', - description: - 'The number of milliseconds that Amazon S3 spent processing your request.\n', - }, - { - name: 'referrer', - type: 'keyword', - description: 'The value of the HTTP Referrer header, if present.\n', - }, - { - name: 'user_agent', - type: 'keyword', - description: 'The value of the HTTP User-Agent header.\n', - }, - { - name: 'version_id', - type: 'keyword', - description: - 'The version ID in the request, or "-" if the operation does not take a versionId parameter.\n', - }, - { - name: 'host_id', - type: 'keyword', - description: 'The x-amz-id-2 or Amazon S3 extended request ID.\n', - }, - { - name: 'signature_version', - type: 'keyword', - description: - 'The signature version, SigV2 or SigV4, that was used to authenticate the request or a - for unauthenticated requests.\n', - }, - { - name: 'cipher_suite', - type: 'keyword', - description: - 'The Secure Sockets Layer (SSL) cipher that was negotiated for HTTPS request or a - for HTTP.\n', - }, - { - name: 'authentication_type', - type: 'keyword', - description: - 'The type of request authentication used, AuthHeader for authentication headers, QueryString for query string (pre-signed URL) or a - for unauthenticated requests.\n', - }, - { - name: 'host_header', - type: 'keyword', - description: 'The endpoint used to connect to Amazon S3.\n', - }, - { - name: 'tls_version', - type: 'keyword', - description: - 'The Transport Layer Security (TLS) version negotiated by the client.\n', - }, - ], - }, - { - name: 'vpcflow', - type: 'group', - release: 'beta', - description: 'Fields for AWS VPC flow logs.\n', - fields: [ - { - name: 'version', - type: 'keyword', - description: - 'The VPC Flow Logs version. If you use the default format, the version is 2. If you specify a custom format, the version is 3.\n', - }, - { - name: 'account_id', - type: 'keyword', - description: 'The AWS account ID for the flow log.\n', - }, - { - name: 'interface_id', - type: 'keyword', - description: 'The ID of the network interface for which the traffic is recorded.\n', - }, - { - name: 'action', - type: 'keyword', - description: 'The action that is associated with the traffic, ACCEPT or REJECT.\n', - }, - { - name: 'log_status', - type: 'keyword', - description: 'The logging status of the flow log, OK, NODATA or SKIPDATA.\n', - }, - { - name: 'instance_id', - type: 'keyword', - description: - "The ID of the instance that's associated with network interface for which the traffic is recorded, if the instance is owned by you.\n", - }, - { - name: 'pkt_srcaddr', - type: 'ip', - description: 'The packet-level (original) source IP address of the traffic.\n', - }, - { - name: 'pkt_dstaddr', - type: 'ip', - description: - 'The packet-level (original) destination IP address for the traffic.\n', - }, - { - name: 'vpc_id', - type: 'keyword', - description: - 'The ID of the VPC that contains the network interface for which the traffic is recorded.\n', - }, - { - name: 'subnet_id', - type: 'keyword', - description: - 'The ID of the subnet that contains the network interface for which the traffic is recorded.\n', - }, - { - name: 'tcp_flags', - type: 'keyword', - description: - 'The bitmask value for the following TCP flags: 2=SYN,18=SYN-ACK,1=FIN,4=RST\n', - }, - { - name: 'type', - type: 'keyword', - description: 'The type of traffic: IPv4, IPv6, or EFA.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'azure', - title: 'Azure', - release: 'beta', - description: 'Azure Module\n', - fields: [ - { - name: 'azure', - type: 'group', - description: '\n', - fields: [ - { - name: 'subscription_id', - type: 'keyword', - description: 'Azure subscription ID\n', - }, - { - name: 'correlation_id', - type: 'keyword', - description: 'Correlation ID\n', - }, - { - name: 'tenant_id', - type: 'keyword', - description: 'tenant ID\n', - }, - { - name: 'resource', - type: 'group', - description: 'Resource\n', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Resource ID\n', - }, - { - name: 'group', - type: 'keyword', - description: 'Resource group\n', - }, - { - name: 'provider', - type: 'keyword', - description: 'Resource type/namespace\n', - }, - { - name: 'namespace', - type: 'keyword', - description: 'Resource type/namespace\n', - }, - { - name: 'name', - type: 'keyword', - description: 'Name\n', - }, - { - name: 'authorization_rule', - type: 'keyword', - description: 'Authorization rule\n', - }, - ], - }, - { - name: 'activitylogs', - type: 'group', - release: 'beta', - description: 'Fields for Azure activity logs.\n', - fields: [ - { - name: 'identity', - type: 'group', - description: 'Identity\n', - fields: [ - { - name: 'claims_initiated_by_user', - type: 'group', - description: 'Claims initiated by user\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'Name\n', - }, - { - name: 'givenname', - type: 'keyword', - description: 'Givenname\n', - }, - { - name: 'surname', - type: 'keyword', - description: 'Surname\n', - }, - { - name: 'fullname', - type: 'keyword', - description: 'Fullname\n', - }, - { - name: 'schema', - type: 'keyword', - description: 'Schema\n', - }, - ], - }, - { - name: 'claims.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Claims\n', - }, - { - name: 'authorization', - type: 'group', - description: 'Authorization\n', - fields: [ - { - name: 'scope', - type: 'keyword', - description: 'Scope\n', - }, - { - name: 'action', - type: 'keyword', - description: 'Action\n', - }, - { - name: 'evidence', - type: 'group', - description: 'Evidence\n', - fields: [ - { - name: 'role_assignment_scope', - type: 'keyword', - description: 'Role assignment scope\n', - }, - { - name: 'role_definition_id', - type: 'keyword', - description: 'Role definition ID\n', - }, - { - name: 'role', - type: 'keyword', - description: 'Role\n', - }, - { - name: 'role_assignment_id', - type: 'keyword', - description: 'Role assignment ID\n', - }, - { - name: 'principal_id', - type: 'keyword', - description: 'Principal ID\n', - }, - { - name: 'principal_type', - type: 'keyword', - description: 'Principal type\n', - }, - ], - }, - ], - }, - ], - }, - { - name: 'operation_name', - type: 'keyword', - description: 'Operation name\n', - }, - { - name: 'result_signature', - type: 'keyword', - description: 'Result signature\n', - }, - { - name: 'category', - type: 'keyword', - description: 'Category\n', - }, - { - name: 'properties', - type: 'group', - description: 'Properties\n', - fields: [ - { - name: 'service_request_id', - type: 'keyword', - description: 'Service Request Id\n', - }, - { - name: 'status_code', - type: 'keyword', - description: 'Status code\n', - }, - ], - }, - ], - }, - { - name: 'auditlogs', - type: 'group', - description: 'Fields for Azure audit logs.\n', - fields: [ - { - name: 'operation_name', - type: 'keyword', - description: 'The operation name\n', - }, - { - name: 'operation_version', - type: 'keyword', - description: 'The operation version\n', - }, - { - name: 'identity', - type: 'keyword', - description: 'Identity\n', - }, - { - name: 'tenant_id', - type: 'keyword', - description: 'Tenant ID\n', - }, - { - name: 'result_signature', - type: 'keyword', - description: 'Result signature\n', - }, - { - name: 'properties', - type: 'group', - description: 'The audit log properties\n', - fields: [ - { - name: 'result', - type: 'keyword', - description: 'Log result\n', - }, - { - name: 'activity_display_name', - type: 'keyword', - description: 'Activity display name\n', - }, - { - name: 'result_reason', - type: 'keyword', - description: 'Reason for the log result\n', - }, - { - name: 'correlation_id', - type: 'keyword', - description: 'Correlation ID\n', - }, - { - name: 'logged_by_service', - type: 'keyword', - description: 'Logged by service\n', - }, - { - name: 'operation_type', - type: 'keyword', - description: 'Operation type\n', - }, - { - name: 'id', - type: 'keyword', - description: 'ID\n', - }, - { - name: 'activity_datetime', - type: 'date', - description: 'Activity timestamp\n', - }, - { - name: 'category', - type: 'keyword', - description: 'category\n', - }, - { - name: 'target_resources.*', - type: 'group', - object_type_mapping_type: '*', - description: 'Target resources\n', - fields: [ - { - name: 'display_name', - type: 'keyword', - description: 'Display name\n', - }, - { - name: 'id', - type: 'keyword', - description: 'ID\n', - }, - { - name: 'type', - type: 'keyword', - description: 'Type\n', - }, - { - name: 'ip_address', - type: 'keyword', - description: 'ip Address\n', - }, - { - name: 'user_principal_name', - type: 'keyword', - description: 'User principal name\n', - }, - { - name: 'modified_properties.*', - type: 'group', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Modified properties\n', - fields: [ - { - name: 'new_value', - type: 'keyword', - description: 'New value\n', - }, - { - name: 'display_name', - type: 'keyword', - description: 'Display value\n', - }, - { - name: 'old_value', - type: 'keyword', - description: 'Old value\n', - }, - ], - }, - ], - }, - { - name: 'initiated_by', - type: 'group', - description: 'Information regarding the initiator\n', - fields: [ - { - name: 'app', - type: 'group', - description: 'App\n', - fields: [ - { - name: 'servicePrincipalName', - type: 'keyword', - description: 'Service principal name\n', - }, - { - name: 'displayName', - type: 'keyword', - description: 'Display name\n', - }, - { - name: 'appId', - type: 'keyword', - description: 'App ID\n', - }, - { - name: 'servicePrincipalId', - type: 'keyword', - description: 'Service principal ID\n', - }, - ], - }, - { - name: 'user', - type: 'group', - description: 'User\n', - fields: [ - { - name: 'userPrincipalName', - type: 'keyword', - description: 'User principal name\n', - }, - { - name: 'displayName', - type: 'keyword', - description: 'Display name\n', - }, - { - name: 'id', - type: 'keyword', - description: 'ID\n', - }, - { - name: 'ipAddress', - type: 'keyword', - description: 'ip Address\n', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - name: 'signinlogs', - type: 'group', - description: 'Fields for Azure sign-in logs.\n', - fields: [ - { - name: 'operation_name', - type: 'keyword', - description: 'The operation name\n', - }, - { - name: 'operation_version', - type: 'keyword', - description: 'The operation version\n', - }, - { - name: 'tenant_id', - type: 'keyword', - description: 'Tenant ID\n', - }, - { - name: 'result_signature', - type: 'keyword', - description: 'Result signature\n', - }, - { - name: 'result_description', - type: 'keyword', - description: 'Result description\n', - }, - { - name: 'identity', - type: 'keyword', - description: 'Identity\n', - }, - { - name: 'properties', - type: 'group', - description: 'The signin log properties\n', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'ID\n', - }, - { - name: 'created_at', - type: 'date', - description: 'Created date time\n', - }, - { - name: 'user_display_name', - type: 'keyword', - description: 'User display name\n', - }, - { - name: 'correlation_id', - type: 'keyword', - description: 'Correlation ID\n', - }, - { - name: 'user_principal_name', - type: 'keyword', - description: 'User principal name\n', - }, - { - name: 'user_id', - type: 'keyword', - description: 'User ID\n', - }, - { - name: 'app_id', - type: 'keyword', - description: 'App ID\n', - }, - { - name: 'app_display_name', - type: 'keyword', - description: 'App display name\n', - }, - { - name: 'ip_address', - type: 'keyword', - description: 'Ip address\n', - }, - { - name: 'client_app_used', - type: 'keyword', - description: 'Client app used\n', - }, - { - name: 'conditional_access_status', - type: 'keyword', - description: 'Conditional access status\n', - }, - { - name: 'original_request_id', - type: 'keyword', - description: 'Original request ID\n', - }, - { - name: 'is_interactive', - type: 'keyword', - description: 'Is interactive\n', - }, - { - name: 'token_issuer_name', - type: 'keyword', - description: 'Token issuer name\n', - }, - { - name: 'token_issuer_type', - type: 'keyword', - description: 'Token issuer type\n', - }, - { - name: 'processing_time_ms', - type: 'float', - description: 'Processing time in milliseconds\n', - }, - { - name: 'risk_detail', - type: 'keyword', - description: 'Risk detail\n', - }, - { - name: 'risk_level_aggregated', - type: 'keyword', - description: 'Risk level aggregated\n', - }, - { - name: 'risk_level_during_signin', - type: 'keyword', - description: 'Risk level during signIn\n', - }, - { - name: 'risk_state', - type: 'keyword', - description: 'Risk state\n', - }, - { - name: 'resource_display_name', - type: 'keyword', - description: 'Resource display name\n', - }, - { - name: 'status', - type: 'group', - description: 'Status\n', - fields: [ - { - name: 'error_code', - type: 'keyword', - description: 'Error code\n', - }, - ], - }, - { - name: 'device_detail', - type: 'group', - description: 'Status\n', - fields: [ - { - name: 'device_id', - type: 'keyword', - description: 'Device ID\n', - }, - { - name: 'operating_system', - type: 'keyword', - description: 'Operating system\n', - }, - { - name: 'browser', - type: 'keyword', - description: 'Browser\n', - }, - { - name: 'display_name', - type: 'keyword', - description: 'Display name\n', - }, - { - name: 'trust_type', - type: 'keyword', - description: 'Trust type\n', - }, - ], - }, - { - name: 'service_principal_id', - type: 'keyword', - description: 'Status\n', - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'cef-module', - title: 'CEF', - description: - 'Module for receiving CEF logs over Syslog. The module adds vendor specific fields in addition to the fields the decode_cef processor provides.\n', - fields: [ - { - name: 'forcepoint', - type: 'group', - default_field: false, - description: 'Fields for Forcepoint Custom String mappings\n', - fields: [ - { - name: 'virus_id', - type: 'keyword', - description: 'Virus ID\n', - }, - ], - }, - { - name: 'checkpoint', - type: 'group', - default_field: false, - description: 'Fields for Check Point custom string mappings.\n', - fields: [ - { - name: 'app_risk', - type: 'keyword', - description: 'Application risk.', - }, - { - name: 'app_severity', - type: 'keyword', - description: 'Application threat severity.', - }, - { - name: 'app_sig_id', - type: 'keyword', - description: 'The signature ID which the application was detected by.', - }, - { - name: 'auth_method', - type: 'keyword', - description: 'Password authentication protocol used.', - }, - { - name: 'category', - type: 'keyword', - description: 'Category.', - }, - { - name: 'confidence_level', - type: 'keyword', - description: 'Confidence level determined.', - }, - { - name: 'connectivity_state', - type: 'keyword', - description: 'Connectivity state.', - }, - { - name: 'cookie', - type: 'keyword', - description: 'IKE cookie.', - }, - { - name: 'dst_phone_number', - type: 'keyword', - description: 'Destination IP-Phone.', - }, - { - name: 'email_control', - type: 'keyword', - description: 'Engine name.', - }, - { - name: 'email_id', - type: 'keyword', - description: 'Internal email ID.', - }, - { - name: 'email_recipients_num', - type: 'long', - description: 'Number of recipients.', - }, - { - name: 'email_session_id', - type: 'keyword', - description: 'Internal email session ID.', - }, - { - name: 'email_spool_id', - type: 'keyword', - description: 'Internal email spool ID.', - }, - { - name: 'email_subject', - type: 'keyword', - description: 'Email subject.', - }, - { - name: 'event_count', - type: 'long', - description: 'Number of events associated with the log.', - }, - { - name: 'file_hash', - type: 'keyword', - description: 'File hash (SHA1 or MD5).', - }, - { - name: 'frequency', - type: 'keyword', - description: 'Scan frequency.', - }, - { - name: 'icmp_type', - type: 'long', - description: 'ICMP type.', - }, - { - name: 'icmp_code', - type: 'long', - description: 'ICMP code.', - }, - { - name: 'identity_type', - type: 'keyword', - description: 'Identity type.', - }, - { - name: 'incident_extension', - type: 'keyword', - description: 'Format of original data.', - }, - { - name: 'integrity_av_invoke_type', - type: 'keyword', - description: 'Scan invoke type.', - }, - { - name: 'peer_gateway', - type: 'ip', - description: 'Main IP of the peer Security Gateway.', - }, - { - name: 'performance_impact', - type: 'keyword', - description: 'Protection performance impact.', - }, - { - name: 'protection_id', - type: 'keyword', - description: 'Protection malware ID.', - }, - { - name: 'protection_name', - type: 'keyword', - description: 'Specific signature name of the attack.', - }, - { - name: 'protection_type', - type: 'keyword', - description: 'Type of protection used to detect the attack.', - }, - { - name: 'scan_result', - type: 'keyword', - description: 'Scan result.', - }, - { - name: 'sensor_mode', - type: 'keyword', - description: 'Sensor mode.', - }, - { - name: 'severity', - type: 'keyword', - description: 'Threat severity.', - }, - { - name: 'malware_status', - type: 'keyword', - description: 'Malware status.', - }, - { - name: 'subscription_expiration', - type: 'date', - description: 'The expiration date of the subscription.', - }, - { - name: 'tcp_flags', - type: 'keyword', - description: 'TCP packet flags.', - }, - { - name: 'termination_reason', - type: 'keyword', - description: 'Termination reason.', - }, - { - name: 'update_status', - type: 'keyword', - description: 'Update status.', - }, - { - name: 'user_status', - type: 'keyword', - description: 'User response.', - }, - { - name: 'uuid', - type: 'keyword', - description: 'External ID.', - }, - { - name: 'virus_name', - type: 'keyword', - description: 'Virus name.', - }, - { - name: 'malware_name', - type: 'keyword', - description: 'Malware name.', - }, - { - name: 'malware_family', - type: 'keyword', - description: 'Malware family.', - }, - { - name: 'voip_log_type', - type: 'keyword', - description: 'VoIP log types.', - }, - ], - }, - { - name: 'cef.extensions', - type: 'group', - default_field: false, - description: 'Extra vendor-specific extensions.\n', - fields: [ - { - name: 'cp_app_risk', - type: 'keyword', - }, - { - name: 'cp_severity', - type: 'keyword', - }, - { - name: 'ifname', - type: 'keyword', - }, - { - name: 'inzone', - type: 'keyword', - }, - { - name: 'layer_uuid', - type: 'keyword', - }, - { - name: 'layer_name', - type: 'keyword', - }, - { - name: 'logid', - type: 'keyword', - }, - { - name: 'loguid', - type: 'keyword', - }, - { - name: 'match_id', - type: 'keyword', - }, - { - name: 'nat_addtnl_rulenum', - type: 'keyword', - }, - { - name: 'nat_rulenum', - type: 'keyword', - }, - { - name: 'origin', - type: 'keyword', - }, - { - name: 'originsicname', - type: 'keyword', - }, - { - name: 'outzone', - type: 'keyword', - }, - { - name: 'parent_rule', - type: 'keyword', - }, - { - name: 'product', - type: 'keyword', - }, - { - name: 'rule_action', - type: 'keyword', - }, - { - name: 'rule_uid', - type: 'keyword', - }, - { - name: 'sequencenum', - type: 'keyword', - }, - { - name: 'service_id', - type: 'keyword', - }, - { - name: 'version', - type: 'keyword', - }, - ], - }, - ], - }, - { - key: 'cisco', - title: 'Cisco', - description: 'Module for handling Cisco network device logs.\n', - fields: [ - { - name: 'cisco', - type: 'group', - description: 'Fields from Cisco logs.\n', - fields: [ - { - name: 'asa', - type: 'group', - description: 'Fields for Cisco ASA Firewall.\n', - fields: [ - { - name: 'message_id', - type: 'keyword', - description: 'The Cisco ASA message identifier.\n', - }, - { - name: 'suffix', - type: 'keyword', - example: 'session', - description: 'Optional suffix after %ASA identifier.\n', - }, - { - name: 'source_interface', - type: 'keyword', - description: 'Source interface for the flow or event.\n', - }, - { - name: 'destination_interface', - type: 'keyword', - description: 'Destination interface for the flow or event.\n', - }, - { - name: 'rule_name', - type: 'keyword', - description: 'Name of the Access Control List rule that matched this event.\n', - }, - { - name: 'source_username', - type: 'keyword', - description: 'Name of the user that is the source for this event.\n', - }, - { - name: 'destination_username', - type: 'keyword', - description: 'Name of the user that is the destination for this event.\n', - }, - { - name: 'mapped_source_ip', - type: 'ip', - description: 'The translated source IP address.\n', - }, - { - name: 'mapped_source_port', - type: 'long', - description: 'The translated source port.\n', - }, - { - name: 'mapped_destination_ip', - type: 'ip', - description: 'The translated destination IP address.\n', - }, - { - name: 'mapped_destination_port', - type: 'long', - description: 'The translated destination port.\n', - }, - { - name: 'threat_level', - type: 'keyword', - description: - 'Threat level for malware / botnet traffic. One of very-low, low, moderate, high or very-high.\n', - }, - { - name: 'threat_category', - type: 'keyword', - description: - 'Category for the malware / botnet traffic. For example: virus, botnet, trojan, etc.\n', - }, - { - name: 'connection_id', - type: 'keyword', - description: 'Unique identifier for a flow.\n', - }, - { - name: 'icmp_type', - type: 'short', - description: 'ICMP type.\n', - }, - { - name: 'icmp_code', - type: 'short', - description: 'ICMP code.\n', - }, - { - name: 'connection_type', - type: 'keyword', - default_field: false, - description: 'The VPN connection type\n', - }, - { - name: 'dap_records', - default_field: false, - type: 'keyword', - description: 'The assigned DAP records\n', - }, - ], - }, - { - name: 'ftd', - type: 'group', - description: 'Fields for Cisco Firepower Threat Defense Firewall.\n', - fields: [ - { - name: 'message_id', - type: 'keyword', - description: 'The Cisco FTD message identifier.\n', - }, - { - name: 'suffix', - type: 'keyword', - example: 'session', - description: 'Optional suffix after %FTD identifier.\n', - }, - { - name: 'source_interface', - type: 'keyword', - description: 'Source interface for the flow or event.\n', - }, - { - name: 'destination_interface', - type: 'keyword', - description: 'Destination interface for the flow or event.\n', - }, - { - name: 'rule_name', - type: 'keyword', - description: 'Name of the Access Control List rule that matched this event.\n', - }, - { - name: 'source_username', - type: 'keyword', - description: 'Name of the user that is the source for this event.\n', - }, - { - name: 'destination_username', - type: 'keyword', - description: 'Name of the user that is the destination for this event.\n', - }, - { - name: 'mapped_source_ip', - type: 'ip', - description: 'The translated source IP address. Use ECS source.nat.ip.\n', - }, - { - name: 'mapped_source_port', - type: 'long', - description: 'The translated source port. Use ECS source.nat.port.\n', - }, - { - name: 'mapped_destination_ip', - type: 'ip', - description: 'The translated destination IP address. Use ECS destination.nat.ip.\n', - }, - { - name: 'mapped_destination_port', - type: 'long', - description: 'The translated destination port. Use ECS destination.nat.port.\n', - }, - { - name: 'threat_level', - type: 'keyword', - description: - 'Threat level for malware / botnet traffic. One of very-low, low, moderate, high or very-high.\n', - }, - { - name: 'threat_category', - type: 'keyword', - description: - 'Category for the malware / botnet traffic. For example: virus, botnet, trojan, etc.\n', - }, - { - name: 'connection_id', - type: 'keyword', - description: 'Unique identifier for a flow.\n', - }, - { - name: 'icmp_type', - type: 'short', - description: 'ICMP type.\n', - }, - { - name: 'icmp_code', - type: 'short', - description: 'ICMP code.\n', - }, - { - name: 'security', - type: 'object', - description: 'Raw fields for Security Events.', - }, - { - name: 'connection_type', - type: 'keyword', - default_field: false, - description: 'The VPN connection type\n', - }, - { - name: 'dap_records', - type: 'keyword', - default_field: false, - description: 'The assigned DAP records\n', - }, - ], - }, - { - name: 'ios', - type: 'group', - description: 'Fields for Cisco IOS logs.\n', - fields: [ - { - name: 'access_list', - type: 'keyword', - description: 'Name of the IP access list.\n', - }, - { - name: 'facility', - type: 'keyword', - example: 'SEC', - description: - 'The facility to which the message refers (for example, SNMP, SYS, and so forth). A facility can be a hardware device, a protocol, or a module of the system software. It denotes the source or the cause of the system message.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'coredns', - title: 'Coredns', - description: 'Module for handling logs produced by coredns\n', - fields: [ - { - name: 'coredns', - type: 'group', - description: 'coredns fields after normalization\n', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'id of the DNS transaction\n', - }, - { - name: 'query.size', - type: 'integer', - format: 'bytes', - description: 'size of the DNS query\n', - }, - { - name: 'query.class', - type: 'keyword', - description: 'DNS query class\n', - }, - { - name: 'query.name', - type: 'keyword', - description: 'DNS query name\n', - }, - { - name: 'query.type', - type: 'keyword', - description: 'DNS query type\n', - }, - { - name: 'response.code', - type: 'keyword', - description: 'DNS response code\n', - }, - { - name: 'response.flags', - type: 'keyword', - description: 'DNS response flags\n', - }, - { - name: 'response.size', - type: 'integer', - format: 'bytes', - description: 'size of the DNS response\n', - }, - { - name: 'dnssec_ok', - type: 'boolean', - description: 'dnssec flag\n', - }, - ], - }, - ], - }, - { - key: 'envoyproxy', - title: 'Envoyproxy', - description: 'Module for handling logs produced by envoy\n', - fields: [ - { - name: 'envoyproxy', - type: 'group', - description: 'Fields from envoy proxy logs after normalization\n', - fields: [ - { - name: 'log_type', - type: 'keyword', - description: 'Envoy log type, normally ACCESS\n', - }, - { - name: 'response_flags', - type: 'keyword', - description: 'Response flags\n', - }, - { - name: 'upstream_service_time', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - description: 'Upstream service time in nanoseconds\n', - }, - { - name: 'request_id', - type: 'keyword', - description: 'ID of the request\n', - }, - { - name: 'authority', - type: 'keyword', - description: 'Envoy proxy authority field\n', - }, - { - name: 'proxy_type', - type: 'keyword', - description: 'Envoy proxy type, tcp or http\n', - }, - ], - }, - ], - }, - { - key: 'googlecloud', - title: 'Google Cloud', - description: 'Module for handling logs from Google Cloud.\n', - fields: [ - { - name: 'googlecloud', - type: 'group', - description: 'Fields from Google Cloud logs.\n', - fields: [ - { - name: 'destination.instance', - type: 'group', - description: - 'If the destination of the connection was a VM located on the same VPC, this field is populated with VM instance details. In a Shared VPC configuration, project_id corresponds to the project that owns the instance, usually the service project.\n', - fields: [ - { - name: 'project_id', - type: 'keyword', - description: 'ID of the project containing the VM.\n', - }, - { - name: 'region', - type: 'keyword', - description: 'Region of the VM.\n', - }, - { - name: 'zone', - type: 'keyword', - description: 'Zone of the VM.\n', - }, - ], - }, - { - name: 'destination.vpc', - type: 'group', - description: - 'If the destination of the connection was a VM located on the same VPC, this field is populated with VPC network details. In a Shared VPC configuration, project_id corresponds to that of the host project.\n', - fields: [ - { - name: 'project_id', - type: 'keyword', - description: 'ID of the project containing the VM.\n', - }, - { - name: 'vpc_name', - type: 'keyword', - description: 'VPC on which the VM is operating.\n', - }, - { - name: 'subnetwork_name', - type: 'keyword', - description: 'Subnetwork on which the VM is operating.\n', - }, - ], - }, - { - name: 'source.instance', - type: 'group', - description: - 'If the source of the connection was a VM located on the same VPC, this field is populated with VM instance details. In a Shared VPC configuration, project_id corresponds to the project that owns the instance, usually the service project.\n', - fields: [ - { - name: 'project_id', - type: 'keyword', - description: 'ID of the project containing the VM.\n', - }, - { - name: 'region', - type: 'keyword', - description: 'Region of the VM.\n', - }, - { - name: 'zone', - type: 'keyword', - description: 'Zone of the VM.\n', - }, - ], - }, - { - name: 'source.vpc', - type: 'group', - description: - 'If the source of the connection was a VM located on the same VPC, this field is populated with VPC network details. In a Shared VPC configuration, project_id corresponds to that of the host project.\n', - fields: [ - { - name: 'project_id', - type: 'keyword', - description: 'ID of the project containing the VM.\n', - }, - { - name: 'vpc_name', - type: 'keyword', - description: 'VPC on which the VM is operating.\n', - }, - { - name: 'subnetwork_name', - type: 'keyword', - description: 'Subnetwork on which the VM is operating.\n', - }, - ], - }, - { - name: 'audit', - type: 'group', - description: 'Fields for Google Cloud audit logs.\n', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'Type property.\n', - }, - { - name: 'authentication_info', - type: 'group', - description: 'Authentication information.\n', - fields: [ - { - name: 'principal_email', - type: 'keyword', - description: - 'The email address of the authenticated user making the request.\n', - }, - { - name: 'authority_selector', - type: 'keyword', - description: - 'The authority selector specified by the requestor, if any. It is not guaranteed that the principal was allowed to use this authority.\n', - }, - ], - }, - { - name: 'authorization_info', - type: 'array', - description: 'Authorization information for the operation.\n', - fields: [ - { - name: 'permission', - type: 'keyword', - description: 'The required IAM permission.\n', - }, - { - name: 'granted', - type: 'boolean', - description: - 'Whether or not authorization for resource and permission was granted.\n', - }, - { - name: 'resource_attributes', - type: 'group', - description: 'The attributes of the resource.\n', - fields: [ - { - name: 'service', - type: 'keyword', - description: 'The name of the service.\n', - }, - { - name: 'name', - type: 'keyword', - description: 'The name of the resource.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'The type of the resource.\n', - }, - ], - }, - ], - }, - { - name: 'method_name', - type: 'keyword', - description: - "The name of the service method or operation. For API calls, this should be the name of the API method. For example, 'google.datastore.v1.Datastore.RunQuery'.\n", - }, - { - name: 'num_response_items', - type: 'long', - description: - 'The number of items returned from a List or Query API method, if applicable.\n', - }, - { - name: 'request', - type: 'group', - description: 'The operation request.\n', - fields: [ - { - name: 'proto_name', - type: 'keyword', - description: 'Type property of the request.\n', - }, - { - name: 'filter', - type: 'keyword', - description: 'Filter of the request.\n', - }, - { - name: 'name', - type: 'keyword', - description: 'Name of the request.\n', - }, - { - name: 'resource_name', - type: 'keyword', - description: 'Name of the request resource.\n', - }, - ], - }, - { - name: 'request_metadata', - type: 'group', - description: 'Metadata about the request.\n', - fields: [ - { - name: 'caller_ip', - type: 'ip', - description: 'The IP address of the caller.\n', - }, - { - name: 'caller_supplied_user_agent', - type: 'keyword', - description: - 'The user agent of the caller. This information is not authenticated and should be treated accordingly.\n', - }, - ], - }, - { - name: 'resource_name', - type: 'keyword', - description: - "The resource or collection that is the target of the operation. The name is a scheme-less URI, not including the API service name. For example, 'shelves/SHELF_ID/books'.\n", - }, - { - name: 'resource_location', - type: 'group', - description: 'The location of the resource.\n', - fields: [ - { - name: 'current_locations', - type: 'keyword', - description: 'Current locations of the resource.\n', - }, - ], - }, - { - name: 'service_name', - type: 'keyword', - description: - 'The name of the API service performing the operation. For example, datastore.googleapis.com.\n', - }, - { - name: 'status', - type: 'group', - description: 'The status of the overall operation.\n', - fields: [ - { - name: 'code', - type: 'integer', - description: - 'The status code, which should be an enum value of google.rpc.Code.\n', - }, - { - name: 'message', - type: 'keyword', - description: - 'A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client.\n', - }, - ], - }, - ], - }, - { - name: 'firewall', - type: 'group', - description: 'Fields for Google Cloud Firewall logs.\n', - fields: [ - { - name: 'rule_details', - type: 'group', - description: 'Description of the firewall rule that matched this connection.\n', - fields: [ - { - name: 'priority', - type: 'long', - description: 'The priority for the firewall rule.', - }, - { - name: 'action', - type: 'keyword', - description: 'Action that the rule performs on match.', - }, - { - name: 'direction', - type: 'keyword', - description: 'Direction of traffic that matches this rule.', - }, - { - name: 'reference', - type: 'keyword', - description: 'Reference to the firewall rule.', - }, - { - name: 'source_range', - type: 'keyword', - description: 'List of source ranges that the firewall rule applies to.', - }, - { - name: 'destination_range', - type: 'keyword', - description: 'List of destination ranges that the firewall applies to.', - }, - { - name: 'source_tag', - type: 'keyword', - description: 'List of all the source tags that the firewall rule applies to.\n', - }, - { - name: 'target_tag', - type: 'keyword', - description: 'List of all the target tags that the firewall rule applies to.\n', - }, - { - name: 'ip_port_info', - type: 'array', - description: 'List of ip protocols and applicable port ranges for rules.\n', - }, - { - name: 'source_service_account', - type: 'keyword', - description: - 'List of all the source service accounts that the firewall rule applies to.\n', - }, - { - name: 'target_service_account', - type: 'keyword', - description: - 'List of all the target service accounts that the firewall rule applies to.\n', - }, - ], - }, - ], - }, - { - name: 'vpcflow', - type: 'group', - description: 'Fields for Google Cloud VPC flow logs.\n', - fields: [ - { - name: 'reporter', - type: 'keyword', - description: "The side which reported the flow. Can be either 'SRC' or 'DEST'.\n", - }, - { - name: 'rtt.ms', - type: 'long', - description: - 'Latency as measured (for TCP flows only) during the time interval. This is the time elapsed between sending a SEQ and receiving a corresponding ACK and it contains the network RTT as well as the application related delay.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'ibmmq', - title: 'ibmmq', - description: 'ibmmq Module\n', - release: 'ga', - fields: [ - { - name: 'ibmmq', - type: 'group', - description: '\n', - fields: [ - { - name: 'errorlog', - description: 'IBM MQ error logs', - type: 'group', - fields: [ - { - name: 'installation', - description: - 'This is the installation name which can be given at installation time.\nEach installation of IBM MQ on UNIX, Linux, and Windows, has a unique identifier known as an installation name. The installation name is used to associate things such as queue managers and configuration files with an installation.\n', - type: 'keyword', - }, - { - name: 'qmgr', - description: - 'Name of the queue manager. Queue managers provide queuing services to applications, and manages the queues that belong to them.\n', - type: 'keyword', - }, - { - name: 'arithinsert', - description: 'Changing content based on error.id', - type: 'keyword', - }, - { - name: 'commentinsert', - description: 'Changing content based on error.id', - type: 'keyword', - }, - { - name: 'errordescription', - description: 'Please add description', - example: 'Please add example', - type: 'text', - }, - { - name: 'explanation', - description: 'Explaines the error in more detail', - type: 'keyword', - }, - { - name: 'action', - description: 'Defines what to do when the error occurs', - type: 'keyword', - }, - { - name: 'code', - description: 'Error code.', - type: 'keyword', - }, - ], - }, - ], - }, - ], - }, - { - key: 'iptables', - title: 'iptables', - description: 'Module for handling the iptables logs.\n', - fields: [ - { - name: 'iptables', - type: 'group', - description: 'Fields from the iptables logs.\n', - fields: [ - { - name: 'ether_type', - type: 'long', - description: - 'Value of the ethernet type field identifying the network layer protocol.\n', - }, - { - name: 'flow_label', - type: 'integer', - description: 'IPv6 flow label.\n', - }, - { - name: 'fragment_flags', - type: 'keyword', - description: 'IP fragment flags. A combination of CE, DF and MF.\n', - }, - { - name: 'fragment_offset', - type: 'long', - description: 'Offset of the current IP fragment.\n', - }, - { - name: 'icmp', - type: 'group', - description: 'ICMP fields.\n', - fields: [ - { - name: 'code', - type: 'long', - description: 'ICMP code.\n', - }, - { - name: 'id', - type: 'long', - description: 'ICMP ID.\n', - }, - { - name: 'parameter', - type: 'long', - description: 'ICMP parameter.\n', - }, - { - name: 'redirect', - type: 'ip', - description: 'ICMP redirect address.\n', - }, - { - name: 'seq', - type: 'long', - description: 'ICMP sequence number.\n', - }, - { - name: 'type', - type: 'long', - description: 'ICMP type.\n', - }, - ], - }, - { - name: 'id', - type: 'long', - description: 'Packet identifier.\n', - }, - { - name: 'incomplete_bytes', - type: 'long', - description: 'Number of incomplete bytes.\n', - }, - { - name: 'input_device', - type: 'keyword', - description: 'Device that received the packet.\n', - }, - { - name: 'precedence_bits', - type: 'short', - description: 'IP precedence bits.\n', - }, - { - name: 'tos', - type: 'long', - description: 'IP Type of Service field.\n', - }, - { - name: 'length', - type: 'long', - description: 'Packet length.\n', - }, - { - name: 'output_device', - type: 'keyword', - description: 'Device that output the packet.\n', - }, - { - name: 'tcp', - type: 'group', - description: 'TCP fields.\n', - fields: [ - { - name: 'flags', - type: 'keyword', - description: 'TCP flags.\n', - }, - { - name: 'reserved_bits', - type: 'short', - description: 'TCP reserved bits.\n', - }, - { - name: 'seq', - type: 'long', - description: 'TCP sequence number.\n', - }, - { - name: 'ack', - type: 'long', - description: 'TCP Acknowledgment number.\n', - }, - { - name: 'window', - type: 'long', - description: 'Advertised TCP window size.\n', - }, - ], - }, - { - name: 'ttl', - type: 'integer', - description: 'Time To Live field.\n', - }, - { - name: 'udp', - type: 'group', - description: 'UDP fields.\n', - fields: [ - { - name: 'length', - type: 'long', - description: 'Length of the UDP header and payload.\n', - }, - ], - }, - { - name: 'ubiquiti', - type: 'group', - description: 'Fields for Ubiquiti network devices.\n', - fields: [ - { - name: 'input_zone', - type: 'keyword', - description: 'Input zone.\n', - }, - { - name: 'output_zone', - type: 'keyword', - description: 'Output zone.\n', - }, - { - name: 'rule_number', - type: 'keyword', - description: 'The rule number within the rule set.', - }, - { - name: 'rule_set', - type: 'keyword', - description: 'The rule set name.', - }, - ], - }, - ], - }, - ], - }, - { - key: 'misp', - title: 'MISP', - description: 'Module for handling threat information from MISP.\n', - fields: [ - { - name: 'misp', - type: 'group', - description: 'Fields from MISP threat information.\n', - fields: [ - { - name: 'attack_pattern', - title: 'Attack Pattern', - short: 'Fields that let you store attack patterns', - description: - 'Fields provide support for specifying information about attack patterns.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the threat indicator.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'Name of the attack pattern.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'Description of the attack pattern.\n', - }, - { - name: 'kill_chain_phases', - level: 'extended', - type: 'keyword', - description: 'The kill chain phase(s) to which this attack pattern corresponds.\n', - }, - ], - }, - { - name: 'campaign', - title: 'Campaign', - short: 'Fields that let you store campaign information', - description: 'Fields provide support for specifying information about campaigns.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the campaign.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'Name of the campaign.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'Description of the campaign.\n', - }, - { - name: 'aliases', - level: 'extended', - type: 'text', - description: 'Alternative names used to identify this campaign.\n', - }, - { - name: 'first_seen', - level: 'core', - type: 'date', - description: 'The time that this Campaign was first seen, in RFC3339 format.\n', - }, - { - name: 'last_seen', - level: 'core', - type: 'date', - description: 'The time that this Campaign was last seen, in RFC3339 format.\n', - }, - { - name: 'objective', - level: 'core', - type: 'keyword', - description: - "This field defines the Campaign's primary goal, objective, desired outcome, or intended effect.\n", - }, - ], - }, - { - name: 'course_of_action', - title: 'Course of Action', - short: 'Fields that let you store information about course of action.', - description: - 'A Course of Action is an action taken either to prevent an attack or to respond to an attack that is in progress.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Course of Action.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Course of Action.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'Description of the Course of Action.\n', - }, - ], - }, - { - name: 'identity', - title: 'Identity', - short: 'Fields that let you store information about identity.', - description: - 'Identity can represent actual individuals, organizations, or groups, as well as classes of individuals, organizations, or groups.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Identity.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Identity.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'Description of the Identity.\n', - }, - { - name: 'identity_class', - level: 'core', - type: 'keyword', - description: - 'The type of entity that this Identity describes, e.g., an individual or organization. Open Vocab - identity-class-ov\n', - }, - { - name: 'labels', - level: 'extended', - type: 'keyword', - description: 'The list of roles that this Identity performs.\n', - example: 'CEO\n', - }, - { - name: 'sectors', - level: 'extended', - type: 'keyword', - description: - 'The list of sectors that this Identity belongs to. Open Vocab - industry-sector-ov\n', - }, - { - name: 'contact_information', - level: 'extended', - type: 'text', - description: - 'The contact information (e-mail, phone number, etc.) for this Identity.\n', - }, - ], - }, - { - name: 'intrusion_set', - title: 'Intrusion Set', - short: 'Fields that let you store information about Intrusion Set.', - description: - 'An Intrusion Set is a grouped set of adversary behavior and resources with common properties that is believed to be orchestrated by a single organization.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Intrusion Set.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Intrusion Set.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'Description of the Intrusion Set.\n', - }, - { - name: 'aliases', - level: 'extended', - type: 'text', - description: 'Alternative names used to identify the Intrusion Set.\n', - }, - { - name: 'first_seen', - level: 'extended', - type: 'date', - description: - 'The time that this Intrusion Set was first seen, in RFC3339 format.\n', - }, - { - name: 'last_seen', - level: 'extended', - type: 'date', - description: 'The time that this Intrusion Set was last seen, in RFC3339 format.\n', - }, - { - name: 'goals', - level: 'extended', - type: 'text', - description: - 'The high level goals of this Intrusion Set, namely, what are they trying to do.\n', - }, - { - name: 'resource_level', - level: 'extended', - type: 'text', - description: - 'This defines the organizational level at which this Intrusion Set typically works. Open Vocab - attack-resource-level-ov\n', - }, - { - name: 'primary_motivation', - level: 'extended', - type: 'text', - description: - 'The primary reason, motivation, or purpose behind this Intrusion Set. Open Vocab - attack-motivation-ov\n', - }, - { - name: 'secondary_motivations', - level: 'extended', - type: 'text', - description: - 'The secondary reasons, motivations, or purposes behind this Intrusion Set. Open Vocab - attack-motivation-ov\n', - }, - ], - }, - { - name: 'malware', - title: 'Malware', - short: 'Fields that let you store information about Malware.', - description: - "Malware is a type of TTP that is also known as malicious code and malicious software, refers to a program that is inserted into a system, usually covertly, with the intent of compromising the confidentiality, integrity, or availability of the victim's data, applications, or operating system (OS) or of otherwise annoying or disrupting the victim.\n", - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Malware.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Malware.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'Description of the Malware.\n', - }, - { - name: 'labels', - level: 'core', - type: 'keyword', - description: - 'The type of malware being described. Open Vocab - malware-label-ov. adware,backdoor,bot,ddos,dropper,exploit-kit,keylogger,ransomware, remote-access-trojan,resource-exploitation,rogue-security-software,rootkit, screen-capture,spyware,trojan,virus,worm\n', - }, - { - name: 'kill_chain_phases', - format: 'string', - level: 'extended', - type: 'keyword', - description: - 'The list of kill chain phases for which this Malware instance can be used.\n', - }, - ], - }, - { - name: 'note', - title: 'Note', - short: 'Fields that let you store information about Malware.', - description: - 'A Note is a comment or note containing informative text to help explain the context of one or more STIX Objects (SDOs or SROs) or to provide additional analysis that is not contained in the original object.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Note.\n', - }, - { - name: 'summary', - level: 'extended', - type: 'keyword', - description: 'A brief description used as a summary of the Note.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'The content of the Note.\n', - }, - { - name: 'authors', - level: 'extended', - type: 'keyword', - description: 'The name of the author(s) of this Note.\n', - }, - { - name: 'object_refs', - level: 'extended', - type: 'keyword', - description: - 'The STIX Objects (SDOs and SROs) that the note is being applied to.\n', - }, - ], - }, - { - name: 'threat_indicator', - title: 'Threat Indicator', - short: 'Fields that let you store Threat Indicators', - description: - 'Fields provide support for specifying information about threat indicators, and related matching patterns.\n', - type: 'group', - fields: [ - { - name: 'labels', - level: 'core', - type: 'keyword', - description: 'list of type open-vocab that specifies the type of indicator.\n', - example: 'Domain Watchlist\n', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the threat indicator.\n', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - description: 'Version of the threat indicator.\n', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: 'Type of the threat indicator.\n', - }, - { - name: 'description', - level: 'core', - type: 'text', - description: 'Description of the threat indicator.\n', - }, - { - name: 'feed', - level: 'core', - type: 'text', - description: 'Name of the threat feed.\n', - }, - { - name: 'valid_from', - level: 'core', - type: 'date', - description: - 'The time from which this Indicator should be considered valuable intelligence, in RFC3339 format.\n', - }, - { - name: 'valid_until', - level: 'core', - type: 'date', - description: - 'The time at which this Indicator should no longer be considered valuable intelligence. If the valid_until property is omitted, then there is no constraint on the latest time for which the indicator should be used, in RFC3339 format.\n', - }, - { - name: 'severity', - format: 'string', - level: 'core', - type: 'keyword', - description: 'Threat severity to which this indicator corresponds.\n', - example: 'high', - }, - { - name: 'confidence', - level: 'core', - type: 'keyword', - description: 'Confidence level to which this indicator corresponds.\n', - example: 'high', - }, - { - name: 'kill_chain_phases', - format: 'string', - level: 'extended', - type: 'keyword', - description: 'The kill chain phase(s) to which this indicator corresponds.\n', - }, - { - name: 'mitre_tactic', - format: 'string', - level: 'extended', - type: 'keyword', - description: 'MITRE tactics to which this indicator corresponds.\n', - example: 'Initial Access', - }, - { - name: 'mitre_technique', - format: 'string', - level: 'extended', - type: 'keyword', - description: 'MITRE techniques to which this indicator corresponds.\n', - example: 'Drive-by Compromise', - }, - { - name: 'attack_pattern', - level: 'core', - type: 'keyword', - description: - 'The attack_pattern for this indicator is a STIX Pattern as specified in STIX Version 2.0 Part 5 - STIX Patterning.\n', - example: "[destination:ip = '91.219.29.188/32']\n", - }, - { - name: 'attack_pattern_kql', - level: 'core', - type: 'keyword', - description: - 'The attack_pattern for this indicator is KQL query that matches the attack_pattern specified in the STIX Pattern format.\n', - example: 'destination.ip: "91.219.29.188/32"\n', - }, - { - name: 'negate', - level: 'core', - type: 'boolean', - description: 'When set to true, it specifies the absence of the attack_pattern.\n', - }, - { - name: 'intrusion_set', - level: 'extended', - type: 'keyword', - description: 'Name of the intrusion set if known.\n', - }, - { - name: 'campaign', - level: 'extended', - type: 'keyword', - description: 'Name of the attack campaign if known.\n', - }, - { - name: 'threat_actor', - level: 'extended', - type: 'keyword', - description: 'Name of the threat actor if known.\n', - }, - ], - }, - { - name: 'observed_data', - title: 'Observed Data', - short: 'Fields that let you store information about Observed Data.', - description: - 'Observed data conveys information that was observed on systems and networks, such as log data or network traffic, using the Cyber Observable specification.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Observed Data.\n', - }, - { - name: 'first_observed', - level: 'core', - type: 'date', - description: - 'The beginning of the time window that the data was observed, in RFC3339 format.\n', - }, - { - name: 'last_observed', - level: 'core', - type: 'date', - description: - 'The end of the time window that the data was observed, in RFC3339 format.\n', - }, - { - name: 'number_observed', - level: 'core', - type: 'integer', - description: - 'The number of times the data represented in the objects property was observed. This MUST be an integer between 1 and 999,999,999 inclusive.\n', - }, - { - name: 'objects', - level: 'core', - type: 'keyword', - description: - 'A dictionary of Cyber Observable Objects that describes the single fact that was observed.\n', - }, - ], - }, - { - name: 'report', - title: 'Report', - short: 'Fields that let you store information about Report.', - description: - 'Reports are collections of threat intelligence focused on one or more topics, such as a description of a threat actor, malware, or attack technique, including context and related details.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Report.\n', - }, - { - name: 'labels', - level: 'core', - type: 'keyword', - description: - 'This field is an Open Vocabulary that specifies the primary subject of this report. Open Vocab - report-label-ov. threat-report,attack-pattern,campaign,identity,indicator,malware,observed-data,threat-actor,tool,vulnerability\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Report.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: 'A description that provides more details and context about Report.\n', - }, - { - name: 'published', - level: 'extended', - type: 'date', - description: - 'The date that this report object was officially published by the creator of this report, in RFC3339 format.\n', - }, - { - name: 'object_refs', - level: 'core', - type: 'text', - description: 'Specifies the STIX Objects that are referred to by this Report.\n', - }, - ], - }, - { - name: 'threat_actor', - title: 'Threat Actor', - short: 'Fields that let you store information about Threat Actor.', - description: - 'Threat Actors are actual individuals, groups, or organizations believed to be operating with malicious intent.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Threat Actor.\n', - }, - { - name: 'labels', - level: 'core', - type: 'keyword', - description: - 'This field specifies the type of threat actor. Open Vocab - threat-actor-label-ov. activist,competitor,crime-syndicate,criminal,hacker,insider-accidental,insider-disgruntled,nation-state,sensationalist,spy,terrorist\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify this Threat Actor or Threat Actor group.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: - 'A description that provides more details and context about the Threat Actor.\n', - }, - { - name: 'aliases', - level: 'extended', - type: 'text', - description: 'A list of other names that this Threat Actor is believed to use.\n', - }, - { - name: 'roles', - level: 'extended', - type: 'text', - description: - 'This is a list of roles the Threat Actor plays. Open Vocab - threat-actor-role-ov. agent,director,independent,sponsor,infrastructure-operator,infrastructure-architect,malware-author\n', - }, - { - name: 'goals', - level: 'extended', - type: 'text', - description: - 'The high level goals of this Threat Actor, namely, what are they trying to do.\n', - }, - { - name: 'sophistication', - level: 'extended', - type: 'text', - description: - 'The skill, specific knowledge, special training, or expertise a Threat Actor must have to perform the attack. Open Vocab - threat-actor-sophistication-ov. none,minimal,intermediate,advanced,strategic,expert,innovator\n', - }, - { - name: 'resource_level', - level: 'extended', - type: 'text', - description: - 'This defines the organizational level at which this Threat Actor typically works. Open Vocab - attack-resource-level-ov. individual,club,contest,team,organization,government\n', - }, - { - name: 'primary_motivation', - level: 'extended', - type: 'text', - description: - 'The primary reason, motivation, or purpose behind this Threat Actor. Open Vocab - attack-motivation-ov. accidental,coercion,dominance,ideology,notoriety,organizational-gain,personal-gain,personal-satisfaction,revenge,unpredictable\n', - }, - { - name: 'secondary_motivations', - level: 'extended', - type: 'text', - description: - 'The secondary reasons, motivations, or purposes behind this Threat Actor. Open Vocab - attack-motivation-ov. accidental,coercion,dominance,ideology,notoriety,organizational-gain,personal-gain,personal-satisfaction,revenge,unpredictable\n', - }, - { - name: 'personal_motivations', - level: 'extended', - type: 'text', - description: - 'The personal reasons, motivations, or purposes of the Threat Actor regardless of organizational goals. Open Vocab - attack-motivation-ov. accidental,coercion,dominance,ideology,notoriety,organizational-gain,personal-gain,personal-satisfaction,revenge,unpredictable\n', - }, - ], - }, - { - name: 'tool', - title: 'Tool', - short: 'Fields that let you store information about Tool.', - description: - 'Tools are legitimate software that can be used by threat actors to perform attacks.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Tool.\n', - }, - { - name: 'labels', - level: 'core', - type: 'keyword', - description: - 'The kind(s) of tool(s) being described. Open Vocab - tool-label-ov. denial-of-service,exploitation,information-gathering,network-capture,credential-exploitation,remote-access,vulnerability-scanning\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Tool.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: - 'A description that provides more details and context about the Tool.\n', - }, - { - name: 'tool_version', - level: 'extended', - type: 'keyword', - description: 'The version identifier associated with the Tool.\n', - }, - { - name: 'kill_chain_phases', - level: 'extended', - type: 'text', - description: - 'The list of kill chain phases for which this Tool instance can be used.\n', - }, - ], - }, - { - name: 'vulnerability', - title: 'Vulnerability', - short: 'Fields that let you store information about Vulnerability.', - description: - 'A Vulnerability is a mistake in software that can be directly used by a hacker to gain access to a system or network.\n', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Identifier of the Vulnerability.\n', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'The name used to identify the Vulnerability.\n', - }, - { - name: 'description', - level: 'extended', - type: 'text', - description: - 'A description that provides more details and context about the Vulnerability.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'mssql', - title: 'mssql', - description: 'MS SQL Filebeat Module', - fields: [ - { - name: 'mssql', - type: 'group', - description: 'Fields from the MSSQL log files', - fields: [ - { - name: 'log', - description: 'Common log fields', - type: 'group', - fields: [ - { - name: 'origin', - description: - 'Origin of the message, usually the server but it can also be a recovery process', - type: 'keyword', - }, - ], - }, - ], - }, - ], - }, - { - key: 'netflow-module', - title: 'NetFlow', - description: - 'Module for receiving NetFlow and IPFIX flow records over UDP. The module does not add fields beyond what the netflow input provides.\n', - fields: [], - }, - { - key: 'o365', - title: 'Office 365', - description: 'Module for handling logs from Office 365.\n', - fields: [ - { - name: 'o365.audit', - type: 'group', - default_field: false, - description: 'Fields from Office 365 Management API audit logs.\n', - fields: [ - { - name: 'Actor', - type: 'array', - fields: [ - { - name: 'ID', - type: 'keyword', - }, - { - name: 'Type', - type: 'keyword', - }, - ], - }, - { - name: 'ActorContextId', - type: 'keyword', - }, - { - name: 'ActorIpAddress', - type: 'keyword', - }, - { - name: 'ActorUserId', - type: 'keyword', - }, - { - name: 'ActorYammerUserId', - type: 'keyword', - }, - { - name: 'AlertEntityId', - type: 'keyword', - }, - { - name: 'AlertId', - type: 'keyword', - }, - { - name: 'AlertLinks', - type: 'array', - }, - { - name: 'AlertType', - type: 'keyword', - }, - { - name: 'AppId', - type: 'keyword', - }, - { - name: 'ApplicationDisplayName', - type: 'keyword', - }, - { - name: 'ApplicationId', - type: 'keyword', - }, - { - name: 'AzureActiveDirectoryEventType', - type: 'keyword', - }, - { - name: 'ExchangeMetaData.*', - type: 'object', - }, - { - name: 'Category', - type: 'keyword', - }, - { - name: 'ClientAppId', - type: 'keyword', - }, - { - name: 'ClientInfoString', - type: 'keyword', - }, - { - name: 'ClientIP', - type: 'keyword', - }, - { - name: 'ClientIPAddress', - type: 'keyword', - }, - { - name: 'Comments', - type: 'text', - norms: false, - }, - { - name: 'CorrelationId', - type: 'keyword', - }, - { - name: 'CreationTime', - type: 'keyword', - }, - { - name: 'CustomUniqueId', - type: 'keyword', - }, - { - name: 'Data', - type: 'keyword', - }, - { - name: 'DataType', - type: 'keyword', - }, - { - name: 'EntityType', - type: 'keyword', - }, - { - name: 'EventData', - type: 'keyword', - }, - { - name: 'EventSource', - type: 'keyword', - }, - { - name: 'ExceptionInfo.*', - type: 'object', - }, - { - name: 'ExtendedProperties.*', - type: 'object', - }, - { - name: 'ExternalAccess', - type: 'keyword', - }, - { - name: 'GroupName', - type: 'keyword', - }, - { - name: 'Id', - type: 'keyword', - }, - { - name: 'ImplicitShare', - type: 'keyword', - }, - { - name: 'IncidentId', - type: 'keyword', - }, - { - name: 'InternalLogonType', - type: 'keyword', - }, - { - name: 'InterSystemsId', - type: 'keyword', - }, - { - name: 'IntraSystemId', - type: 'keyword', - }, - { - name: 'Item.*', - type: 'object', - }, - { - name: 'Item.*.*', - type: 'object', - }, - { - name: 'ItemName', - type: 'keyword', - }, - { - name: 'ItemType', - type: 'keyword', - }, - { - name: 'ListId', - type: 'keyword', - }, - { - name: 'ListItemUniqueId', - type: 'keyword', - }, - { - name: 'LogonError', - type: 'keyword', - }, - { - name: 'LogonType', - type: 'keyword', - }, - { - name: 'LogonUserSid', - type: 'keyword', - }, - { - name: 'MailboxGuid', - type: 'keyword', - }, - { - name: 'MailboxOwnerMasterAccountSid', - type: 'keyword', - }, - { - name: 'MailboxOwnerSid', - type: 'keyword', - }, - { - name: 'MailboxOwnerUPN', - type: 'keyword', - }, - { - name: 'Members', - type: 'array', - }, - { - name: 'Members.*', - type: 'object', - }, - { - name: 'ModifiedProperties.*.*', - type: 'object', - }, - { - name: 'Name', - type: 'keyword', - }, - { - name: 'ObjectId', - type: 'keyword', - }, - { - name: 'Operation', - type: 'keyword', - }, - { - name: 'OrganizationId', - type: 'keyword', - }, - { - name: 'OrganizationName', - type: 'keyword', - }, - { - name: 'OriginatingServer', - type: 'keyword', - }, - { - name: 'Parameters.*', - type: 'object', - }, - { - name: 'PolicyDetails', - type: 'array', - }, - { - name: 'PolicyId', - type: 'keyword', - }, - { - name: 'RecordType', - type: 'keyword', - }, - { - name: 'ResultStatus', - type: 'keyword', - }, - { - name: 'SensitiveInfoDetectionIsIncluded', - type: 'keyword', - }, - { - name: 'SharePointMetaData.*', - type: 'object', - }, - { - name: 'SessionId', - type: 'keyword', - }, - { - name: 'Severity', - type: 'keyword', - }, - { - name: 'Site', - type: 'keyword', - }, - { - name: 'SiteUrl', - type: 'keyword', - }, - { - name: 'Source', - type: 'keyword', - }, - { - name: 'SourceFileExtension', - type: 'keyword', - }, - { - name: 'SourceFileName', - type: 'keyword', - }, - { - name: 'SourceRelativeUrl', - type: 'keyword', - }, - { - name: 'Status', - type: 'keyword', - }, - { - name: 'SupportTicketId', - type: 'keyword', - }, - { - name: 'Target', - type: 'array', - fields: [ - { - name: 'ID', - type: 'keyword', - }, - { - name: 'Type', - type: 'keyword', - }, - ], - }, - { - name: 'TargetContextId', - type: 'keyword', - }, - { - name: 'TargetUserOrGroupName', - type: 'keyword', - }, - { - name: 'TargetUserOrGroupType', - type: 'keyword', - }, - { - name: 'TeamName', - type: 'keyword', - }, - { - name: 'TeamGuid', - type: 'keyword', - }, - { - name: 'UniqueSharingId', - type: 'keyword', - }, - { - name: 'UserAgent', - type: 'keyword', - }, - { - name: 'UserId', - type: 'keyword', - }, - { - name: 'UserKey', - type: 'keyword', - }, - { - name: 'UserType', - type: 'keyword', - }, - { - name: 'Version', - type: 'keyword', - }, - { - name: 'WebId', - type: 'keyword', - }, - { - name: 'Workload', - type: 'keyword', - }, - { - name: 'YammerNetworkId', - type: 'keyword', - }, - ], - }, - ], - }, - { - key: 'okta', - title: 'Okta', - description: 'Module for handling system logs from Okta.\n', - fields: [ - { - name: 'okta', - type: 'group', - default_field: false, - description: 'Fields from Okta.\n', - fields: [ - { - name: 'uuid', - title: 'UUID', - short: 'The unique identifier of the Okta LogEvent.', - description: 'The unique identifier of the Okta LogEvent.\n', - type: 'keyword', - }, - { - name: 'event_type', - title: 'Event Type', - short: 'The type of the LogEvent.', - description: 'The type of the LogEvent.\n', - type: 'keyword', - }, - { - name: 'version', - title: 'Version', - short: 'The version of the LogEvent.', - description: 'The version of the LogEvent.\n', - type: 'keyword', - }, - { - name: 'severity', - title: 'Severity', - short: 'The severity of the LogEvent.', - description: - 'The severity of the LogEvent. Must be one of DEBUG, INFO, WARN, or ERROR.\n', - type: 'keyword', - }, - { - name: 'display_message', - title: 'Display Message', - short: 'The display message of the LogEvent.', - description: 'The display message of the LogEvent.\n', - type: 'keyword', - }, - { - name: 'actor', - title: 'Actor', - short: 'Fields of the actor for the LogEvent.', - description: 'Fields that let you store information of the actor for the LogEvent.\n', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Identifier of the actor.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'Type of the actor.\n', - }, - { - name: 'alternate_id', - type: 'keyword', - description: 'Alternate identifier of the actor.\n', - }, - { - name: 'display_name', - type: 'keyword', - description: 'Display name of the actor.\n', - }, - ], - }, - { - name: 'client', - title: 'Client', - short: 'Fields about the client of the actor.', - description: 'Fields that let you store information about the client of the actor.\n', - type: 'group', - fields: [ - { - name: 'ip', - type: 'ip', - description: 'The IP address of the client.\n', - }, - { - name: 'user_agent', - description: 'Fields about the user agent information of the client.\n', - type: 'group', - fields: [ - { - name: 'raw_user_agent', - type: 'keyword', - description: 'The raw informaton of the user agent.\n', - }, - { - name: 'os', - type: 'keyword', - description: 'The OS informaton.\n', - }, - { - name: 'browser', - type: 'keyword', - description: 'The browser informaton of the client.\n', - }, - ], - }, - { - name: 'zone', - type: 'keyword', - description: 'The zone information of the client.\n', - }, - { - name: 'device', - type: 'keyword', - description: 'The information of the client device.\n', - }, - { - name: 'id', - type: 'keyword', - description: 'The identifier of the client.\n', - }, - ], - }, - { - name: 'outcome', - title: 'Outcome of the LogEvent.', - short: 'Fields that let you store information about the outcome.', - description: 'Fields that let you store information about the outcome.\n', - type: 'group', - fields: [ - { - name: 'reason', - type: 'keyword', - description: 'The reason of the outcome.\n', - }, - { - name: 'result', - type: 'keyword', - description: - 'The result of the outcome. Must be one of: SUCCESS, FAILURE, SKIPPED, ALLOW, DENY, CHALLENGE, UNKNOWN.\n', - }, - ], - }, - { - name: 'target', - title: 'Target', - short: 'The list of targets.', - description: 'The list of targets.\n', - type: 'array', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Identifier of the actor.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'Type of the actor.\n', - }, - { - name: 'alternate_id', - type: 'keyword', - description: 'Alternate identifier of the actor.\n', - }, - { - name: 'display_name', - type: 'keyword', - description: 'Display name of the actor.\n', - }, - ], - }, - { - name: 'transaction', - title: 'Transaction', - short: 'Fields that let you store information about related transaction.', - description: 'Fields that let you store information about related transaction.\n', - type: 'group', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'Identifier of the transaction.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'The type of transaction. Must be one of "WEB", "JOB".\n', - }, - ], - }, - { - name: 'debug_context', - title: 'Debug Context', - short: 'Fields that let you store information about the debug context.', - description: 'Fields that let you store information about the debug context.\n', - type: 'group', - fields: [ - { - name: 'debug_data', - description: 'The debug data.\n', - type: 'group', - fields: [ - { - name: 'device_fingerprint', - type: 'keyword', - description: 'The fingerprint of the device.\n', - }, - { - name: 'request_id', - type: 'keyword', - description: 'The identifier of the request.\n', - }, - { - name: 'request_uri', - type: 'keyword', - description: 'The request URI.\n', - }, - { - name: 'threat_suspected', - type: 'keyword', - description: 'Threat suspected.\n', - }, - { - name: 'url', - type: 'keyword', - description: 'The URL.\n', - }, - ], - }, - ], - }, - { - name: 'authentication_context', - title: 'Authentication Context', - short: 'Fields that let you store information about authentication context.', - description: 'Fields that let you store information about authentication context.\n', - type: 'group', - fields: [ - { - name: 'authentication_provider', - type: 'keyword', - description: - 'The information about the authentication provider. Must be one of OKTA_AUTHENTICATION_PROVIDER, ACTIVE_DIRECTORY, LDAP, FEDERATION, SOCIAL, FACTOR_PROVIDER.\n', - }, - { - name: 'authentication_step', - type: 'integer', - description: 'The authentication step.\n', - }, - { - name: 'credential_provider', - type: 'keyword', - description: - 'The information about credential provider. Must be one of OKTA_CREDENTIAL_PROVIDER, RSA, SYMANTEC, GOOGLE, DUO, YUBIKEY.\n', - }, - { - name: 'credential_type', - type: 'keyword', - description: - 'The information about credential type. Must be one of OTP, SMS, PASSWORD, ASSERTION, IWA, EMAIL, OAUTH2, JWT, CERTIFICATE, PRE_SHARED_SYMMETRIC_KEY, OKTA_CLIENT_SESSION, DEVICE_UDID.\n', - }, - { - name: 'issuer', - description: 'The information about the issuer.\n', - type: 'array', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'The identifier of the issuer.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'The type of the issuer.\n', - }, - ], - }, - { - name: 'external_session_id', - type: 'keyword', - description: 'The session identifer of the external session if any.\n', - }, - { - name: 'interface', - type: 'keyword', - description: 'The interface used. e.g., Outlook, Office365, wsTrust\n', - }, - ], - }, - { - name: 'security_context', - title: 'Security Context', - short: 'Fields that let you store information about security context.', - description: 'Fields that let you store information about security context.\n', - type: 'group', - fields: [ - { - name: 'as', - type: 'group', - description: 'The autonomous system.\n', - fields: [ - { - name: 'number', - type: 'integer', - description: 'The AS number.\n', - }, - { - name: 'organization', - type: 'group', - description: 'The organization that owns the AS number.\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'The organization name.\n', - }, - ], - }, - ], - }, - { - name: 'isp', - type: 'keyword', - description: 'The Internet Service Provider.\n', - }, - { - name: 'domain', - type: 'keyword', - description: 'The domain name.\n', - }, - { - name: 'is_proxy', - type: 'boolean', - description: 'Whether it is a proxy or not.\n', - }, - ], - }, - { - name: 'request', - title: 'Request', - short: 'Fields that let you store information about the request.', - description: - 'Fields that let you store information about the request, in the form of list of ip_chain.\n', - type: 'group', - fields: [ - { - name: 'ip_chain', - description: 'List of ip_chain objects.\n', - type: 'group', - fields: [ - { - name: 'ip', - type: 'ip', - description: 'IP address.\n', - }, - { - name: 'version', - type: 'keyword', - description: 'IP version. Must be one of V4, V6.\n', - }, - { - name: 'source', - type: 'keyword', - description: 'Source information.\n', - }, - { - name: 'geographical_context', - description: 'Geographical information.\n', - type: 'group', - fields: [ - { - name: 'city', - type: 'keyword', - description: 'The city.', - }, - { - name: 'state', - type: 'keyword', - description: 'The state.', - }, - { - name: 'postal_code', - type: 'keyword', - description: 'The postal code.', - }, - { - name: 'country', - type: 'keyword', - description: 'The country.', - }, - { - name: 'geolocation', - description: 'Geolocation information.\n', - type: 'geo_point', - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'panw', - title: 'panw', - description: 'Module for Palo Alto Networks (PAN-OS)\n', - fields: [ - { - name: 'panw', - type: 'group', - description: 'Fields from the panw module.\n', - fields: [ - { - name: 'panos', - type: 'group', - description: 'Fields for the Palo Alto Networks PAN-OS logs.\n', - fields: [ - { - name: 'ruleset', - type: 'keyword', - description: 'Name of the rule that matched this session.\n', - }, - { - name: 'source', - type: 'group', - description: 'Fields to extend the top-level source object.\n', - fields: [ - { - name: 'zone', - type: 'keyword', - description: 'Source zone for this session.\n', - }, - { - name: 'interface', - type: 'keyword', - description: 'Source interface for this session.\n', - }, - { - name: 'nat', - type: 'group', - description: 'Post-NAT source address, if source NAT is performed.\n', - fields: [ - { - name: 'ip', - type: 'ip', - description: 'Post-NAT source IP.\n', - }, - { - name: 'port', - type: 'long', - description: 'Post-NAT source port.\n', - }, - ], - }, - ], - }, - { - name: 'destination', - type: 'group', - description: 'Fields to extend the top-level destination object.\n', - fields: [ - { - name: 'zone', - type: 'keyword', - description: 'Destination zone for this session.\n', - }, - { - name: 'interface', - type: 'keyword', - description: 'Destination interface for this session.\n', - }, - { - name: 'nat', - type: 'group', - description: 'Post-NAT destination address, if destination NAT is performed.\n', - fields: [ - { - name: 'ip', - type: 'ip', - description: 'Post-NAT destination IP.\n', - }, - { - name: 'port', - type: 'long', - description: 'Post-NAT destination port.\n', - }, - ], - }, - ], - }, - { - name: 'network', - type: 'group', - description: 'Fields to extend the top-level network object.\n', - fields: [ - { - name: 'pcap_id', - type: 'keyword', - description: 'Packet capture ID for a threat.\n', - }, - { - name: 'nat', - type: 'group', - fields: [ - { - name: 'community_id', - type: 'keyword', - description: 'Community ID flow-hash for the NAT 5-tuple.\n', - }, - ], - }, - ], - }, - { - name: 'file', - type: 'group', - description: 'Fields to extend the top-level file object.\n', - fields: [ - { - name: 'hash', - description: - 'Binary hash for a threat file sent to be analyzed by the WildFire service.\n', - type: 'keyword', - }, - ], - }, - { - name: 'url', - type: 'group', - description: 'Fields to extend the top-level url object.\n', - fields: [ - { - name: 'category', - type: 'keyword', - description: - "For threat URLs, it's the URL category. For WildFire, the verdict on the file and is either 'malicious', 'grayware', or 'benign'.\n", - }, - ], - }, - { - name: 'flow_id', - type: 'keyword', - description: 'Internal numeric identifier for each session.\n', - }, - { - name: 'sequence_number', - type: 'long', - description: - 'Log entry identifier that is incremented sequentially. Unique for each log type.\n', - }, - { - name: 'threat.resource', - type: 'keyword', - description: 'URL or file name for a threat.\n', - }, - { - name: 'threat.id', - type: 'keyword', - description: 'Palo Alto Networks identifier for the threat.\n', - }, - { - name: 'threat.name', - type: 'keyword', - description: 'Palo Alto Networks name for the threat.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'rabbitmq', - title: 'RabbitMQ', - description: 'RabbitMQ Module\n', - fields: [ - { - name: 'rabbitmq', - type: 'group', - description: '\n', - fields: [ - { - name: 'log', - type: 'group', - description: 'RabbitMQ log files\n', - fields: [ - { - name: 'pid', - type: 'keyword', - description: 'The Erlang process id', - example: '<0.222.0>', - }, - ], - }, - ], - }, - ], - }, - { - key: 'suricata', - title: 'Suricata', - description: 'Module for handling the EVE JSON logs produced by Suricata.\n', - fields: [ - { - name: 'suricata', - type: 'group', - description: 'Fields from the Suricata EVE log file.\n', - fields: [ - { - name: 'eve', - type: 'group', - description: 'Fields exported by the EVE JSON logs\n', - fields: [ - { - name: 'event_type', - type: 'keyword', - }, - { - name: 'app_proto_orig', - type: 'keyword', - }, - { - name: 'tcp', - type: 'group', - fields: [ - { - name: 'tcp_flags', - type: 'keyword', - }, - { - name: 'psh', - type: 'boolean', - }, - { - name: 'tcp_flags_tc', - type: 'keyword', - }, - { - name: 'ack', - type: 'boolean', - }, - { - name: 'syn', - type: 'boolean', - }, - { - name: 'state', - type: 'keyword', - }, - { - name: 'tcp_flags_ts', - type: 'keyword', - }, - { - name: 'rst', - type: 'boolean', - }, - { - name: 'fin', - type: 'boolean', - }, - ], - }, - { - name: 'fileinfo', - type: 'group', - fields: [ - { - name: 'sha1', - type: 'keyword', - }, - { - name: 'filename', - type: 'alias', - path: 'file.path', - }, - { - name: 'tx_id', - type: 'long', - }, - { - name: 'state', - type: 'keyword', - }, - { - name: 'stored', - type: 'boolean', - }, - { - name: 'gaps', - type: 'boolean', - }, - { - name: 'sha256', - type: 'keyword', - }, - { - name: 'md5', - type: 'keyword', - }, - { - name: 'size', - type: 'alias', - path: 'file.size', - }, - ], - }, - { - name: 'icmp_type', - type: 'long', - }, - { - name: 'dest_port', - type: 'alias', - path: 'destination.port', - }, - { - name: 'src_port', - type: 'alias', - path: 'source.port', - }, - { - name: 'proto', - type: 'alias', - path: 'network.transport', - }, - { - name: 'pcap_cnt', - type: 'long', - }, - { - name: 'src_ip', - type: 'alias', - path: 'source.ip', - }, - { - name: 'dns', - type: 'group', - fields: [ - { - name: 'type', - type: 'keyword', - }, - { - name: 'rrtype', - type: 'keyword', - }, - { - name: 'rrname', - type: 'keyword', - }, - { - name: 'rdata', - type: 'keyword', - }, - { - name: 'tx_id', - type: 'long', - }, - { - name: 'ttl', - type: 'long', - }, - { - name: 'rcode', - type: 'keyword', - }, - { - name: 'id', - type: 'long', - }, - ], - }, - { - name: 'flow_id', - type: 'keyword', - }, - { - name: 'email', - type: 'group', - fields: [ - { - name: 'status', - type: 'keyword', - }, - ], - }, - { - name: 'dest_ip', - type: 'alias', - path: 'destination.ip', - }, - { - name: 'icmp_code', - type: 'long', - }, - { - name: 'http', - type: 'group', - fields: [ - { - name: 'status', - type: 'alias', - path: 'http.response.status_code', - }, - { - name: 'redirect', - type: 'keyword', - }, - { - name: 'http_user_agent', - type: 'alias', - path: 'user_agent.original', - }, - { - name: 'protocol', - type: 'keyword', - }, - { - name: 'http_refer', - type: 'alias', - path: 'http.request.referrer', - }, - { - name: 'url', - type: 'alias', - path: 'url.original', - }, - { - name: 'hostname', - type: 'alias', - path: 'url.domain', - }, - { - name: 'length', - type: 'alias', - path: 'http.response.body.bytes', - }, - { - name: 'http_method', - type: 'alias', - path: 'http.request.method', - }, - { - name: 'http_content_type', - type: 'keyword', - }, - ], - }, - { - name: 'timestamp', - type: 'alias', - path: '@timestamp', - }, - { - name: 'in_iface', - type: 'keyword', - }, - { - name: 'alert', - type: 'group', - fields: [ - { - name: 'category', - type: 'keyword', - }, - { - name: 'severity', - type: 'alias', - path: 'event.severity', - }, - { - name: 'rev', - type: 'long', - }, - { - name: 'gid', - type: 'long', - }, - { - name: 'signature', - type: 'keyword', - }, - { - name: 'action', - type: 'alias', - path: 'event.outcome', - }, - { - name: 'signature_id', - type: 'long', - }, - ], - }, - { - name: 'ssh', - type: 'group', - fields: [ - { - name: 'client', - type: 'group', - fields: [ - { - name: 'proto_version', - type: 'keyword', - }, - { - name: 'software_version', - type: 'keyword', - }, - ], - }, - { - name: 'server', - type: 'group', - fields: [ - { - name: 'proto_version', - type: 'keyword', - }, - { - name: 'software_version', - type: 'keyword', - }, - ], - }, - ], - }, - { - name: 'stats', - type: 'group', - fields: [ - { - name: 'capture', - type: 'group', - fields: [ - { - name: 'kernel_packets', - type: 'long', - }, - { - name: 'kernel_drops', - type: 'long', - }, - { - name: 'kernel_ifdrops', - type: 'long', - }, - ], - }, - { - name: 'uptime', - type: 'long', - }, - { - name: 'detect', - type: 'group', - fields: [ - { - name: 'alert', - type: 'long', - }, - ], - }, - { - name: 'http', - type: 'group', - fields: [ - { - name: 'memcap', - type: 'long', - }, - { - name: 'memuse', - type: 'long', - }, - ], - }, - { - name: 'file_store', - type: 'group', - fields: [ - { - name: 'open_files', - type: 'long', - }, - ], - }, - { - name: 'defrag', - type: 'group', - fields: [ - { - name: 'max_frag_hits', - type: 'long', - }, - { - name: 'ipv4', - type: 'group', - fields: [ - { - name: 'timeouts', - type: 'long', - }, - { - name: 'fragments', - type: 'long', - }, - { - name: 'reassembled', - type: 'long', - }, - ], - }, - { - name: 'ipv6', - type: 'group', - fields: [ - { - name: 'timeouts', - type: 'long', - }, - { - name: 'fragments', - type: 'long', - }, - { - name: 'reassembled', - type: 'long', - }, - ], - }, - ], - }, - { - name: 'flow', - type: 'group', - fields: [ - { - name: 'tcp_reuse', - type: 'long', - }, - { - name: 'udp', - type: 'long', - }, - { - name: 'memcap', - type: 'long', - }, - { - name: 'emerg_mode_entered', - type: 'long', - }, - { - name: 'emerg_mode_over', - type: 'long', - }, - { - name: 'tcp', - type: 'long', - }, - { - name: 'icmpv6', - type: 'long', - }, - { - name: 'icmpv4', - type: 'long', - }, - { - name: 'spare', - type: 'long', - }, - { - name: 'memuse', - type: 'long', - }, - ], - }, - { - name: 'tcp', - type: 'group', - fields: [ - { - name: 'pseudo_failed', - type: 'long', - }, - { - name: 'ssn_memcap_drop', - type: 'long', - }, - { - name: 'insert_data_overlap_fail', - type: 'long', - }, - { - name: 'sessions', - type: 'long', - }, - { - name: 'pseudo', - type: 'long', - }, - { - name: 'synack', - type: 'long', - }, - { - name: 'insert_data_normal_fail', - type: 'long', - }, - { - name: 'syn', - type: 'long', - }, - { - name: 'memuse', - type: 'long', - }, - { - name: 'invalid_checksum', - type: 'long', - }, - { - name: 'segment_memcap_drop', - type: 'long', - }, - { - name: 'overlap', - type: 'long', - }, - { - name: 'insert_list_fail', - type: 'long', - }, - { - name: 'rst', - type: 'long', - }, - { - name: 'stream_depth_reached', - type: 'long', - }, - { - name: 'reassembly_memuse', - type: 'long', - }, - { - name: 'reassembly_gap', - type: 'long', - }, - { - name: 'overlap_diff_data', - type: 'long', - }, - { - name: 'no_flow', - type: 'long', - }, - ], - }, - { - name: 'decoder', - type: 'group', - fields: [ - { - name: 'avg_pkt_size', - type: 'long', - }, - { - name: 'bytes', - type: 'long', - }, - { - name: 'tcp', - type: 'long', - }, - { - name: 'raw', - type: 'long', - }, - { - name: 'ppp', - type: 'long', - }, - { - name: 'vlan_qinq', - type: 'long', - }, - { - name: 'null', - type: 'long', - }, - { - name: 'ltnull', - type: 'group', - fields: [ - { - name: 'unsupported_type', - type: 'long', - }, - { - name: 'pkt_too_small', - type: 'long', - }, - ], - }, - { - name: 'invalid', - type: 'long', - }, - { - name: 'gre', - type: 'long', - }, - { - name: 'ipv4', - type: 'long', - }, - { - name: 'ipv6', - type: 'long', - }, - { - name: 'pkts', - type: 'long', - }, - { - name: 'ipv6_in_ipv6', - type: 'long', - }, - { - name: 'ipraw', - type: 'group', - fields: [ - { - name: 'invalid_ip_version', - type: 'long', - }, - ], - }, - { - name: 'pppoe', - type: 'long', - }, - { - name: 'udp', - type: 'long', - }, - { - name: 'dce', - type: 'group', - fields: [ - { - name: 'pkt_too_small', - type: 'long', - }, - ], - }, - { - name: 'vlan', - type: 'long', - }, - { - name: 'sctp', - type: 'long', - }, - { - name: 'max_pkt_size', - type: 'long', - }, - { - name: 'teredo', - type: 'long', - }, - { - name: 'mpls', - type: 'long', - }, - { - name: 'sll', - type: 'long', - }, - { - name: 'icmpv6', - type: 'long', - }, - { - name: 'icmpv4', - type: 'long', - }, - { - name: 'erspan', - type: 'long', - }, - { - name: 'ethernet', - type: 'long', - }, - { - name: 'ipv4_in_ipv6', - type: 'long', - }, - { - name: 'ieee8021ah', - type: 'long', - }, - ], - }, - { - name: 'dns', - type: 'group', - fields: [ - { - name: 'memcap_global', - type: 'long', - }, - { - name: 'memcap_state', - type: 'long', - }, - { - name: 'memuse', - type: 'long', - }, - ], - }, - { - name: 'flow_mgr', - type: 'group', - fields: [ - { - name: 'rows_busy', - type: 'long', - }, - { - name: 'flows_timeout', - type: 'long', - }, - { - name: 'flows_notimeout', - type: 'long', - }, - { - name: 'rows_skipped', - type: 'long', - }, - { - name: 'closed_pruned', - type: 'long', - }, - { - name: 'new_pruned', - type: 'long', - }, - { - name: 'flows_removed', - type: 'long', - }, - { - name: 'bypassed_pruned', - type: 'long', - }, - { - name: 'est_pruned', - type: 'long', - }, - { - name: 'flows_timeout_inuse', - type: 'long', - }, - { - name: 'flows_checked', - type: 'long', - }, - { - name: 'rows_maxlen', - type: 'long', - }, - { - name: 'rows_checked', - type: 'long', - }, - { - name: 'rows_empty', - type: 'long', - }, - ], - }, - { - name: 'app_layer', - type: 'group', - fields: [ - { - name: 'flow', - type: 'group', - fields: [ - { - name: 'tls', - type: 'long', - }, - { - name: 'ftp', - type: 'long', - }, - { - name: 'http', - type: 'long', - }, - { - name: 'failed_udp', - type: 'long', - }, - { - name: 'dns_udp', - type: 'long', - }, - { - name: 'dns_tcp', - type: 'long', - }, - { - name: 'smtp', - type: 'long', - }, - { - name: 'failed_tcp', - type: 'long', - }, - { - name: 'msn', - type: 'long', - }, - { - name: 'ssh', - type: 'long', - }, - { - name: 'imap', - type: 'long', - }, - { - name: 'dcerpc_udp', - type: 'long', - }, - { - name: 'dcerpc_tcp', - type: 'long', - }, - { - name: 'smb', - type: 'long', - }, - ], - }, - { - name: 'tx', - type: 'group', - fields: [ - { - name: 'tls', - type: 'long', - }, - { - name: 'ftp', - type: 'long', - }, - { - name: 'http', - type: 'long', - }, - { - name: 'dns_udp', - type: 'long', - }, - { - name: 'dns_tcp', - type: 'long', - }, - { - name: 'smtp', - type: 'long', - }, - { - name: 'ssh', - type: 'long', - }, - { - name: 'dcerpc_udp', - type: 'long', - }, - { - name: 'dcerpc_tcp', - type: 'long', - }, - { - name: 'smb', - type: 'long', - }, - ], - }, - ], - }, - ], - }, - { - name: 'tls', - type: 'group', - fields: [ - { - name: 'notbefore', - type: 'date', - }, - { - name: 'issuerdn', - type: 'keyword', - }, - { - name: 'sni', - type: 'keyword', - }, - { - name: 'version', - type: 'keyword', - }, - { - name: 'session_resumed', - type: 'boolean', - }, - { - name: 'fingerprint', - type: 'keyword', - }, - { - name: 'serial', - type: 'keyword', - }, - { - name: 'notafter', - type: 'date', - }, - { - name: 'subject', - type: 'keyword', - }, - ], - }, - { - name: 'app_proto_ts', - type: 'keyword', - }, - { - name: 'flow', - type: 'group', - fields: [ - { - name: 'bytes_toclient', - type: 'alias', - path: 'destination.bytes', - }, - { - name: 'start', - type: 'alias', - path: 'event.start', - }, - { - name: 'pkts_toclient', - type: 'alias', - path: 'destination.packets', - }, - { - name: 'age', - type: 'long', - }, - { - name: 'state', - type: 'keyword', - }, - { - name: 'bytes_toserver', - type: 'alias', - path: 'source.bytes', - }, - { - name: 'reason', - type: 'keyword', - }, - { - name: 'pkts_toserver', - type: 'alias', - path: 'source.packets', - }, - { - name: 'end', - type: 'date', - }, - { - name: 'alerted', - type: 'boolean', - }, - ], - }, - { - name: 'app_proto', - type: 'alias', - path: 'network.protocol', - }, - { - name: 'tx_id', - type: 'long', - }, - { - name: 'app_proto_tc', - type: 'keyword', - }, - { - name: 'smtp', - type: 'group', - fields: [ - { - name: 'rcpt_to', - type: 'keyword', - }, - { - name: 'mail_from', - type: 'keyword', - }, - { - name: 'helo', - type: 'keyword', - }, - ], - }, - { - name: 'app_proto_expected', - type: 'keyword', - }, - { - name: 'flags', - type: 'group', - fields: [], - }, - ], - }, - ], - }, - ], - }, - { - key: 'zeek', - title: 'Zeek', - description: 'Module for handling logs produced by Zeek/Bro\n', - fields: [ - { - name: 'zeek', - type: 'group', - description: 'Fields from Zeek/Bro logs after normalization\n', - fields: [ - { - name: 'session_id', - type: 'keyword', - description: 'A unique identifier of the session\n', - }, - { - name: 'capture_loss', - type: 'group', - description: 'Fields exported by the Zeek capture_loss log\n', - fields: [ - { - name: 'ts_delta', - type: 'integer', - description: 'The time delay between this measurement and the last.\n', - }, - { - name: 'peer', - type: 'keyword', - description: - 'In the event that there are multiple Bro instances logging to the same host, this distinguishes each peer with its individual name.\n', - }, - { - name: 'gaps', - type: 'integer', - description: 'Number of missed ACKs from the previous measurement interval.\n', - }, - { - name: 'acks', - type: 'integer', - description: 'Total number of ACKs seen in the previous measurement interval.\n', - }, - { - name: 'percent_lost', - type: 'double', - description: "Percentage of ACKs seen where the data being ACKed wasn't seen.\n", - }, - ], - }, - { - name: 'connection', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek Connection log\n', - fields: [ - { - name: 'local_orig', - type: 'boolean', - description: 'Indicates whether the session is originated locally.\n', - }, - { - name: 'local_resp', - type: 'boolean', - description: 'Indicates whether the session is responded locally.\n', - }, - { - name: 'missed_bytes', - type: 'long', - description: 'Missed bytes for the session.\n', - }, - { - name: 'state', - type: 'keyword', - description: 'Code indicating the state of the session.\n', - }, - { - name: 'state_message', - type: 'keyword', - description: 'The state of the session.\n', - }, - { - name: 'icmp', - type: 'group', - fields: [ - { - name: 'type', - type: 'integer', - description: 'ICMP message type.\n', - }, - { - name: 'code', - type: 'integer', - description: 'ICMP message code.\n', - }, - ], - }, - { - name: 'history', - type: 'keyword', - description: 'Flags indicating the history of the session.\n', - }, - { - name: 'vlan', - type: 'integer', - description: 'VLAN identifier.\n', - }, - { - name: 'inner_vlan', - type: 'integer', - description: 'VLAN identifier.\n', - }, - ], - }, - { - name: 'dce_rpc', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek DCE_RPC log\n', - fields: [ - { - name: 'rtt', - type: 'integer', - description: - "Round trip time from the request to the response. If either the request or response wasn't seen, this will be null.\n", - }, - { - name: 'named_pipe', - type: 'keyword', - description: 'Remote pipe name.\n', - }, - { - name: 'endpoint', - type: 'keyword', - description: 'Endpoint name looked up from the uuid.\n', - }, - { - name: 'operation', - type: 'keyword', - description: 'Operation seen in the call.\n', - }, - ], - }, - { - name: 'dhcp', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek DHCP log\n', - fields: [ - { - name: 'domain', - type: 'keyword', - description: 'Domain given by the server in option 15.\n', - }, - { - name: 'duration', - type: 'double', - description: - 'Duration of the DHCP session representing the time from the first\nmessage to the last, in seconds.\n', - }, - { - name: 'hostname', - type: 'keyword', - description: 'Name given by client in Hostname option 12.\n', - }, - { - name: 'client_fqdn', - type: 'keyword', - description: 'FQDN given by client in Client FQDN option 81.\n', - }, - { - name: 'lease_time', - type: 'integer', - description: 'IP address lease interval in seconds.\n', - }, - { - name: 'address', - type: 'group', - description: 'Addresses seen in this DHCP exchange.\n', - fields: [ - { - name: 'assigned', - type: 'ip', - description: 'IP address assigned by the server.\n', - }, - { - name: 'client', - type: 'ip', - description: - 'IP address of the client. If a transaction is only a client sending\nINFORM messages then there is no lease information exchanged so this\nis helpful to know who sent the messages. Getting an address in this\nfield does require that the client sources at least one DHCP message\nusing a non-broadcast address.\n', - }, - { - name: 'mac', - type: 'keyword', - description: "Client's hardware address.\n", - }, - { - name: 'requested', - type: 'ip', - description: 'IP address requested by the client.\n', - }, - { - name: 'server', - type: 'ip', - description: 'IP address of the DHCP server.\n', - }, - ], - }, - { - name: 'msg', - type: 'group', - fields: [ - { - name: 'types', - type: 'keyword', - description: 'List of DHCP message types seen in this exchange.\n', - }, - { - name: 'origin', - type: 'ip', - description: - '(present if policy/protocols/dhcp/msg-orig.bro is loaded)\nThe address that originated each message from the msg.types field.\n', - }, - { - name: 'client', - type: 'keyword', - description: - 'Message typically accompanied with a DHCP_DECLINE so the client can\ntell the server why it rejected an address.\n', - }, - { - name: 'server', - type: 'keyword', - description: - 'Message typically accompanied with a DHCP_NAK to let the client know\nwhy it rejected the request.\n', - }, - ], - }, - { - name: 'software', - type: 'group', - fields: [ - { - name: 'client', - type: 'keyword', - description: - '(present if policy/protocols/dhcp/software.bro is loaded)\nSoftware reported by the client in the vendor_class option.\n', - }, - { - name: 'server', - type: 'keyword', - description: - '(present if policy/protocols/dhcp/software.bro is loaded)\nSoftware reported by the client in the vendor_class option.\n', - }, - ], - }, - { - name: 'id', - type: 'group', - fields: [ - { - name: 'circuit', - type: 'keyword', - description: - '(present if policy/protocols/dhcp/sub-opts.bro is loaded)\nAdded by DHCP relay agents which terminate switched or permanent\ncircuits. It encodes an agent-local identifier of the circuit from\nwhich a DHCP client-to-server packet was received. Typically it\nshould represent a router or switch interface number.\n', - }, - { - name: 'remote_agent', - type: 'keyword', - description: - '(present if policy/protocols/dhcp/sub-opts.bro is loaded)\nA globally unique identifier added by relay agents to identify the\nremote host end of the circuit.\n', - }, - { - name: 'subscriber', - type: 'keyword', - description: - "(present if policy/protocols/dhcp/sub-opts.bro is loaded)\nThe subscriber ID is a value independent of the physical network\nconfiguration so that a customer's DHCP configuration can be given\nto them correctly no matter where they are physically connected.\n", - }, - ], - }, - ], - }, - { - name: 'dnp3', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SSH log\n', - fields: [ - { - name: 'function', - type: 'group', - fields: [ - { - name: 'request', - type: 'keyword', - description: 'The name of the function message in the request.\n', - }, - { - name: 'reply', - type: 'keyword', - description: 'The name of the function message in the reply.\n', - }, - ], - }, - { - name: 'id', - type: 'integer', - description: "The response's internal indication number.\n", - }, - ], - }, - { - name: 'dns', - type: 'group', - description: 'Fields exported by the Zeek DNS log\n', - fields: [ - { - name: 'trans_id', - type: 'keyword', - description: 'DNS transaction identifier.\n', - }, - { - name: 'rtt', - type: 'double', - description: 'Round trip time for the query and response.\n', - }, - { - name: 'query', - type: 'keyword', - description: 'The domain name that is the subject of the DNS query.\n', - }, - { - name: 'qclass', - type: 'long', - description: 'The QCLASS value specifying the class of the query.\n', - }, - { - name: 'qclass_name', - type: 'keyword', - description: 'A descriptive name for the class of the query.\n', - }, - { - name: 'qtype', - type: 'long', - description: 'A QTYPE value specifying the type of the query.\n', - }, - { - name: 'qtype_name', - type: 'keyword', - description: 'A descriptive name for the type of the query.\n', - }, - { - name: 'rcode', - type: 'long', - description: 'The response code value in DNS response messages.\n', - }, - { - name: 'rcode_name', - type: 'keyword', - description: 'A descriptive name for the response code value.\n', - }, - { - name: 'AA', - type: 'boolean', - description: - 'The Authoritative Answer bit for response messages specifies that the responding\nname server is an authority for the domain name in the question section.\n', - }, - { - name: 'TC', - type: 'boolean', - description: 'The Truncation bit specifies that the message was truncated.\n', - }, - { - name: 'RD', - type: 'boolean', - description: - 'The Recursion Desired bit in a request message indicates that the client\nwants recursive service for this query.\n', - }, - { - name: 'RA', - type: 'boolean', - description: - 'The Recursion Available bit in a response message indicates that the name\nserver supports recursive queries.\n', - }, - { - name: 'answers', - type: 'keyword', - description: 'The set of resource descriptions in the query answer.\n', - }, - { - name: 'TTLs', - type: 'double', - description: - 'The caching intervals of the associated RRs described by the answers field.\n', - }, - { - name: 'rejected', - type: 'boolean', - description: 'Indicates whether the DNS query was rejected by the server.\n', - }, - { - name: 'total_answers', - type: 'integer', - description: 'The total number of resource records in the reply.\n', - }, - { - name: 'total_replies', - type: 'integer', - description: 'The total number of resource records in the reply message.\n', - }, - { - name: 'saw_query', - type: 'boolean', - description: 'Whether the full DNS query has been seen.\n', - }, - { - name: 'saw_reply', - type: 'boolean', - description: 'Whether the full DNS reply has been seen.\n', - }, - ], - }, - { - name: 'dpd', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek DPD log\n', - fields: [ - { - name: 'analyzer', - type: 'keyword', - description: 'The analyzer that generated the violation.\n', - }, - { - name: 'failure_reason', - type: 'keyword', - description: 'The textual reason for the analysis failure.\n', - }, - { - name: 'packet_segment', - type: 'keyword', - description: - '(present if policy/frameworks/dpd/packet-segment-logging.bro is loaded)\nA chunk of the payload that most likely resulted in the protocol violation.\n', - }, - ], - }, - { - name: 'files', - type: 'group', - description: 'Fields exported by the Zeek Files log.\n', - fields: [ - { - name: 'fuid', - type: 'keyword', - description: 'A file unique identifier.\n', - }, - { - name: 'tx_host', - type: 'ip', - description: 'The host that transferred the file.\n', - }, - { - name: 'rx_host', - type: 'ip', - description: 'The host that received the file.\n', - }, - { - name: 'session_ids', - type: 'keyword', - description: 'The sessions that have this file.\n', - }, - { - name: 'source', - type: 'keyword', - description: - 'An identification of the source of the file data. E.g. it may be a network protocol\nover which it was transferred, or a local file path which was read, or some other\ninput source.\n', - }, - { - name: 'depth', - type: 'long', - description: - 'A value to represent the depth of this file in relation to its source. In SMTP, it\nis the depth of the MIME attachment on the message. In HTTP, it is the depth of the\nrequest within the TCP connection.\n', - }, - { - name: 'analyzers', - type: 'keyword', - description: 'A set of analysis types done during the file analysis.\n', - }, - { - name: 'mime_type', - type: 'keyword', - description: 'Mime type of the file.\n', - }, - { - name: 'filename', - type: 'keyword', - description: 'Name of the file if available.\n', - }, - { - name: 'local_orig', - type: 'boolean', - description: - 'If the source of this file is a network connection, this field indicates if the data\noriginated from the local network or not.\n', - }, - { - name: 'is_orig', - type: 'boolean', - description: - 'If the source of this file is a network connection, this field indicates if the file is\nbeing sent by the originator of the connection or the responder.\n', - }, - { - name: 'duration', - type: 'double', - description: - 'The duration the file was analyzed for. Not the duration of the session.\n', - }, - { - name: 'seen_bytes', - type: 'long', - description: 'Number of bytes provided to the file analysis engine for the file.\n', - }, - { - name: 'total_bytes', - type: 'long', - description: 'Total number of bytes that are supposed to comprise the full file.\n', - }, - { - name: 'missing_bytes', - type: 'long', - description: - 'The number of bytes in the file stream that were completely missed during the process\nof analysis.\n', - }, - { - name: 'overflow_bytes', - type: 'long', - description: - "The number of bytes in the file stream that were not delivered to stream file analyzers.\nThis could be overlapping bytes or bytes that couldn't be reassembled.\n", - }, - { - name: 'timedout', - type: 'boolean', - description: 'Whether the file analysis timed out at least once for the file.\n', - }, - { - name: 'parent_fuid', - type: 'keyword', - description: - 'Identifier associated with a container file from which this one was extracted as part of\nthe file analysis.\n', - }, - { - name: 'md5', - type: 'keyword', - description: 'An MD5 digest of the file contents.\n', - }, - { - name: 'sha1', - type: 'keyword', - description: 'A SHA1 digest of the file contents.\n', - }, - { - name: 'sha256', - type: 'keyword', - description: 'A SHA256 digest of the file contents.\n', - }, - { - name: 'extracted', - type: 'keyword', - description: 'Local filename of extracted file.\n', - }, - { - name: 'extracted_cutoff', - type: 'boolean', - description: - 'Indicate whether the file being extracted was cut off hence not extracted completely.\n', - }, - { - name: 'extracted_size', - type: 'long', - description: 'The number of bytes extracted to disk.\n', - }, - { - name: 'entropy', - type: 'double', - description: 'The information density of the contents of the file.\n', - }, - ], - }, - { - name: 'ftp', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek FTP log\n', - fields: [ - { - name: 'user', - type: 'keyword', - description: 'User name for the current FTP session.\n', - }, - { - name: 'password', - type: 'keyword', - description: 'Password for the current FTP session if captured.\n', - }, - { - name: 'command', - type: 'keyword', - description: 'Command given by the client.\n', - }, - { - name: 'arg', - type: 'keyword', - description: 'Argument for the command if one is given.\n', - }, - { - name: 'file', - type: 'group', - fields: [ - { - name: 'size', - type: 'long', - description: 'Size of the file if the command indicates a file transfer.\n', - }, - { - name: 'mime_type', - type: 'keyword', - description: 'Sniffed mime type of file.\n', - }, - { - name: 'fuid', - type: 'keyword', - description: - '(present if base/protocols/ftp/files.bro is loaded)\nFile unique ID.\n', - }, - ], - }, - { - name: 'reply', - type: 'group', - fields: [ - { - name: 'code', - type: 'integer', - description: 'Reply code from the server in response to the command.\n', - }, - { - name: 'msg', - type: 'keyword', - description: 'Reply message from the server in response to the command.\n', - }, - ], - }, - { - name: 'data_channel', - type: 'group', - description: 'Expected FTP data channel.\n', - fields: [ - { - name: 'passive', - type: 'boolean', - description: 'Whether PASV mode is toggled for control channel.\n', - }, - { - name: 'originating_host', - type: 'ip', - description: 'The host that will be initiating the data connection.\n', - }, - { - name: 'response_host', - type: 'ip', - description: 'The host that will be accepting the data connection.\n', - }, - { - name: 'response_port', - type: 'integer', - description: - 'The port at which the acceptor is listening for the data connection.\n', - }, - ], - }, - { - name: 'cwd', - type: 'keyword', - description: - "Current working directory that this session is in. By making the default value '.', we can indicate that unless something more concrete is discovered that the existing but unknown directory is ok to use.\n", - }, - { - name: 'cmdarg', - type: 'group', - description: 'Command that is currently waiting for a response.\n', - fields: [ - { - name: 'cmd', - type: 'keyword', - description: 'Command.\n', - }, - { - name: 'arg', - type: 'keyword', - description: 'Argument for the command if one was given.\n', - }, - { - name: 'seq', - type: 'integer', - description: 'Counter to track how many commands have been executed.\n', - }, - ], - }, - { - name: 'pending_commands', - type: 'integer', - description: - 'Queue for commands that have been sent but not yet responded to are tracked here.\n', - }, - { - name: 'passive', - type: 'boolean', - description: 'Indicates if the session is in active or passive mode.\n', - }, - { - name: 'capture_password', - type: 'boolean', - description: 'Determines if the password will be captured for this request.\n', - }, - { - name: 'last_auth_requested', - type: 'keyword', - description: - 'present if base/protocols/ftp/gridftp.bro is loaded.\nLast authentication/security mechanism that was used.\n', - }, - ], - }, - { - name: 'http', - type: 'group', - description: 'Fields exported by the Zeek HTTP log\n', - fields: [ - { - name: 'trans_depth', - type: 'integer', - description: - 'Represents the pipelined depth into the connection of this request/response transaction.\n', - }, - { - name: 'status_msg', - type: 'keyword', - description: 'Status message returned by the server.\n', - }, - { - name: 'info_code', - type: 'integer', - description: 'Last seen 1xx informational reply code returned by the server.\n', - }, - { - name: 'info_msg', - type: 'keyword', - description: 'Last seen 1xx informational reply message returned by the server.\n', - }, - { - name: 'tags', - type: 'keyword', - description: - 'A set of indicators of various attributes discovered and related to a particular\nrequest/response pair.\n', - }, - { - name: 'password', - type: 'keyword', - description: 'Password if basic-auth is performed for the request.\n', - }, - { - name: 'captured_password', - type: 'boolean', - description: 'Determines if the password will be captured for this request.\n', - }, - { - name: 'proxied', - type: 'keyword', - description: - 'All of the headers that may indicate if the HTTP request was proxied.\n', - }, - { - name: 'range_request', - type: 'boolean', - description: - 'Indicates if this request can assume 206 partial content in response.\n', - }, - { - name: 'client_header_names', - type: 'keyword', - description: - 'The vector of HTTP header names sent by the client. No header values\nare included here, just the header names.\n', - }, - { - name: 'server_header_names', - type: 'keyword', - description: - 'The vector of HTTP header names sent by the server. No header values\nare included here, just the header names.\n', - }, - { - name: 'orig_fuids', - type: 'keyword', - description: 'An ordered vector of file unique IDs from the originator.\n', - }, - { - name: 'orig_mime_types', - type: 'keyword', - description: 'An ordered vector of mime types from the originator.\n', - }, - { - name: 'orig_filenames', - type: 'keyword', - description: 'An ordered vector of filenames from the originator.\n', - }, - { - name: 'resp_fuids', - type: 'keyword', - description: 'An ordered vector of file unique IDs from the responder.\n', - }, - { - name: 'resp_mime_types', - type: 'keyword', - description: 'An ordered vector of mime types from the responder.\n', - }, - { - name: 'resp_filenames', - type: 'keyword', - description: 'An ordered vector of filenames from the responder.\n', - }, - { - name: 'orig_mime_depth', - type: 'integer', - description: 'Current number of MIME entities in the HTTP request message body.\n', - }, - { - name: 'resp_mime_depth', - type: 'integer', - description: 'Current number of MIME entities in the HTTP response message body.\n', - }, - ], - }, - { - name: 'intel', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek Intel log.\n', - fields: [ - { - name: 'seen', - type: 'group', - fields: [ - { - name: 'indicator', - type: 'keyword', - description: 'The intelligence indicator.\n', - }, - { - name: 'indicator_type', - type: 'keyword', - description: 'The type of data the indicator represents.\n', - }, - { - name: 'host', - type: 'keyword', - description: - 'If the indicator type was Intel::ADDR, then this field will be present.\n', - }, - { - name: 'conn', - type: 'keyword', - description: - 'If the data was discovered within a connection, the connection record should go here to give context to the data.\n', - }, - { - name: 'where', - type: 'keyword', - description: 'Where the data was discovered.\n', - }, - { - name: 'node', - type: 'keyword', - description: 'The name of the node where the match was discovered.\n', - }, - { - name: 'uid', - type: 'keyword', - description: - 'If the data was discovered within a connection, the connection uid should go here to give context to the data. If the conn field is provided, this will be automatically filled out.\n', - }, - { - name: 'f', - type: 'object', - description: - 'If the data was discovered within a file, the file record should go here to provide context to the data.\n', - }, - { - name: 'fuid', - type: 'keyword', - description: - 'If the data was discovered within a file, the file uid should go here to provide context to the data. If the file record f is provided, this will be automatically filled out.\n', - }, - ], - }, - { - name: 'matched', - type: 'keyword', - description: - 'Event to represent a match in the intelligence data from data that was seen.\n', - }, - { - name: 'sources', - type: 'keyword', - description: 'Sources which supplied data for this match.\n', - }, - { - name: 'fuid', - type: 'keyword', - description: - 'If a file was associated with this intelligence hit, this is the uid for the file.\n', - }, - { - name: 'file_mime_type', - type: 'keyword', - description: - 'A mime type if the intelligence hit is related to a file. If the $f field is provided this will be automatically filled out.\n', - }, - { - name: 'file_desc', - type: 'keyword', - description: - 'Frequently files can be described to give a bit more context. If the $f field is provided this field will be automatically filled out.\n', - }, - ], - }, - { - name: 'irc', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek IRC log\n', - fields: [ - { - name: 'nick', - type: 'keyword', - description: 'Nickname given for the connection.\n', - }, - { - name: 'user', - type: 'keyword', - description: 'Username given for the connection.\n', - }, - { - name: 'command', - type: 'keyword', - description: 'Command given by the client.\n', - }, - { - name: 'value', - type: 'keyword', - description: 'Value for the command given by the client.\n', - }, - { - name: 'addl', - type: 'keyword', - description: 'Any additional data for the command.\n', - }, - { - name: 'dcc', - type: 'group', - fields: [ - { - name: 'file', - type: 'group', - fields: [ - { - name: 'name', - type: 'keyword', - description: - 'Present if base/protocols/irc/dcc-send.bro is loaded.\nDCC filename requested.\n', - }, - { - name: 'size', - type: 'long', - description: - 'Present if base/protocols/irc/dcc-send.bro is loaded.\nSize of the DCC transfer as indicated by the sender.\n', - }, - ], - }, - { - name: 'mime_type', - type: 'keyword', - description: - 'present if base/protocols/irc/dcc-send.bro is loaded.\nSniffed mime type of the file.\n', - }, - ], - }, - { - name: 'fuid', - type: 'keyword', - description: - 'present if base/protocols/irc/files.bro is loaded.\nFile unique ID.\n', - }, - ], - }, - { - name: 'kerberos', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek Kerberos log\n', - fields: [ - { - name: 'request_type', - type: 'keyword', - description: - 'Request type - Authentication Service (AS) or Ticket Granting Service (TGS).\n', - }, - { - name: 'client', - type: 'keyword', - description: 'Client name.\n', - }, - { - name: 'service', - type: 'keyword', - description: 'Service name.\n', - }, - { - name: 'success', - type: 'boolean', - description: 'Request result.\n', - }, - { - name: 'error', - type: 'group', - fields: [ - { - name: 'code', - type: 'integer', - description: 'Error code.\n', - }, - { - name: 'msg', - type: 'keyword', - description: 'Error message.\n', - }, - ], - }, - { - name: 'valid', - type: 'group', - fields: [ - { - name: 'from', - type: 'date', - description: 'Ticket valid from.\n', - }, - { - name: 'until', - type: 'date', - description: 'Ticket valid until.\n', - }, - { - name: 'days', - type: 'integer', - description: 'Number of days the ticket is valid for.\n', - }, - ], - }, - { - name: 'cipher', - type: 'keyword', - description: 'Ticket encryption type.\n', - }, - { - name: 'forwardable', - type: 'boolean', - description: 'Forwardable ticket requested.\n', - }, - { - name: 'renewable', - type: 'boolean', - description: 'Renewable ticket requested.\n', - }, - { - name: 'ticket', - type: 'group', - fields: [ - { - name: 'auth', - type: 'keyword', - description: 'Hash of ticket used to authorize request/transaction.\n', - }, - { - name: 'new', - type: 'keyword', - description: 'Hash of ticket returned by the KDC.\n', - }, - ], - }, - { - name: 'cert', - type: 'group', - fields: [ - { - name: 'client', - type: 'group', - fields: [ - { - name: 'value', - type: 'keyword', - description: 'Client certificate.\n', - }, - { - name: 'fuid', - type: 'keyword', - description: 'File unique ID of client cert.\n', - }, - { - name: 'subject', - type: 'keyword', - description: 'Subject of client certificate.\n', - }, - ], - }, - { - name: 'server', - type: 'group', - fields: [ - { - name: 'value', - type: 'keyword', - description: 'Server certificate.\n', - }, - { - name: 'fuid', - type: 'keyword', - description: 'File unique ID of server certificate.\n', - }, - { - name: 'subject', - type: 'keyword', - description: 'Subject of server certificate.\n', - }, - ], - }, - ], - }, - ], - }, - { - name: 'modbus', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek modbus log.\n', - fields: [ - { - name: 'function', - type: 'keyword', - description: 'The name of the function message that was sent.\n', - }, - { - name: 'exception', - type: 'keyword', - description: 'The exception if the response was a failure.\n', - }, - { - name: 'track_address', - type: 'integer', - description: - 'Present if policy/protocols/modbus/track-memmap.bro is loaded.\nModbus track address.\n', - }, - ], - }, - { - name: 'mysql', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek MySQL log.\n', - fields: [ - { - name: 'cmd', - type: 'keyword', - description: 'The command that was issued.\n', - }, - { - name: 'arg', - type: 'keyword', - description: 'The argument issued to the command.\n', - }, - { - name: 'success', - type: 'boolean', - description: 'Whether the command succeeded.\n', - }, - { - name: 'rows', - type: 'integer', - description: 'The number of affected rows, if any.\n', - }, - { - name: 'response', - type: 'keyword', - description: 'Server message, if any.\n', - }, - ], - }, - { - name: 'notice', - type: 'group', - description: 'Fields exported by the Zeek Notice log.\n', - fields: [ - { - name: 'connection_id', - type: 'keyword', - description: 'Identifier of the related connection session.\n', - }, - { - name: 'icmp_id', - type: 'keyword', - description: 'Identifier of the related ICMP session.\n', - }, - { - name: 'file.id', - type: 'keyword', - description: - 'An identifier associated with a single file that is related to this notice.\n', - }, - { - name: 'file.parent_id', - type: 'keyword', - description: - 'Identifier associated with a container file from which this one was extracted.\n', - }, - { - name: 'file.source', - type: 'keyword', - description: - 'An identification of the source of the file data. E.g. it may be a network protocol\nover which it was transferred, or a local file path which was read, or some other\ninput source.\n', - }, - { - name: 'file.mime_type', - type: 'keyword', - description: 'A mime type if the notice is related to a file.\n', - }, - { - name: 'file.is_orig', - type: 'boolean', - description: - 'If the source of this file is a network connection, this field indicates if the file is\nbeing sent by the originator of the connection or the responder.\n', - }, - { - name: 'file.seen_bytes', - type: 'long', - description: 'Number of bytes provided to the file analysis engine for the file.\n', - }, - { - name: 'ffile.total_bytes', - type: 'long', - description: 'Total number of bytes that are supposed to comprise the full file.\n', - }, - { - name: 'file.missing_bytes', - type: 'long', - description: - 'The number of bytes in the file stream that were completely missed during the process\nof analysis.\n', - }, - { - name: 'file.overflow_bytes', - type: 'long', - description: - "The number of bytes in the file stream that were not delivered to stream file analyzers.\nThis could be overlapping bytes or bytes that couldn't be reassembled.\n", - }, - { - name: 'fuid', - type: 'keyword', - description: 'A file unique ID if this notice is related to a file.\n', - }, - { - name: 'note', - type: 'keyword', - description: 'The type of the notice.\n', - }, - { - name: 'msg', - type: 'keyword', - description: 'The human readable message for the notice.\n', - }, - { - name: 'sub', - type: 'keyword', - description: 'The human readable sub-message.\n', - }, - { - name: 'n', - type: 'long', - description: 'Associated count, or a status code.\n', - }, - { - name: 'peer_name', - type: 'keyword', - description: 'Name of remote peer that raised this notice.\n', - }, - { - name: 'peer_descr', - type: 'text', - description: 'Textual description for the peer that raised this notice.\n', - }, - { - name: 'actions', - type: 'keyword', - description: 'The actions which have been applied to this notice.\n', - }, - { - name: 'email_body_sections', - type: 'text', - description: - 'By adding chunks of text into this element, other scripts can expand on notices\nthat are being emailed.\n', - }, - { - name: 'email_delay_tokens', - type: 'keyword', - description: - 'Adding a string token to this set will cause the built-in emailing functionality\nto delay sending the email either the token has been removed or the email\nhas been delayed for the specified time duration.\n', - }, - { - name: 'identifier', - type: 'keyword', - description: - 'This field is provided when a notice is generated for the purpose of deduplicating notices.\n', - }, - { - name: 'suppress_for', - type: 'double', - description: - 'This field indicates the length of time that this unique notice should be suppressed.\n', - }, - { - name: 'dropped', - type: 'boolean', - description: - 'Indicate if the source IP address was dropped and denied network access.\n', - }, - ], - }, - { - name: 'ntlm', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek NTLM log.\n', - fields: [ - { - name: 'domain', - type: 'keyword', - description: 'Domain name given by the client.\n', - }, - { - name: 'hostname', - type: 'keyword', - description: 'Hostname given by the client.\n', - }, - { - name: 'success', - type: 'boolean', - description: 'Indicate whether or not the authentication was successful.\n', - }, - { - name: 'username', - type: 'keyword', - description: 'Username given by the client.\n', - }, - { - name: 'server', - type: 'group', - fields: [ - { - name: 'name', - type: 'group', - fields: [ - { - name: 'dns', - type: 'keyword', - description: 'DNS name given by the server in a CHALLENGE.\n', - }, - { - name: 'netbios', - type: 'keyword', - description: 'NetBIOS name given by the server in a CHALLENGE.\n', - }, - { - name: 'tree', - type: 'keyword', - description: 'Tree name given by the server in a CHALLENGE.\n', - }, - ], - }, - ], - }, - ], - }, - { - name: 'ocsp', - type: 'group', - default_field: false, - description: - 'Fields exported by the Zeek OCSP log\nOnline Certificate Status Protocol (OCSP). Only created if policy script is loaded.\n', - fields: [ - { - name: 'file_id', - type: 'keyword', - description: 'File id of the OCSP reply.\n', - }, - { - name: 'hash', - type: 'group', - fields: [ - { - name: 'algorithm', - type: 'keyword', - description: - 'Hash algorithm used to generate issuerNameHash and issuerKeyHash.\n', - }, - { - name: 'issuer', - type: 'group', - fields: [ - { - name: 'name', - type: 'keyword', - description: "Hash of the issuer's distingueshed name.\n", - }, - { - name: 'key', - type: 'keyword', - description: "Hash of the issuer's public key.\n", - }, - ], - }, - ], - }, - { - name: 'serial_number', - type: 'keyword', - description: 'Serial number of the affected certificate.\n', - }, - { - name: 'status', - type: 'keyword', - description: 'Status of the affected certificate.\n', - }, - { - name: 'revoke', - type: 'group', - fields: [ - { - name: 'time', - type: 'date', - description: 'Time at which the certificate was revoked.\n', - }, - { - name: 'reason', - type: 'keyword', - description: 'Reason for which the certificate was revoked.\n', - }, - ], - }, - { - name: 'update', - type: 'group', - fields: [ - { - name: 'this', - type: 'date', - description: - 'The time at which the status being shows is known to have been correct.\n', - }, - { - name: 'next', - type: 'date', - description: - 'The latest time at which new information about the status of the certificate will be available.\n', - }, - ], - }, - ], - }, - { - name: 'pe', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek pe log.\n', - fields: [ - { - name: 'client', - type: 'keyword', - description: "The client's version string.\n", - }, - { - name: 'id', - type: 'keyword', - description: 'File id of this portable executable file.\n', - }, - { - name: 'machine', - type: 'keyword', - description: 'The target machine that the file was compiled for.\n', - }, - { - name: 'compile_time', - type: 'date', - description: 'The time that the file was created at.\n', - }, - { - name: 'os', - type: 'keyword', - description: 'The required operating system.\n', - }, - { - name: 'subsystem', - type: 'keyword', - description: 'The subsystem that is required to run this file.\n', - }, - { - name: 'is_exe', - type: 'boolean', - description: 'Is the file an executable, or just an object file?\n', - }, - { - name: 'is_64bit', - type: 'boolean', - description: 'Is the file a 64-bit executable?\n', - }, - { - name: 'uses_aslr', - type: 'boolean', - description: 'Does the file support Address Space Layout Randomization?\n', - }, - { - name: 'uses_dep', - type: 'boolean', - description: 'Does the file support Data Execution Prevention?\n', - }, - { - name: 'uses_code_integrity', - type: 'boolean', - description: 'Does the file enforce code integrity checks?\n', - }, - { - name: 'uses_seh', - type: 'boolean', - description: 'Does the file use structured exception handing?\n', - }, - { - name: 'has_import_table', - type: 'boolean', - description: 'Does the file have an import table?\n', - }, - { - name: 'has_export_table', - type: 'boolean', - description: 'Does the file have an export table?\n', - }, - { - name: 'has_cert_table', - type: 'boolean', - description: 'Does the file have an attribute certificate table?\n', - }, - { - name: 'has_debug_data', - type: 'boolean', - description: 'Does the file have a debug table?\n', - }, - { - name: 'section_names', - type: 'keyword', - description: 'The names of the sections, in order.\n', - }, - ], - }, - { - name: 'radius', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek Radius log.\n', - fields: [ - { - name: 'username', - type: 'keyword', - description: 'The username, if present.\n', - }, - { - name: 'mac', - type: 'keyword', - description: 'MAC address, if present.\n', - }, - { - name: 'framed_addr', - type: 'ip', - description: - 'The address given to the network access server, if present. This is only a hint from the RADIUS server and the network access server is not required to honor the address.\n', - }, - { - name: 'remote_ip', - type: 'ip', - description: - 'Remote IP address, if present. This is collected from the Tunnel-Client-Endpoint attribute.\n', - }, - { - name: 'connect_info', - type: 'keyword', - description: 'Connect info, if present.\n', - }, - { - name: 'reply_msg', - type: 'keyword', - description: - 'Reply message from the server challenge. This is frequently shown to the user authenticating.\n', - }, - { - name: 'result', - type: 'keyword', - description: 'Successful or failed authentication.\n', - }, - { - name: 'ttl', - type: 'integer', - description: - 'The duration between the first request and either the "Access-Accept" message or an error. If the field is empty, it means that either the request or response was not seen.\n', - }, - { - name: 'logged', - type: 'boolean', - description: 'Whether this has already been logged and can be ignored.\n', - }, - ], - }, - { - name: 'rdp', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek RDP log.\n', - fields: [ - { - name: 'cookie', - type: 'keyword', - description: - 'Cookie value used by the client machine. This is typically a username.\n', - }, - { - name: 'result', - type: 'keyword', - description: - "Status result for the connection. It's a mix between RDP negotation failure messages and GCC server create response messages.\n", - }, - { - name: 'security_protocol', - type: 'keyword', - description: 'Security protocol chosen by the server.\n', - }, - { - name: 'keyboard_layout', - type: 'keyword', - description: 'Keyboard layout (language) of the client machine.\n', - }, - { - name: 'client', - type: 'group', - fields: [ - { - name: 'build', - type: 'keyword', - description: 'RDP client version used by the client machine.\n', - }, - { - name: 'client_name', - type: 'keyword', - description: 'Name of the client machine.\n', - }, - { - name: 'product_id', - type: 'keyword', - description: 'Product ID of the client machine.\n', - }, - ], - }, - { - name: 'desktop', - type: 'group', - fields: [ - { - name: 'width', - type: 'integer', - description: 'Desktop width of the client machine.\n', - }, - { - name: 'height', - type: 'integer', - description: 'Desktop height of the client machine.\n', - }, - { - name: 'color_depth', - type: 'keyword', - description: - 'The color depth requested by the client in the high_color_depth field.\n', - }, - ], - }, - { - name: 'cert', - type: 'group', - fields: [ - { - name: 'type', - type: 'keyword', - description: - 'If the connection is being encrypted with native RDP encryption, this is the type of cert being used.\n', - }, - { - name: 'count', - type: 'integer', - description: - 'The number of certs seen. X.509 can transfer an entire certificate chain.\n', - }, - { - name: 'permanent', - type: 'boolean', - description: - 'Indicates if the provided certificate or certificate chain is permanent or temporary.\n', - }, - ], - }, - { - name: 'encryption', - type: 'group', - fields: [ - { - name: 'level', - type: 'keyword', - description: 'Encryption level of the connection.\n', - }, - { - name: 'method', - type: 'keyword', - description: 'Encryption method of the connection.\n', - }, - ], - }, - { - name: 'done', - type: 'boolean', - description: 'Track status of logging RDP connections.\n', - }, - { - name: 'ssl', - type: 'boolean', - description: - '(present if policy/protocols/rdp/indicate_ssl.bro is loaded)\nFlag the connection if it was seen over SSL.\n', - }, - ], - }, - { - name: 'rfb', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek RFB log.\n', - fields: [ - { - name: 'version', - type: 'group', - fields: [ - { - name: 'client', - type: 'group', - fields: [ - { - name: 'major', - type: 'keyword', - description: 'Major version of the client.\n', - }, - { - name: 'minor', - type: 'keyword', - description: 'Minor version of the client.\n', - }, - ], - }, - { - name: 'server', - type: 'group', - fields: [ - { - name: 'major', - type: 'keyword', - description: 'Major version of the server.\n', - }, - { - name: 'minor', - type: 'keyword', - description: 'Minor version of the server.\n', - }, - ], - }, - ], - }, - { - name: 'auth', - type: 'group', - fields: [ - { - name: 'success', - type: 'boolean', - description: 'Whether or not authentication was successful.\n', - }, - { - name: 'method', - type: 'keyword', - description: 'Identifier of authentication method used.\n', - }, - ], - }, - { - name: 'share_flag', - type: 'boolean', - description: 'Whether the client has an exclusive or a shared session.\n', - }, - { - name: 'desktop_name', - type: 'keyword', - description: 'Name of the screen that is being shared.\n', - }, - { - name: 'width', - type: 'integer', - description: 'Width of the screen that is being shared.\n', - }, - { - name: 'height', - type: 'integer', - description: 'Height of the screen that is being shared.\n', - }, - ], - }, - { - name: 'sip', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SIP log.\n', - fields: [ - { - name: 'transaction_depth', - type: 'integer', - description: - 'Represents the pipelined depth into the connection of this request/response transaction.\n', - }, - { - name: 'sequence', - type: 'group', - fields: [ - { - name: 'method', - type: 'keyword', - description: 'Verb used in the SIP request (INVITE, REGISTER etc.).\n', - }, - { - name: 'number', - type: 'keyword', - description: 'Contents of the CSeq: header from the client.\n', - }, - ], - }, - { - name: 'uri', - type: 'keyword', - description: 'URI used in the request.\n', - }, - { - name: 'date', - type: 'keyword', - description: 'Contents of the Date: header from the client.\n', - }, - { - name: 'request', - type: 'group', - fields: [ - { - name: 'from', - type: 'keyword', - description: - "Contents of the request From: header Note: The tag= value that's usually appended to the sender is stripped off and not logged.\n", - }, - { - name: 'to', - type: 'keyword', - description: 'Contents of the To: header.\n', - }, - { - name: 'path', - type: 'keyword', - description: - 'The client message transmission path, as extracted from the headers.\n', - }, - { - name: 'body_length', - type: 'long', - description: 'Contents of the Content-Length: header from the client.\n', - }, - ], - }, - { - name: 'response', - type: 'group', - fields: [ - { - name: 'from', - type: 'keyword', - description: - "Contents of the response From: header Note: The tag= value that's usually appended to the sender is stripped off and not logged.\n", - }, - { - name: 'to', - type: 'keyword', - description: 'Contents of the response To: header.\n', - }, - { - name: 'path', - type: 'keyword', - description: - 'The server message transmission path, as extracted from the headers.\n', - }, - { - name: 'body_length', - type: 'long', - description: 'Contents of the Content-Length: header from the server.\n', - }, - ], - }, - { - name: 'reply_to', - type: 'keyword', - description: 'Contents of the Reply-To: header.\n', - }, - { - name: 'call_id', - type: 'keyword', - description: 'Contents of the Call-ID: header from the client.\n', - }, - { - name: 'subject', - type: 'keyword', - description: 'Contents of the Subject: header from the client.\n', - }, - { - name: 'user_agent', - type: 'keyword', - description: 'Contents of the User-Agent: header from the client.\n', - }, - { - name: 'status', - type: 'group', - fields: [ - { - name: 'code', - type: 'integer', - description: 'Status code returned by the server.\n', - }, - { - name: 'msg', - type: 'keyword', - description: 'Status message returned by the server.\n', - }, - ], - }, - { - name: 'warning', - type: 'keyword', - description: 'Contents of the Warning: header.\n', - }, - { - name: 'content_type', - type: 'keyword', - description: 'Contents of the Content-Type: header from the server.\n', - }, - ], - }, - { - name: 'smb_cmd', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek smb_cmd log.\n', - fields: [ - { - name: 'command', - type: 'keyword', - description: 'The command sent by the client.\n', - }, - { - name: 'sub_command', - type: 'keyword', - description: 'The subcommand sent by the client, if present.\n', - }, - { - name: 'argument', - type: 'keyword', - description: 'Command argument sent by the client, if any.\n', - }, - { - name: 'status', - type: 'keyword', - description: "Server reply to the client's command.\n", - }, - { - name: 'rtt', - type: 'double', - description: 'Round trip time from the request to the response.\n', - }, - { - name: 'version', - type: 'keyword', - description: 'Version of SMB for the command.\n', - }, - { - name: 'username', - type: 'keyword', - description: 'Authenticated username, if available.\n', - }, - { - name: 'tree', - type: 'keyword', - description: - 'If this is related to a tree, this is the tree that was used for the current command.\n', - }, - { - name: 'tree_service', - type: 'keyword', - description: 'The type of tree (disk share, printer share, named pipe, etc.).\n', - }, - { - name: 'file', - type: 'group', - description: 'If the command referenced a file, store it here.\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'Filename if one was seen.\n', - }, - { - name: 'action', - type: 'keyword', - description: 'Action this log record represents.\n', - }, - { - name: 'uid', - type: 'keyword', - description: 'UID of the referenced file.\n', - }, - { - name: 'host', - type: 'group', - fields: [ - { - name: 'tx', - type: 'ip', - description: 'Address of the transmitting host.\n', - }, - { - name: 'rx', - type: 'ip', - description: 'Address of the receiving host.\n', - }, - ], - }, - ], - }, - { - name: 'smb1_offered_dialects', - type: 'keyword', - description: - 'Present if base/protocols/smb/smb1-main.bro is loaded.\nDialects offered by the client.\n', - }, - { - name: 'smb2_offered_dialects', - type: 'integer', - description: - 'Present if base/protocols/smb/smb2-main.bro is loaded.\nDialects offered by the client.\n', - }, - ], - }, - { - name: 'smb_files', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SMB Files log.\n', - fields: [ - { - name: 'action', - type: 'keyword', - description: 'Action this log record represents.\n', - }, - { - name: 'fid', - type: 'integer', - description: 'ID referencing this file.\n', - }, - { - name: 'name', - type: 'keyword', - description: 'Filename if one was seen.\n', - }, - { - name: 'path', - type: 'keyword', - description: 'Path pulled from the tree this file was transferred to or from.\n', - }, - { - name: 'previous_name', - type: 'keyword', - description: - "If the rename action was seen, this will be the file's previous name.\n", - }, - { - name: 'size', - type: 'long', - description: 'Byte size of the file.\n', - }, - { - name: 'times', - type: 'group', - description: 'Timestamps of the file.\n', - fields: [ - { - name: 'accessed', - type: 'date', - description: "The file's access time.\n", - }, - { - name: 'changed', - type: 'date', - description: "The file's change time.\n", - }, - { - name: 'created', - type: 'date', - description: "The file's create time.\n", - }, - { - name: 'modified', - type: 'date', - description: "The file's modify time.\n", - }, - ], - }, - { - name: 'uuid', - type: 'keyword', - description: 'UUID referencing this file if DCE/RPC.\n', - }, - ], - }, - { - name: 'smb_mapping', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SMB_Mapping log.\n', - fields: [ - { - name: 'path', - type: 'keyword', - description: 'Name of the tree path.\n', - }, - { - name: 'service', - type: 'keyword', - description: - 'The type of resource of the tree (disk share, printer share, named pipe, etc.).\n', - }, - { - name: 'native_file_system', - type: 'keyword', - description: 'File system of the tree.\n', - }, - { - name: 'share_type', - type: 'keyword', - description: - 'If this is SMB2, a share type will be included. For SMB1, the type of share\nwill be deduced and included as well.\n', - }, - ], - }, - { - name: 'smtp', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SMTP log.\n', - fields: [ - { - name: 'transaction_depth', - type: 'integer', - description: - 'A count to represent the depth of this message transaction in a single connection where multiple messages were transferred.\n', - }, - { - name: 'helo', - type: 'keyword', - description: 'Contents of the Helo header.\n', - }, - { - name: 'mail_from', - type: 'keyword', - description: 'Email addresses found in the MAIL FROM header.\n', - }, - { - name: 'rcpt_to', - type: 'keyword', - description: 'Email addresses found in the RCPT TO header.\n', - }, - { - name: 'date', - type: 'date', - description: 'Contents of the Date header.\n', - }, - { - name: 'from', - type: 'keyword', - description: 'Contents of the From header.\n', - }, - { - name: 'to', - type: 'keyword', - description: 'Contents of the To header.\n', - }, - { - name: 'cc', - type: 'keyword', - description: 'Contents of the CC header.\n', - }, - { - name: 'reply_to', - type: 'keyword', - description: 'Contents of the ReplyTo header.\n', - }, - { - name: 'msg_id', - type: 'keyword', - description: 'Contents of the MsgID header.\n', - }, - { - name: 'in_reply_to', - type: 'keyword', - description: 'Contents of the In-Reply-To header.\n', - }, - { - name: 'subject', - type: 'keyword', - description: 'Contents of the Subject header.\n', - }, - { - name: 'x_originating_ip', - type: 'keyword', - description: 'Contents of the X-Originating-IP header.\n', - }, - { - name: 'first_received', - type: 'keyword', - description: 'Contents of the first Received header.\n', - }, - { - name: 'second_received', - type: 'keyword', - description: 'Contents of the second Received header.\n', - }, - { - name: 'last_reply', - type: 'keyword', - description: 'The last message that the server sent to the client.\n', - }, - { - name: 'path', - type: 'ip', - description: 'The message transmission path, as extracted from the headers.\n', - }, - { - name: 'user_agent', - type: 'keyword', - description: 'Value of the User-Agent header from the client.\n', - }, - { - name: 'tls', - type: 'boolean', - description: 'Indicates that the connection has switched to using TLS.\n', - }, - { - name: 'process_received_from', - type: 'boolean', - description: - 'Indicates if the "Received: from" headers should still be processed.\n', - }, - { - name: 'has_client_activity', - type: 'boolean', - description: 'Indicates if client activity has been seen, but not yet logged.\n', - }, - { - name: 'fuids', - type: 'keyword', - description: - '(present if base/protocols/smtp/files.bro is loaded)\nAn ordered vector of file unique IDs seen attached to the message.\n', - }, - { - name: 'is_webmail', - type: 'boolean', - description: 'Indicates if the message was sent through a webmail interface.\n', - }, - ], - }, - { - name: 'snmp', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SNMP log.\n', - fields: [ - { - name: 'duration', - type: 'double', - description: - 'The amount of time between the first packet beloning to the SNMP session and the latest one seen.\n', - }, - { - name: 'version', - type: 'keyword', - description: 'The version of SNMP being used.\n', - }, - { - name: 'community', - type: 'keyword', - description: - "The community string of the first SNMP packet associated with the session. This is used as part of SNMP's (v1 and v2c) administrative/security framework. See RFC 1157 or RFC 1901.\n", - }, - { - name: 'get', - type: 'group', - fields: [ - { - name: 'requests', - type: 'integer', - description: - 'The number of variable bindings in GetRequest/GetNextRequest PDUs seen for the session.\n', - }, - { - name: 'bulk_requests', - type: 'integer', - description: - 'The number of variable bindings in GetBulkRequest PDUs seen for the session.\n', - }, - { - name: 'responses', - type: 'integer', - description: - 'The number of variable bindings in GetResponse/Response PDUs seen for the session.\n', - }, - ], - }, - { - name: 'set', - type: 'group', - fields: [ - { - name: 'requests', - type: 'integer', - description: - 'The number of variable bindings in SetRequest PDUs seen for the session.\n', - }, - ], - }, - { - name: 'display_string', - type: 'keyword', - description: 'A system description of the SNMP responder endpoint.\n', - }, - { - name: 'up_since', - type: 'date', - description: - "The time at which the SNMP responder endpoint claims it's been up since.\n", - }, - ], - }, - { - name: 'socks', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SOCKS log.\n', - fields: [ - { - name: 'version', - type: 'integer', - description: 'Protocol version of SOCKS.\n', - }, - { - name: 'user', - type: 'keyword', - description: 'Username used to request a login to the proxy.\n', - }, - { - name: 'password', - type: 'keyword', - description: 'Password used to request a login to the proxy.\n', - }, - { - name: 'status', - type: 'keyword', - description: 'Server status for the attempt at using the proxy.\n', - }, - { - name: 'request', - type: 'group', - fields: [ - { - name: 'host', - type: 'keyword', - description: - 'Client requested SOCKS address. Could be an address, a name or both.\n', - }, - { - name: 'port', - type: 'integer', - description: 'Client requested port.\n', - }, - ], - }, - { - name: 'bound', - type: 'group', - fields: [ - { - name: 'host', - type: 'keyword', - description: 'Server bound address. Could be an address, a name or both.\n', - }, - { - name: 'port', - type: 'integer', - description: 'Server bound port.\n', - }, - ], - }, - { - name: 'capture_password', - type: 'boolean', - description: 'Determines if the password will be captured for this request.\n', - }, - ], - }, - { - name: 'ssh', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SSH log.\n', - fields: [ - { - name: 'client', - type: 'keyword', - description: "The client's version string.\n", - }, - { - name: 'direction', - type: 'keyword', - description: - 'Direction of the connection. If the client was a local host logging into\nan external host, this would be OUTBOUND. INBOUND would be set for the\nopposite situation.\n', - }, - { - name: 'host_key', - type: 'keyword', - description: "The server's key thumbprint.\n", - }, - { - name: 'server', - type: 'keyword', - description: "The server's version string.\n", - }, - { - name: 'version', - type: 'integer', - description: 'SSH major version (1 or 2).\n', - }, - { - name: 'algorithm', - type: 'group', - description: 'Cipher algorithms used in this session.\n', - fields: [ - { - name: 'cipher', - type: 'keyword', - description: 'The encryption algorithm in use.\n', - }, - { - name: 'compression', - type: 'keyword', - description: 'The compression algorithm in use.\n', - }, - { - name: 'host_key', - type: 'keyword', - description: "The server host key's algorithm.\n", - }, - { - name: 'key_exchange', - type: 'keyword', - description: 'The key exchange algorithm in use.\n', - }, - { - name: 'mac', - type: 'keyword', - description: 'The signing (MAC) algorithm in use.\n', - }, - ], - }, - { - name: 'auth', - type: 'group', - fields: [ - { - name: 'attempts', - type: 'integer', - description: - "The number of authentication attemps we observed. There's always at\nleast one, since some servers might support no authentication at all.\nIt's important to note that not all of these are failures, since some\nservers require two-factor auth (e.g. password AND pubkey).\n", - }, - { - name: 'success', - type: 'boolean', - description: 'Authentication result.\n', - }, - ], - }, - ], - }, - { - name: 'ssl', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SSL log.\n', - fields: [ - { - name: 'version', - type: 'keyword', - description: 'SSL/TLS version that was logged.\n', - }, - { - name: 'cipher', - type: 'keyword', - description: 'SSL/TLS cipher suite that was logged.\n', - }, - { - name: 'curve', - type: 'keyword', - description: 'Elliptic curve that was logged when using ECDH/ECDHE.\n', - }, - { - name: 'resumed', - type: 'boolean', - description: - 'Flag to indicate if the session was resumed reusing the key material exchanged in an\nearlier connection.\n', - }, - { - name: 'next_protocol', - type: 'keyword', - description: - 'Next protocol the server chose using the application layer next protocol extension.\n', - }, - { - name: 'established', - type: 'boolean', - description: - 'Flag to indicate if this ssl session has been established successfully.\n', - }, - { - name: 'validation', - type: 'group', - fields: [ - { - name: 'status', - type: 'keyword', - description: 'Result of certificate validation for this connection.\n', - }, - { - name: 'code', - type: 'keyword', - description: - 'Result of certificate validation for this connection, given as OpenSSL validation code.\n', - }, - ], - }, - { - name: 'last_alert', - type: 'keyword', - description: 'Last alert that was seen during the connection.\n', - }, - { - name: 'server', - type: 'group', - fields: [ - { - name: 'name', - type: 'keyword', - description: - 'Value of the Server Name Indicator SSL/TLS extension. It indicates the server name\nthat the client was requesting.\n', - }, - { - name: 'cert_chain', - type: 'keyword', - description: - 'Chain of certificates offered by the server to validate its complete signing chain.\n', - }, - { - name: 'cert_chain_fuids', - type: 'keyword', - description: - 'An ordered vector of certificate file identifiers for the certificates offered by the server.\n', - }, - { - name: 'issuer', - type: 'group', - description: - 'Subject of the signer of the X.509 certificate offered by the server.\n', - fields: [ - { - name: 'common_name', - type: 'keyword', - description: - 'Common name of the signer of the X.509 certificate offered by the server.\n', - }, - { - name: 'country', - type: 'keyword', - description: - 'Country code of the signer of the X.509 certificate offered by the server.\n', - }, - { - name: 'locality', - type: 'keyword', - description: - 'Locality of the signer of the X.509 certificate offered by the server.\n', - }, - { - name: 'organization', - type: 'keyword', - description: - 'Organization of the signer of the X.509 certificate offered by the server.\n', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: - 'Organizational unit of the signer of the X.509 certificate offered by the server.\n', - }, - { - name: 'state', - type: 'keyword', - description: - 'State or province name of the signer of the X.509 certificate offered by the server.\n', - }, - ], - }, - { - name: 'subject', - type: 'group', - description: 'Subject of the X.509 certificate offered by the server.\n', - fields: [ - { - name: 'common_name', - type: 'keyword', - description: - 'Common name of the X.509 certificate offered by the server.\n', - }, - { - name: 'country', - type: 'keyword', - description: - 'Country code of the X.509 certificate offered by the server.\n', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality of the X.509 certificate offered by the server.\n', - }, - { - name: 'organization', - type: 'keyword', - description: - 'Organization of the X.509 certificate offered by the server.\n', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: - 'Organizational unit of the X.509 certificate offered by the server.\n', - }, - { - name: 'state', - type: 'keyword', - description: - 'State or province name of the X.509 certificate offered by the server.\n', - }, - ], - }, - ], - }, - { - name: 'client', - type: 'group', - fields: [ - { - name: 'cert_chain', - type: 'keyword', - description: - 'Chain of certificates offered by the client to validate its complete signing chain.\n', - }, - { - name: 'cert_chain_fuids', - type: 'keyword', - description: - 'An ordered vector of certificate file identifiers for the certificates offered by the client.\n', - }, - { - name: 'issuer', - type: 'group', - description: - 'Subject of the signer of the X.509 certificate offered by the client.\n', - fields: [ - { - name: 'common_name', - type: 'keyword', - description: - 'Common name of the signer of the X.509 certificate offered by the client.\n', - }, - { - name: 'country', - type: 'keyword', - description: - 'Country code of the signer of the X.509 certificate offered by the client.\n', - }, - { - name: 'locality', - type: 'keyword', - description: - 'Locality of the signer of the X.509 certificate offered by the client.\n', - }, - { - name: 'organization', - type: 'keyword', - description: - 'Organization of the signer of the X.509 certificate offered by the client.\n', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: - 'Organizational unit of the signer of the X.509 certificate offered by the client.\n', - }, - { - name: 'state', - type: 'keyword', - description: - 'State or province name of the signer of the X.509 certificate offered by the client.\n', - }, - ], - }, - { - name: 'subject', - type: 'group', - description: 'Subject of the X.509 certificate offered by the client.\n', - fields: [ - { - name: 'common_name', - type: 'keyword', - description: - 'Common name of the X.509 certificate offered by the client.\n', - }, - { - name: 'country', - type: 'keyword', - description: - 'Country code of the X.509 certificate offered by the client.\n', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality of the X.509 certificate offered by the client.\n', - }, - { - name: 'organization', - type: 'keyword', - description: - 'Organization of the X.509 certificate offered by the client.\n', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: - 'Organizational unit of the X.509 certificate offered by the client.\n', - }, - { - name: 'state', - type: 'keyword', - description: - 'State or province name of the X.509 certificate offered by the client.\n', - }, - ], - }, - ], - }, - ], - }, - { - name: 'stats', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek stats log.\n', - fields: [ - { - name: 'peer', - type: 'keyword', - description: 'Peer that generated this log. Mostly for clusters.\n', - }, - { - name: 'memory', - type: 'integer', - description: 'Amount of memory currently in use in MB.\n', - }, - { - name: 'packets', - type: 'group', - fields: [ - { - name: 'processed', - type: 'long', - description: 'Number of packets processed since the last stats interval.\n', - }, - { - name: 'dropped', - type: 'long', - description: - 'Number of packets dropped since the last stats interval if reading live traffic.\n', - }, - { - name: 'received', - type: 'long', - description: - 'Number of packets seen on the link since the last stats interval if reading live traffic.\n', - }, - ], - }, - { - name: 'bytes', - type: 'group', - fields: [ - { - name: 'received', - type: 'long', - description: - 'Number of bytes received since the last stats interval if reading live traffic.\n', - }, - ], - }, - { - name: 'connections', - type: 'group', - fields: [ - { - name: 'tcp', - type: 'group', - fields: [ - { - name: 'active', - type: 'integer', - description: 'TCP connections currently in memory.\n', - }, - { - name: 'count', - type: 'integer', - description: 'TCP connections seen since last stats interval.\n', - }, - ], - }, - { - name: 'udp', - type: 'group', - fields: [ - { - name: 'active', - type: 'integer', - description: 'UDP connections currently in memory.\n', - }, - { - name: 'count', - type: 'integer', - description: 'UDP connections seen since last stats interval.\n', - }, - ], - }, - { - name: 'icmp', - type: 'group', - fields: [ - { - name: 'active', - type: 'integer', - description: 'ICMP connections currently in memory.\n', - }, - { - name: 'count', - type: 'integer', - description: 'ICMP connections seen since last stats interval.\n', - }, - ], - }, - ], - }, - { - name: 'events', - type: 'group', - fields: [ - { - name: 'processed', - type: 'integer', - description: 'Number of events processed since the last stats interval.\n', - }, - { - name: 'queued', - type: 'integer', - description: - 'Number of events that have been queued since the last stats interval.\n', - }, - ], - }, - { - name: 'timers', - type: 'group', - fields: [ - { - name: 'count', - type: 'integer', - description: 'Number of timers scheduled since last stats interval.\n', - }, - { - name: 'active', - type: 'integer', - description: 'Current number of scheduled timers.\n', - }, - ], - }, - { - name: 'files', - type: 'group', - fields: [ - { - name: 'count', - type: 'integer', - description: 'Number of files seen since last stats interval.\n', - }, - { - name: 'active', - type: 'integer', - description: 'Current number of files actively being seen.\n', - }, - ], - }, - { - name: 'dns_requests', - type: 'group', - fields: [ - { - name: 'count', - type: 'integer', - description: 'Number of DNS requests seen since last stats interval.\n', - }, - { - name: 'active', - type: 'integer', - description: 'Current number of DNS requests awaiting a reply.\n', - }, - ], - }, - { - name: 'reassembly_size', - type: 'group', - fields: [ - { - name: 'tcp', - type: 'integer', - description: 'Current size of TCP data in reassembly.\n', - }, - { - name: 'file', - type: 'integer', - description: 'Current size of File data in reassembly.\n', - }, - { - name: 'frag', - type: 'integer', - description: 'Current size of packet fragment data in reassembly.\n', - }, - { - name: 'unknown', - type: 'integer', - description: - 'Current size of unknown data in reassembly (this is only PIA buffer right now).\n', - }, - ], - }, - { - name: 'timestamp_lag', - type: 'integer', - description: - 'Lag between the wall clock and packet timestamps if reading live traffic.\n', - }, - ], - }, - { - name: 'syslog', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek syslog log.\n', - fields: [ - { - name: 'facility', - type: 'keyword', - description: 'Syslog facility for the message.\n', - }, - { - name: 'severity', - type: 'keyword', - description: 'Syslog severity for the message.\n', - }, - { - name: 'message', - type: 'keyword', - description: 'The plain text message.\n', - }, - ], - }, - { - name: 'tunnel', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek SSH log.\n', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'The type of tunnel.\n', - }, - { - name: 'action', - type: 'keyword', - description: 'The type of activity that occurred.\n', - }, - ], - }, - { - name: 'weird', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek Weird log.\n', - fields: [ - { - name: 'name', - type: 'keyword', - description: 'The name of the weird that occurred.\n', - }, - { - name: 'additional_info', - type: 'keyword', - description: 'Additional information accompanying the weird if any.\n', - }, - { - name: 'notice', - type: 'boolean', - description: 'Indicate if this weird was also turned into a notice.\n', - }, - { - name: 'peer', - type: 'keyword', - description: - 'The peer that originated this weird. This is helpful in cluster deployments if a particular cluster node is having trouble to help identify which node is having trouble.\n', - }, - { - name: 'identifier', - type: 'keyword', - description: - 'This field is to be provided when a weird is generated for the purpose of deduplicating weirds. The identifier string should be unique for a single instance of the weird. This field is used to define when a weird is conceptually a duplicate of a previous weird.\n', - }, - ], - }, - { - name: 'x509', - type: 'group', - default_field: false, - description: 'Fields exported by the Zeek x509 log.\n', - fields: [ - { - name: 'id', - type: 'keyword', - description: 'File id of this certificate.\n', - }, - { - name: 'certificate', - type: 'group', - description: 'Basic information about the certificate.\n', - fields: [ - { - name: 'version', - type: 'integer', - description: 'Version number.\n', - }, - { - name: 'serial', - type: 'keyword', - description: 'Serial number.\n', - }, - { - name: 'subject', - type: 'group', - description: 'Subject.\n', - fields: [ - { - name: 'country', - type: 'keyword', - description: 'Country provided in the certificate subject.\n', - }, - { - name: 'common_name', - type: 'keyword', - description: 'Common name provided in the certificate subject.\n', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality provided in the certificate subject.\n', - }, - { - name: 'organization', - type: 'keyword', - description: 'Organization provided in the certificate subject.\n', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: 'Organizational unit provided in the certificate subject.\n', - }, - { - name: 'state', - type: 'keyword', - description: 'State or province provided in the certificate subject.\n', - }, - ], - }, - { - name: 'issuer', - type: 'group', - description: 'Issuer.\n', - fields: [ - { - name: 'country', - type: 'keyword', - description: 'Country provided in the certificate issuer field.\n', - }, - { - name: 'common_name', - type: 'keyword', - description: 'Common name provided in the certificate issuer field.\n', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality provided in the certificate issuer field.\n', - }, - { - name: 'organization', - type: 'keyword', - description: 'Organization provided in the certificate issuer field.\n', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: - 'Organizational unit provided in the certificate issuer field.\n', - }, - { - name: 'state', - type: 'keyword', - description: - 'State or province provided in the certificate issuer field.\n', - }, - ], - }, - { - name: 'common_name', - type: 'keyword', - description: 'Last (most specific) common name.\n', - }, - { - name: 'valid', - type: 'group', - description: 'Certificate validity timestamps\n', - fields: [ - { - name: 'from', - type: 'date', - description: 'Timestamp before when certificate is not valid.\n', - }, - { - name: 'until', - type: 'date', - description: 'Timestamp after when certificate is not valid.\n', - }, - ], - }, - { - name: 'key', - type: 'group', - fields: [ - { - name: 'algorithm', - type: 'keyword', - description: 'Name of the key algorithm.\n', - }, - { - name: 'type', - type: 'keyword', - description: - 'Key type, if key parseable by openssl (either rsa, dsa or ec).\n', - }, - { - name: 'length', - type: 'integer', - description: 'Key length in bits.\n', - }, - ], - }, - { - name: 'signature_algorithm', - type: 'keyword', - description: 'Name of the signature algorithm.\n', - }, - { - name: 'exponent', - type: 'keyword', - description: 'Exponent, if RSA-certificate.\n', - }, - { - name: 'curve', - type: 'keyword', - description: 'Curve, if EC-certificate.\n', - }, - ], - }, - { - name: 'san', - type: 'group', - description: 'Subject alternative name extension of the certificate.\n', - fields: [ - { - name: 'dns', - type: 'keyword', - description: 'List of DNS entries in SAN.\n', - }, - { - name: 'uri', - type: 'keyword', - description: 'List of URI entries in SAN.\n', - }, - { - name: 'email', - type: 'keyword', - description: 'List of email entries in SAN.\n', - }, - { - name: 'ip', - type: 'ip', - description: 'List of IP entries in SAN.\n', - }, - { - name: 'other_fields', - type: 'boolean', - description: - 'True if the certificate contained other, not recognized or parsed name fields.\n', - }, - ], - }, - { - name: 'basic_constraints', - type: 'group', - description: 'Basic constraints extension of the certificate.\n', - fields: [ - { - name: 'certificate_authority', - type: 'boolean', - description: 'CA flag set or not.\n', - }, - { - name: 'path_length', - type: 'integer', - description: 'Maximum path length.\n', - }, - ], - }, - { - name: 'log_cert', - type: 'boolean', - description: - 'Present if policy/protocols/ssl/log-hostcerts-only.bro is loaded\nLogging of certificate is suppressed if set to F.\n', - }, - ], - }, - ], - }, - ], - }, - { - key: 'netflow', - title: 'NetFlow', - description: 'Fields from NetFlow and IPFIX flows.\n', - fields: [ - { - name: 'netflow', - type: 'group', - description: 'Fields from NetFlow and IPFIX.\n', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'The type of NetFlow record described by this event.\n', - }, - { - name: 'exporter', - type: 'group', - description: 'Metadata related to the exporter device that generated this record.\n', - fields: [ - { - name: 'address', - type: 'keyword', - description: "Exporter's network address in IP:port format.\n", - }, - { - name: 'source_id', - type: 'long', - description: 'Observation domain ID to which this record belongs.\n', - }, - { - name: 'timestamp', - type: 'date', - description: 'Time and date of export.\n', - }, - { - name: 'uptime_millis', - type: 'long', - description: 'How long the exporter process has been running, in milliseconds.\n', - }, - { - name: 'version', - type: 'integer', - description: 'NetFlow version used.\n', - }, - ], - }, - { - name: 'octet_delta_count', - type: 'long', - }, - { - name: 'packet_delta_count', - type: 'long', - }, - { - name: 'delta_flow_count', - type: 'long', - }, - { - name: 'protocol_identifier', - type: 'short', - }, - { - name: 'ip_class_of_service', - type: 'short', - }, - { - name: 'tcp_control_bits', - type: 'integer', - }, - { - name: 'source_transport_port', - type: 'integer', - }, - { - name: 'source_ipv4_address', - type: 'ip', - }, - { - name: 'source_ipv4_prefix_length', - type: 'short', - }, - { - name: 'ingress_interface', - type: 'long', - }, - { - name: 'destination_transport_port', - type: 'integer', - }, - { - name: 'destination_ipv4_address', - type: 'ip', - }, - { - name: 'destination_ipv4_prefix_length', - type: 'short', - }, - { - name: 'egress_interface', - type: 'long', - }, - { - name: 'ip_next_hop_ipv4_address', - type: 'ip', - }, - { - name: 'bgp_source_as_number', - type: 'long', - }, - { - name: 'bgp_destination_as_number', - type: 'long', - }, - { - name: 'bgp_next_hop_ipv4_address', - type: 'ip', - }, - { - name: 'post_mcast_packet_delta_count', - type: 'long', - }, - { - name: 'post_mcast_octet_delta_count', - type: 'long', - }, - { - name: 'flow_end_sys_up_time', - type: 'long', - }, - { - name: 'flow_start_sys_up_time', - type: 'long', - }, - { - name: 'post_octet_delta_count', - type: 'long', - }, - { - name: 'post_packet_delta_count', - type: 'long', - }, - { - name: 'minimum_ip_total_length', - type: 'long', - }, - { - name: 'maximum_ip_total_length', - type: 'long', - }, - { - name: 'source_ipv6_address', - type: 'ip', - }, - { - name: 'destination_ipv6_address', - type: 'ip', - }, - { - name: 'source_ipv6_prefix_length', - type: 'short', - }, - { - name: 'destination_ipv6_prefix_length', - type: 'short', - }, - { - name: 'flow_label_ipv6', - type: 'long', - }, - { - name: 'icmp_type_code_ipv4', - type: 'integer', - }, - { - name: 'igmp_type', - type: 'short', - }, - { - name: 'sampling_interval', - type: 'long', - }, - { - name: 'sampling_algorithm', - type: 'short', - }, - { - name: 'flow_active_timeout', - type: 'integer', - }, - { - name: 'flow_idle_timeout', - type: 'integer', - }, - { - name: 'engine_type', - type: 'short', - }, - { - name: 'engine_id', - type: 'short', - }, - { - name: 'exported_octet_total_count', - type: 'long', - }, - { - name: 'exported_message_total_count', - type: 'long', - }, - { - name: 'exported_flow_record_total_count', - type: 'long', - }, - { - name: 'ipv4_router_sc', - type: 'ip', - }, - { - name: 'source_ipv4_prefix', - type: 'ip', - }, - { - name: 'destination_ipv4_prefix', - type: 'ip', - }, - { - name: 'mpls_top_label_type', - type: 'short', - }, - { - name: 'mpls_top_label_ipv4_address', - type: 'ip', - }, - { - name: 'sampler_id', - type: 'short', - }, - { - name: 'sampler_mode', - type: 'short', - }, - { - name: 'sampler_random_interval', - type: 'long', - }, - { - name: 'class_id', - type: 'long', - }, - { - name: 'minimum_ttl', - type: 'short', - }, - { - name: 'maximum_ttl', - type: 'short', - }, - { - name: 'fragment_identification', - type: 'long', - }, - { - name: 'post_ip_class_of_service', - type: 'short', - }, - { - name: 'source_mac_address', - type: 'keyword', - }, - { - name: 'post_destination_mac_address', - type: 'keyword', - }, - { - name: 'vlan_id', - type: 'integer', - }, - { - name: 'post_vlan_id', - type: 'integer', - }, - { - name: 'ip_version', - type: 'short', - }, - { - name: 'flow_direction', - type: 'short', - }, - { - name: 'ip_next_hop_ipv6_address', - type: 'ip', - }, - { - name: 'bgp_next_hop_ipv6_address', - type: 'ip', - }, - { - name: 'ipv6_extension_headers', - type: 'long', - }, - { - name: 'mpls_top_label_stack_section', - type: 'short', - }, - { - name: 'mpls_label_stack_section2', - type: 'short', - }, - { - name: 'mpls_label_stack_section3', - type: 'short', - }, - { - name: 'mpls_label_stack_section4', - type: 'short', - }, - { - name: 'mpls_label_stack_section5', - type: 'short', - }, - { - name: 'mpls_label_stack_section6', - type: 'short', - }, - { - name: 'mpls_label_stack_section7', - type: 'short', - }, - { - name: 'mpls_label_stack_section8', - type: 'short', - }, - { - name: 'mpls_label_stack_section9', - type: 'short', - }, - { - name: 'mpls_label_stack_section10', - type: 'short', - }, - { - name: 'destination_mac_address', - type: 'keyword', - }, - { - name: 'post_source_mac_address', - type: 'keyword', - }, - { - name: 'interface_name', - type: 'keyword', - }, - { - name: 'interface_description', - type: 'keyword', - }, - { - name: 'sampler_name', - type: 'keyword', - }, - { - name: 'octet_total_count', - type: 'long', - }, - { - name: 'packet_total_count', - type: 'long', - }, - { - name: 'flags_and_sampler_id', - type: 'long', - }, - { - name: 'fragment_offset', - type: 'integer', - }, - { - name: 'forwarding_status', - type: 'short', - }, - { - name: 'mpls_vpn_route_distinguisher', - type: 'short', - }, - { - name: 'mpls_top_label_prefix_length', - type: 'short', - }, - { - name: 'src_traffic_index', - type: 'long', - }, - { - name: 'dst_traffic_index', - type: 'long', - }, - { - name: 'application_description', - type: 'keyword', - }, - { - name: 'application_id', - type: 'short', - }, - { - name: 'application_name', - type: 'keyword', - }, - { - name: 'post_ip_diff_serv_code_point', - type: 'short', - }, - { - name: 'multicast_replication_factor', - type: 'long', - }, - { - name: 'class_name', - type: 'keyword', - }, - { - name: 'classification_engine_id', - type: 'short', - }, - { - name: 'layer2packet_section_offset', - type: 'integer', - }, - { - name: 'layer2packet_section_size', - type: 'integer', - }, - { - name: 'layer2packet_section_data', - type: 'short', - }, - { - name: 'bgp_next_adjacent_as_number', - type: 'long', - }, - { - name: 'bgp_prev_adjacent_as_number', - type: 'long', - }, - { - name: 'exporter_ipv4_address', - type: 'ip', - }, - { - name: 'exporter_ipv6_address', - type: 'ip', - }, - { - name: 'dropped_octet_delta_count', - type: 'long', - }, - { - name: 'dropped_packet_delta_count', - type: 'long', - }, - { - name: 'dropped_octet_total_count', - type: 'long', - }, - { - name: 'dropped_packet_total_count', - type: 'long', - }, - { - name: 'flow_end_reason', - type: 'short', - }, - { - name: 'common_properties_id', - type: 'long', - }, - { - name: 'observation_point_id', - type: 'long', - }, - { - name: 'icmp_type_code_ipv6', - type: 'integer', - }, - { - name: 'mpls_top_label_ipv6_address', - type: 'ip', - }, - { - name: 'line_card_id', - type: 'long', - }, - { - name: 'port_id', - type: 'long', - }, - { - name: 'metering_process_id', - type: 'long', - }, - { - name: 'exporting_process_id', - type: 'long', - }, - { - name: 'template_id', - type: 'integer', - }, - { - name: 'wlan_channel_id', - type: 'short', - }, - { - name: 'wlan_ssid', - type: 'keyword', - }, - { - name: 'flow_id', - type: 'long', - }, - { - name: 'observation_domain_id', - type: 'long', - }, - { - name: 'flow_start_seconds', - type: 'date', - }, - { - name: 'flow_end_seconds', - type: 'date', - }, - { - name: 'flow_start_milliseconds', - type: 'date', - }, - { - name: 'flow_end_milliseconds', - type: 'date', - }, - { - name: 'flow_start_microseconds', - type: 'date', - }, - { - name: 'flow_end_microseconds', - type: 'date', - }, - { - name: 'flow_start_nanoseconds', - type: 'date', - }, - { - name: 'flow_end_nanoseconds', - type: 'date', - }, - { - name: 'flow_start_delta_microseconds', - type: 'long', - }, - { - name: 'flow_end_delta_microseconds', - type: 'long', - }, - { - name: 'system_init_time_milliseconds', - type: 'date', - }, - { - name: 'flow_duration_milliseconds', - type: 'long', - }, - { - name: 'flow_duration_microseconds', - type: 'long', - }, - { - name: 'observed_flow_total_count', - type: 'long', - }, - { - name: 'ignored_packet_total_count', - type: 'long', - }, - { - name: 'ignored_octet_total_count', - type: 'long', - }, - { - name: 'not_sent_flow_total_count', - type: 'long', - }, - { - name: 'not_sent_packet_total_count', - type: 'long', - }, - { - name: 'not_sent_octet_total_count', - type: 'long', - }, - { - name: 'destination_ipv6_prefix', - type: 'ip', - }, - { - name: 'source_ipv6_prefix', - type: 'ip', - }, - { - name: 'post_octet_total_count', - type: 'long', - }, - { - name: 'post_packet_total_count', - type: 'long', - }, - { - name: 'flow_key_indicator', - type: 'long', - }, - { - name: 'post_mcast_packet_total_count', - type: 'long', - }, - { - name: 'post_mcast_octet_total_count', - type: 'long', - }, - { - name: 'icmp_type_ipv4', - type: 'short', - }, - { - name: 'icmp_code_ipv4', - type: 'short', - }, - { - name: 'icmp_type_ipv6', - type: 'short', - }, - { - name: 'icmp_code_ipv6', - type: 'short', - }, - { - name: 'udp_source_port', - type: 'integer', - }, - { - name: 'udp_destination_port', - type: 'integer', - }, - { - name: 'tcp_source_port', - type: 'integer', - }, - { - name: 'tcp_destination_port', - type: 'integer', - }, - { - name: 'tcp_sequence_number', - type: 'long', - }, - { - name: 'tcp_acknowledgement_number', - type: 'long', - }, - { - name: 'tcp_window_size', - type: 'integer', - }, - { - name: 'tcp_urgent_pointer', - type: 'integer', - }, - { - name: 'tcp_header_length', - type: 'short', - }, - { - name: 'ip_header_length', - type: 'short', - }, - { - name: 'total_length_ipv4', - type: 'integer', - }, - { - name: 'payload_length_ipv6', - type: 'integer', - }, - { - name: 'ip_ttl', - type: 'short', - }, - { - name: 'next_header_ipv6', - type: 'short', - }, - { - name: 'mpls_payload_length', - type: 'long', - }, - { - name: 'ip_diff_serv_code_point', - type: 'short', - }, - { - name: 'ip_precedence', - type: 'short', - }, - { - name: 'fragment_flags', - type: 'short', - }, - { - name: 'octet_delta_sum_of_squares', - type: 'long', - }, - { - name: 'octet_total_sum_of_squares', - type: 'long', - }, - { - name: 'mpls_top_label_ttl', - type: 'short', - }, - { - name: 'mpls_label_stack_length', - type: 'long', - }, - { - name: 'mpls_label_stack_depth', - type: 'long', - }, - { - name: 'mpls_top_label_exp', - type: 'short', - }, - { - name: 'ip_payload_length', - type: 'long', - }, - { - name: 'udp_message_length', - type: 'integer', - }, - { - name: 'is_multicast', - type: 'short', - }, - { - name: 'ipv4_ihl', - type: 'short', - }, - { - name: 'ipv4_options', - type: 'long', - }, - { - name: 'tcp_options', - type: 'long', - }, - { - name: 'padding_octets', - type: 'short', - }, - { - name: 'collector_ipv4_address', - type: 'ip', - }, - { - name: 'collector_ipv6_address', - type: 'ip', - }, - { - name: 'export_interface', - type: 'long', - }, - { - name: 'export_protocol_version', - type: 'short', - }, - { - name: 'export_transport_protocol', - type: 'short', - }, - { - name: 'collector_transport_port', - type: 'integer', - }, - { - name: 'exporter_transport_port', - type: 'integer', - }, - { - name: 'tcp_syn_total_count', - type: 'long', - }, - { - name: 'tcp_fin_total_count', - type: 'long', - }, - { - name: 'tcp_rst_total_count', - type: 'long', - }, - { - name: 'tcp_psh_total_count', - type: 'long', - }, - { - name: 'tcp_ack_total_count', - type: 'long', - }, - { - name: 'tcp_urg_total_count', - type: 'long', - }, - { - name: 'ip_total_length', - type: 'long', - }, - { - name: 'post_nat_source_ipv4_address', - type: 'ip', - }, - { - name: 'post_nat_destination_ipv4_address', - type: 'ip', - }, - { - name: 'post_napt_source_transport_port', - type: 'integer', - }, - { - name: 'post_napt_destination_transport_port', - type: 'integer', - }, - { - name: 'nat_originating_address_realm', - type: 'short', - }, - { - name: 'nat_event', - type: 'short', - }, - { - name: 'initiator_octets', - type: 'long', - }, - { - name: 'responder_octets', - type: 'long', - }, - { - name: 'firewall_event', - type: 'short', - }, - { - name: 'ingress_vrfid', - type: 'long', - }, - { - name: 'egress_vrfid', - type: 'long', - }, - { - name: 'vr_fname', - type: 'keyword', - }, - { - name: 'post_mpls_top_label_exp', - type: 'short', - }, - { - name: 'tcp_window_scale', - type: 'integer', - }, - { - name: 'biflow_direction', - type: 'short', - }, - { - name: 'ethernet_header_length', - type: 'short', - }, - { - name: 'ethernet_payload_length', - type: 'integer', - }, - { - name: 'ethernet_total_length', - type: 'integer', - }, - { - name: 'dot1q_vlan_id', - type: 'integer', - }, - { - name: 'dot1q_priority', - type: 'short', - }, - { - name: 'dot1q_customer_vlan_id', - type: 'integer', - }, - { - name: 'dot1q_customer_priority', - type: 'short', - }, - { - name: 'metro_evc_id', - type: 'keyword', - }, - { - name: 'metro_evc_type', - type: 'short', - }, - { - name: 'pseudo_wire_id', - type: 'long', - }, - { - name: 'pseudo_wire_type', - type: 'integer', - }, - { - name: 'pseudo_wire_control_word', - type: 'long', - }, - { - name: 'ingress_physical_interface', - type: 'long', - }, - { - name: 'egress_physical_interface', - type: 'long', - }, - { - name: 'post_dot1q_vlan_id', - type: 'integer', - }, - { - name: 'post_dot1q_customer_vlan_id', - type: 'integer', - }, - { - name: 'ethernet_type', - type: 'integer', - }, - { - name: 'post_ip_precedence', - type: 'short', - }, - { - name: 'collection_time_milliseconds', - type: 'date', - }, - { - name: 'export_sctp_stream_id', - type: 'integer', - }, - { - name: 'max_export_seconds', - type: 'date', - }, - { - name: 'max_flow_end_seconds', - type: 'date', - }, - { - name: 'message_md5_checksum', - type: 'short', - }, - { - name: 'message_scope', - type: 'short', - }, - { - name: 'min_export_seconds', - type: 'date', - }, - { - name: 'min_flow_start_seconds', - type: 'date', - }, - { - name: 'opaque_octets', - type: 'short', - }, - { - name: 'session_scope', - type: 'short', - }, - { - name: 'max_flow_end_microseconds', - type: 'date', - }, - { - name: 'max_flow_end_milliseconds', - type: 'date', - }, - { - name: 'max_flow_end_nanoseconds', - type: 'date', - }, - { - name: 'min_flow_start_microseconds', - type: 'date', - }, - { - name: 'min_flow_start_milliseconds', - type: 'date', - }, - { - name: 'min_flow_start_nanoseconds', - type: 'date', - }, - { - name: 'collector_certificate', - type: 'short', - }, - { - name: 'exporter_certificate', - type: 'short', - }, - { - name: 'data_records_reliability', - type: 'boolean', - }, - { - name: 'observation_point_type', - type: 'short', - }, - { - name: 'new_connection_delta_count', - type: 'long', - }, - { - name: 'connection_sum_duration_seconds', - type: 'long', - }, - { - name: 'connection_transaction_id', - type: 'long', - }, - { - name: 'post_nat_source_ipv6_address', - type: 'ip', - }, - { - name: 'post_nat_destination_ipv6_address', - type: 'ip', - }, - { - name: 'nat_pool_id', - type: 'long', - }, - { - name: 'nat_pool_name', - type: 'keyword', - }, - { - name: 'anonymization_flags', - type: 'integer', - }, - { - name: 'anonymization_technique', - type: 'integer', - }, - { - name: 'information_element_index', - type: 'integer', - }, - { - name: 'p2p_technology', - type: 'keyword', - }, - { - name: 'tunnel_technology', - type: 'keyword', - }, - { - name: 'encrypted_technology', - type: 'keyword', - }, - { - name: 'bgp_validity_state', - type: 'short', - }, - { - name: 'ip_sec_spi', - type: 'long', - }, - { - name: 'gre_key', - type: 'long', - }, - { - name: 'nat_type', - type: 'short', - }, - { - name: 'initiator_packets', - type: 'long', - }, - { - name: 'responder_packets', - type: 'long', - }, - { - name: 'observation_domain_name', - type: 'keyword', - }, - { - name: 'selection_sequence_id', - type: 'long', - }, - { - name: 'selector_id', - type: 'long', - }, - { - name: 'information_element_id', - type: 'integer', - }, - { - name: 'selector_algorithm', - type: 'integer', - }, - { - name: 'sampling_packet_interval', - type: 'long', - }, - { - name: 'sampling_packet_space', - type: 'long', - }, - { - name: 'sampling_time_interval', - type: 'long', - }, - { - name: 'sampling_time_space', - type: 'long', - }, - { - name: 'sampling_size', - type: 'long', - }, - { - name: 'sampling_population', - type: 'long', - }, - { - name: 'sampling_probability', - type: 'double', - }, - { - name: 'data_link_frame_size', - type: 'integer', - }, - { - name: 'ip_header_packet_section', - type: 'short', - }, - { - name: 'ip_payload_packet_section', - type: 'short', - }, - { - name: 'data_link_frame_section', - type: 'short', - }, - { - name: 'mpls_label_stack_section', - type: 'short', - }, - { - name: 'mpls_payload_packet_section', - type: 'short', - }, - { - name: 'selector_id_total_pkts_observed', - type: 'long', - }, - { - name: 'selector_id_total_pkts_selected', - type: 'long', - }, - { - name: 'absolute_error', - type: 'double', - }, - { - name: 'relative_error', - type: 'double', - }, - { - name: 'observation_time_seconds', - type: 'date', - }, - { - name: 'observation_time_milliseconds', - type: 'date', - }, - { - name: 'observation_time_microseconds', - type: 'date', - }, - { - name: 'observation_time_nanoseconds', - type: 'date', - }, - { - name: 'digest_hash_value', - type: 'long', - }, - { - name: 'hash_ip_payload_offset', - type: 'long', - }, - { - name: 'hash_ip_payload_size', - type: 'long', - }, - { - name: 'hash_output_range_min', - type: 'long', - }, - { - name: 'hash_output_range_max', - type: 'long', - }, - { - name: 'hash_selected_range_min', - type: 'long', - }, - { - name: 'hash_selected_range_max', - type: 'long', - }, - { - name: 'hash_digest_output', - type: 'boolean', - }, - { - name: 'hash_initialiser_value', - type: 'long', - }, - { - name: 'selector_name', - type: 'keyword', - }, - { - name: 'upper_ci_limit', - type: 'double', - }, - { - name: 'lower_ci_limit', - type: 'double', - }, - { - name: 'confidence_level', - type: 'double', - }, - { - name: 'information_element_data_type', - type: 'short', - }, - { - name: 'information_element_description', - type: 'keyword', - }, - { - name: 'information_element_name', - type: 'keyword', - }, - { - name: 'information_element_range_begin', - type: 'long', - }, - { - name: 'information_element_range_end', - type: 'long', - }, - { - name: 'information_element_semantics', - type: 'short', - }, - { - name: 'information_element_units', - type: 'integer', - }, - { - name: 'private_enterprise_number', - type: 'long', - }, - { - name: 'virtual_station_interface_id', - type: 'short', - }, - { - name: 'virtual_station_interface_name', - type: 'keyword', - }, - { - name: 'virtual_station_uuid', - type: 'short', - }, - { - name: 'virtual_station_name', - type: 'keyword', - }, - { - name: 'layer2_segment_id', - type: 'long', - }, - { - name: 'layer2_octet_delta_count', - type: 'long', - }, - { - name: 'layer2_octet_total_count', - type: 'long', - }, - { - name: 'ingress_unicast_packet_total_count', - type: 'long', - }, - { - name: 'ingress_multicast_packet_total_count', - type: 'long', - }, - { - name: 'ingress_broadcast_packet_total_count', - type: 'long', - }, - { - name: 'egress_unicast_packet_total_count', - type: 'long', - }, - { - name: 'egress_broadcast_packet_total_count', - type: 'long', - }, - { - name: 'monitoring_interval_start_milli_seconds', - type: 'date', - }, - { - name: 'monitoring_interval_end_milli_seconds', - type: 'date', - }, - { - name: 'port_range_start', - type: 'integer', - }, - { - name: 'port_range_end', - type: 'integer', - }, - { - name: 'port_range_step_size', - type: 'integer', - }, - { - name: 'port_range_num_ports', - type: 'integer', - }, - { - name: 'sta_mac_address', - type: 'keyword', - }, - { - name: 'sta_ipv4_address', - type: 'ip', - }, - { - name: 'wtp_mac_address', - type: 'keyword', - }, - { - name: 'ingress_interface_type', - type: 'long', - }, - { - name: 'egress_interface_type', - type: 'long', - }, - { - name: 'rtp_sequence_number', - type: 'integer', - }, - { - name: 'user_name', - type: 'keyword', - }, - { - name: 'application_category_name', - type: 'keyword', - }, - { - name: 'application_sub_category_name', - type: 'keyword', - }, - { - name: 'application_group_name', - type: 'keyword', - }, - { - name: 'original_flows_present', - type: 'long', - }, - { - name: 'original_flows_initiated', - type: 'long', - }, - { - name: 'original_flows_completed', - type: 'long', - }, - { - name: 'distinct_count_of_source_ip_address', - type: 'long', - }, - { - name: 'distinct_count_of_destination_ip_address', - type: 'long', - }, - { - name: 'distinct_count_of_source_ipv4_address', - type: 'long', - }, - { - name: 'distinct_count_of_destination_ipv4_address', - type: 'long', - }, - { - name: 'distinct_count_of_source_ipv6_address', - type: 'long', - }, - { - name: 'distinct_count_of_destination_ipv6_address', - type: 'long', - }, - { - name: 'value_distribution_method', - type: 'short', - }, - { - name: 'rfc3550_jitter_milliseconds', - type: 'long', - }, - { - name: 'rfc3550_jitter_microseconds', - type: 'long', - }, - { - name: 'rfc3550_jitter_nanoseconds', - type: 'long', - }, - { - name: 'dot1q_dei', - type: 'boolean', - }, - { - name: 'dot1q_customer_dei', - type: 'boolean', - }, - { - name: 'flow_selector_algorithm', - type: 'integer', - }, - { - name: 'flow_selected_octet_delta_count', - type: 'long', - }, - { - name: 'flow_selected_packet_delta_count', - type: 'long', - }, - { - name: 'flow_selected_flow_delta_count', - type: 'long', - }, - { - name: 'selector_id_total_flows_observed', - type: 'long', - }, - { - name: 'selector_id_total_flows_selected', - type: 'long', - }, - { - name: 'sampling_flow_interval', - type: 'long', - }, - { - name: 'sampling_flow_spacing', - type: 'long', - }, - { - name: 'flow_sampling_time_interval', - type: 'long', - }, - { - name: 'flow_sampling_time_spacing', - type: 'long', - }, - { - name: 'hash_flow_domain', - type: 'integer', - }, - { - name: 'transport_octet_delta_count', - type: 'long', - }, - { - name: 'transport_packet_delta_count', - type: 'long', - }, - { - name: 'original_exporter_ipv4_address', - type: 'ip', - }, - { - name: 'original_exporter_ipv6_address', - type: 'ip', - }, - { - name: 'original_observation_domain_id', - type: 'long', - }, - { - name: 'intermediate_process_id', - type: 'long', - }, - { - name: 'ignored_data_record_total_count', - type: 'long', - }, - { - name: 'data_link_frame_type', - type: 'integer', - }, - { - name: 'section_offset', - type: 'integer', - }, - { - name: 'section_exported_octets', - type: 'integer', - }, - { - name: 'dot1q_service_instance_tag', - type: 'short', - }, - { - name: 'dot1q_service_instance_id', - type: 'long', - }, - { - name: 'dot1q_service_instance_priority', - type: 'short', - }, - { - name: 'dot1q_customer_source_mac_address', - type: 'keyword', - }, - { - name: 'dot1q_customer_destination_mac_address', - type: 'keyword', - }, - { - name: 'post_layer2_octet_delta_count', - type: 'long', - }, - { - name: 'post_mcast_layer2_octet_delta_count', - type: 'long', - }, - { - name: 'post_layer2_octet_total_count', - type: 'long', - }, - { - name: 'post_mcast_layer2_octet_total_count', - type: 'long', - }, - { - name: 'minimum_layer2_total_length', - type: 'long', - }, - { - name: 'maximum_layer2_total_length', - type: 'long', - }, - { - name: 'dropped_layer2_octet_delta_count', - type: 'long', - }, - { - name: 'dropped_layer2_octet_total_count', - type: 'long', - }, - { - name: 'ignored_layer2_octet_total_count', - type: 'long', - }, - { - name: 'not_sent_layer2_octet_total_count', - type: 'long', - }, - { - name: 'layer2_octet_delta_sum_of_squares', - type: 'long', - }, - { - name: 'layer2_octet_total_sum_of_squares', - type: 'long', - }, - { - name: 'layer2_frame_delta_count', - type: 'long', - }, - { - name: 'layer2_frame_total_count', - type: 'long', - }, - { - name: 'pseudo_wire_destination_ipv4_address', - type: 'ip', - }, - { - name: 'ignored_layer2_frame_total_count', - type: 'long', - }, - { - name: 'mib_object_value_integer', - type: 'integer', - }, - { - name: 'mib_object_value_octet_string', - type: 'short', - }, - { - name: 'mib_object_value_oid', - type: 'short', - }, - { - name: 'mib_object_value_bits', - type: 'short', - }, - { - name: 'mib_object_value_ip_address', - type: 'ip', - }, - { - name: 'mib_object_value_counter', - type: 'long', - }, - { - name: 'mib_object_value_gauge', - type: 'long', - }, - { - name: 'mib_object_value_time_ticks', - type: 'long', - }, - { - name: 'mib_object_value_unsigned', - type: 'long', - }, - { - name: 'mib_object_identifier', - type: 'short', - }, - { - name: 'mib_sub_identifier', - type: 'long', - }, - { - name: 'mib_index_indicator', - type: 'long', - }, - { - name: 'mib_capture_time_semantics', - type: 'short', - }, - { - name: 'mib_context_engine_id', - type: 'short', - }, - { - name: 'mib_context_name', - type: 'keyword', - }, - { - name: 'mib_object_name', - type: 'keyword', - }, - { - name: 'mib_object_description', - type: 'keyword', - }, - { - name: 'mib_object_syntax', - type: 'keyword', - }, - { - name: 'mib_module_name', - type: 'keyword', - }, - { - name: 'mobile_imsi', - type: 'keyword', - }, - { - name: 'mobile_msisdn', - type: 'keyword', - }, - { - name: 'http_status_code', - type: 'integer', - }, - { - name: 'source_transport_ports_limit', - type: 'integer', - }, - { - name: 'http_request_method', - type: 'keyword', - }, - { - name: 'http_request_host', - type: 'keyword', - }, - { - name: 'http_request_target', - type: 'keyword', - }, - { - name: 'http_message_version', - type: 'keyword', - }, - { - name: 'nat_instance_id', - type: 'long', - }, - { - name: 'internal_address_realm', - type: 'short', - }, - { - name: 'external_address_realm', - type: 'short', - }, - { - name: 'nat_quota_exceeded_event', - type: 'long', - }, - { - name: 'nat_threshold_event', - type: 'long', - }, - { - name: 'http_user_agent', - type: 'keyword', - }, - { - name: 'http_content_type', - type: 'keyword', - }, - { - name: 'http_reason_phrase', - type: 'keyword', - }, - { - name: 'max_session_entries', - type: 'long', - }, - { - name: 'max_bib_entries', - type: 'long', - }, - { - name: 'max_entries_per_user', - type: 'long', - }, - { - name: 'max_subscribers', - type: 'long', - }, - { - name: 'max_fragments_pending_reassembly', - type: 'long', - }, - { - name: 'address_pool_high_threshold', - type: 'long', - }, - { - name: 'address_pool_low_threshold', - type: 'long', - }, - { - name: 'address_port_mapping_high_threshold', - type: 'long', - }, - { - name: 'address_port_mapping_low_threshold', - type: 'long', - }, - { - name: 'address_port_mapping_per_user_high_threshold', - type: 'long', - }, - { - name: 'global_address_mapping_high_threshold', - type: 'long', - }, - { - name: 'vpn_identifier', - type: 'short', - }, - ], - }, - ], - }, - { - key: 's3', - title: 's3', - description: 'S3 fields from s3 input.\n', - release: 'beta', - fields: [ - { - name: 'bucket_name', - type: 'keyword', - description: 'Name of the S3 bucket that this log retrieved from.\n', - }, - { - name: 'object_key', - type: 'keyword', - description: 'Name of the S3 object that this log retrieved from.\n', - }, - ], - }, - { - key: 'cef', - title: 'Decode CEF processor fields', - description: 'Common Event Format (CEF) data.\n', - fields: [ - { - name: 'cef', - type: 'group', - description: - 'By default the `decode_cef` processor writes all data from the CEF message to this `cef` object. It contains the CEF header fields and the extension data.\n', - fields: [ - { - name: 'version', - type: 'keyword', - description: 'Version of the CEF specification used by the message.\n', - }, - { - name: 'device.vendor', - type: 'keyword', - description: 'Vendor of the device that produced the message.\n', - }, - { - name: 'device.product', - type: 'keyword', - description: 'Product of the device that produced the message.\n', - }, - { - name: 'device.version', - type: 'keyword', - description: 'Version of the product that produced the message.\n', - }, - { - name: 'device.event_class_id', - type: 'keyword', - description: 'Unique identifier of the event type.\n', - }, - { - name: 'severity', - type: 'keyword', - example: 'Very-High', - description: - 'Importance of the event. The valid string values are Unknown, Low, Medium, High, and Very-High. The valid integer values are 0-3=Low, 4-6=Medium, 7- 8=High, and 9-10=Very-High.\n', - }, - { - name: 'name', - type: 'keyword', - description: 'Short description of the event.\n', - }, - { - name: 'extensions', - type: 'group', - description: 'Collection of key-value pairs carried in the CEF extension field.\n', - default_field: false, - fields: [ - { - name: 'agentAddress', - type: 'ip', - description: 'The IP address of the ArcSight connector that processed the event.', - }, - { - name: 'agentDnsDomain', - type: 'keyword', - description: - 'The DNS domain name of the ArcSight connector that processed the event.', - }, - { - name: 'agentHostName', - type: 'keyword', - description: 'The hostname of the ArcSight connector that processed the event.', - }, - { - name: 'agentId', - type: 'keyword', - description: 'The agent ID of the ArcSight connector that processed the event.', - }, - { - name: 'agentMacAddress', - type: 'keyword', - description: 'The MAC address of the ArcSight connector that processed the event.', - }, - { - name: 'agentNtDomain', - type: 'keyword', - description: '', - }, - { - name: 'agentReceiptTime', - type: 'date', - description: - 'The time at which information about the event was received by the ArcSight connector.', - }, - { - name: 'agentTimeZone', - type: 'keyword', - description: - 'The agent time zone of the ArcSight connector that processed the event.', - }, - { - name: 'agentTranslatedAddress', - type: 'ip', - description: '', - }, - { - name: 'agentTranslatedZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'agentTranslatedZoneURI', - type: 'keyword', - description: '', - }, - { - name: 'agentType', - type: 'keyword', - description: 'The agent type of the ArcSight connector that processed the event', - }, - { - name: 'agentVersion', - type: 'keyword', - description: 'The version of the ArcSight connector that processed the event.', - }, - { - name: 'agentZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'agentZoneURI', - type: 'keyword', - description: '', - }, - { - name: 'applicationProtocol', - type: 'keyword', - description: - 'Application level protocol, example values are HTTP, HTTPS, SSHv2, Telnet, POP, IMPA, IMAPS, and so on.', - }, - { - name: 'baseEventCount', - type: 'long', - description: - 'A count associated with this event. How many times was this same event observed? Count can be omitted if it is 1.', - }, - { - name: 'bytesIn', - type: 'long', - description: - 'Number of bytes transferred inbound, relative to the source to destination relationship, meaning that data was flowing from source to destination.', - }, - { - name: 'bytesOut', - type: 'long', - description: - 'Number of bytes transferred outbound relative to the source to destination relationship. For example, the byte number of data flowing from the destination to the source.', - }, - { - name: 'customerExternalID', - type: 'keyword', - description: '', - }, - { - name: 'customerURI', - type: 'keyword', - description: '', - }, - { - name: 'destinationAddress', - type: 'ip', - description: - 'Identifies the destination address that the event refers to in an IP network. The format is an IPv4 address.', - }, - { - name: 'destinationDnsDomain', - type: 'keyword', - description: - 'The DNS domain part of the complete fully qualified domain name (FQDN).', - }, - { - name: 'destinationGeoLatitude', - type: 'double', - description: - "The latitudinal value from which the destination's IP address belongs.", - }, - { - name: 'destinationGeoLongitude', - type: 'double', - description: - "The longitudinal value from which the destination's IP address belongs.", - }, - { - name: 'destinationHostName', - type: 'keyword', - description: - 'Identifies the destination that an event refers to in an IP network. The format should be a fully qualified domain name (FQDN) associated with the destination node, when a node is available.', - }, - { - name: 'destinationMacAddress', - type: 'keyword', - description: 'Six colon-seperated hexadecimal numbers.', - }, - { - name: 'destinationNtDomain', - type: 'keyword', - description: 'The Windows domain name of the destination address.', - }, - { - name: 'destinationPort', - type: 'long', - description: 'The valid port numbers are between 0 and 65535.', - }, - { - name: 'destinationProcessId', - type: 'long', - description: - 'Provides the ID of the destination process associated with the event. For example, if an event contains process ID 105, "105" is the process ID.', - }, - { - name: 'destinationProcessName', - type: 'keyword', - description: "The name of the event's destination process.", - }, - { - name: 'destinationServiceName', - type: 'keyword', - description: 'The service targeted by this event.', - }, - { - name: 'destinationTranslatedAddress', - type: 'ip', - description: - 'Identifies the translated destination that the event refers to in an IP network.', - }, - { - name: 'destinationTranslatedPort', - type: 'long', - description: - 'Port after it was translated; for example, a firewall. Valid port numbers are 0 to 65535.', - }, - { - name: 'destinationTranslatedZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'destinationTranslatedZoneURI', - type: 'keyword', - description: - 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.', - }, - { - name: 'destinationUserId', - type: 'keyword', - description: - 'Identifies the destination user by ID. For example, in UNIX, the root user is generally associated with user ID 0.', - }, - { - name: 'destinationUserName', - type: 'keyword', - description: - "Identifies the destination user by name. This is the user associated with the event's destination. Email addresses are often mapped into the UserName fields. The recipient is a candidate to put into this field.", - }, - { - name: 'destinationUserPrivileges', - type: 'keyword', - description: - 'The typical values are "Administrator", "User", and "Guest". This identifies the destination user\'s privileges. In UNIX, for example, activity executed on the root user would be identified with destinationUser Privileges of "Administrator".', - }, - { - name: 'destinationZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'destinationZoneURI', - type: 'keyword', - description: - 'The URI for the Zone that the destination asset has been assigned to in ArcSight.', - }, - { - name: 'deviceAction', - type: 'keyword', - description: 'Action taken by the device.', - }, - { - name: 'deviceAddress', - type: 'ip', - description: - 'Identifies the device address that an event refers to in an IP network.', - }, - { - name: 'deviceCustomFloatingPoint1Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomFloatingPoint3Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomFloatingPoint4Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomDate1', - type: 'date', - description: - 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomDate1Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomDate2', - type: 'date', - description: - 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomDate2Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomFloatingPoint1', - type: 'double', - description: - 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomFloatingPoint2', - type: 'double', - description: - 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomFloatingPoint2Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomFloatingPoint3', - type: 'double', - description: - 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomFloatingPoint4', - type: 'double', - description: - 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomIPv6Address1', - type: 'ip', - description: - 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomIPv6Address1Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomIPv6Address2', - type: 'ip', - description: - 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomIPv6Address2Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomIPv6Address3', - type: 'ip', - description: - 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomIPv6Address3Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomIPv6Address4', - type: 'ip', - description: - 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', - }, - { - name: 'deviceCustomIPv6Address4Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomNumber1', - type: 'long', - description: - 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomNumber1Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomNumber2', - type: 'long', - description: - 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomNumber2Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomNumber3', - type: 'long', - description: - 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomNumber3Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomString1', - type: 'keyword', - description: - 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomString1Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomString2', - type: 'keyword', - description: - 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomString2Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomString3', - type: 'keyword', - description: - 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomString3Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomString4', - type: 'keyword', - description: - 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomString4Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomString5', - type: 'keyword', - description: - 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomString5Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceCustomString6', - type: 'keyword', - description: - 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceCustomString6Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceDirection', - type: 'long', - description: - 'Any information about what direction the observed communication has taken. The following values are supported - "0" for inbound or "1" for outbound.', - }, - { - name: 'deviceDnsDomain', - type: 'keyword', - description: - 'The DNS domain part of the complete fully qualified domain name (FQDN).', - }, - { - name: 'deviceEventCategory', - type: 'keyword', - description: - 'Represents the category assigned by the originating device. Devices often use their own categorization schema to classify event. Example "/Monitor/Disk/Read".', - }, - { - name: 'deviceExternalId', - type: 'keyword', - description: 'A name that uniquely identifies the device generating this event.', - }, - { - name: 'deviceFacility', - type: 'keyword', - description: - 'The facility generating this event. For example, Syslog has an explicit facility associated with every event.', - }, - { - name: 'deviceFlexNumber1', - type: 'long', - description: - 'One of two alternative number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceFlexNumber1Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceFlexNumber2', - type: 'long', - description: - 'One of two alternative number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', - }, - { - name: 'deviceFlexNumber2Label', - type: 'keyword', - description: - 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', - }, - { - name: 'deviceHostName', - type: 'keyword', - description: - 'The format should be a fully qualified domain name (FQDN) associated with the device node, when a node is available.', - }, - { - name: 'deviceInboundInterface', - type: 'keyword', - description: 'Interface on which the packet or data entered the device.', - }, - { - name: 'deviceMacAddress', - type: 'keyword', - description: 'Six colon-separated hexadecimal numbers.', - }, - { - name: 'deviceNtDomain', - type: 'keyword', - description: 'The Windows domain name of the device address.', - }, - { - name: 'deviceOutboundInterface', - type: 'keyword', - description: 'Interface on which the packet or data left the device.', - }, - { - name: 'devicePayloadId', - type: 'keyword', - description: 'Unique identifier for the payload associated with the event.', - }, - { - name: 'deviceProcessId', - type: 'long', - description: 'Provides the ID of the process on the device generating the event.', - }, - { - name: 'deviceProcessName', - type: 'keyword', - description: - 'Process name associated with the event. An example might be the process generating the syslog entry in UNIX.', - }, - { - name: 'deviceReceiptTime', - type: 'date', - description: - 'The time at which the event related to the activity was received. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)', - }, - { - name: 'deviceTimeZone', - type: 'keyword', - description: 'The timezone for the device generating the event.', - }, - { - name: 'deviceTranslatedAddress', - type: 'ip', - description: - 'Identifies the translated device address that the event refers to in an IP network.', - }, - { - name: 'deviceTranslatedZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'deviceTranslatedZoneURI', - type: 'keyword', - description: - 'The URI for the Translated Zone that the device asset has been assigned to in ArcSight.', - }, - { - name: 'deviceZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'deviceZoneURI', - type: 'keyword', - description: - 'Thee URI for the Zone that the device asset has been assigned to in ArcSight.', - }, - { - name: 'endTime', - type: 'date', - description: - 'The time at which the activity related to the event ended. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st1970). An example would be reporting the end of a session.', - }, - { - name: 'eventId', - type: 'long', - description: 'This is a unique ID that ArcSight assigns to each event.', - }, - { - name: 'eventOutcome', - type: 'keyword', - description: "Displays the outcome, usually as 'success' or 'failure'.", - }, - { - name: 'externalId', - type: 'keyword', - description: - 'The ID used by an originating device. They are usually increasing numbers, associated with events.', - }, - { - name: 'fileCreateTime', - type: 'date', - description: 'Time when the file was created.', - }, - { - name: 'fileHash', - type: 'keyword', - description: 'Hash of a file.', - }, - { - name: 'fileId', - type: 'keyword', - description: 'An ID associated with a file could be the inode.', - }, - { - name: 'fileModificationTime', - type: 'date', - description: 'Time when the file was last modified.', - }, - { - name: 'filename', - type: 'keyword', - description: 'Name of the file only (without its path).', - }, - { - name: 'filePath', - type: 'keyword', - description: 'Full path to the file, including file name itself.', - }, - { - name: 'filePermission', - type: 'keyword', - description: 'Permissions of the file.', - }, - { - name: 'fileSize', - type: 'long', - description: 'Size of the file.', - }, - { - name: 'fileType', - type: 'keyword', - description: 'Type of file (pipe, socket, etc.)', - }, - { - name: 'flexDate1', - type: 'date', - description: - 'A timestamp field available to map a timestamp that does not apply to any other defined timestamp field in this dictionary. Use all flex fields sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.', - }, - { - name: 'flexDate1Label', - type: 'keyword', - description: - 'The label field is a string and describes the purpose of the flex field.', - }, - { - name: 'flexString1', - type: 'keyword', - description: - 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.', - }, - { - name: 'flexString2', - type: 'keyword', - description: - 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.', - }, - { - name: 'flexString1Label', - type: 'keyword', - description: - 'The label field is a string and describes the purpose of the flex field.', - }, - { - name: 'flexString2Label', - type: 'keyword', - description: - 'The label field is a string and describes the purpose of the flex field.', - }, - { - name: 'message', - type: 'keyword', - description: - 'An arbitrary message giving more details about the event. Multi-line entries can be produced by using \\n as the new line separator.', - }, - { - name: 'oldFileCreateTime', - type: 'date', - description: 'Time when old file was created.', - }, - { - name: 'oldFileHash', - type: 'keyword', - description: 'Hash of the old file.', - }, - { - name: 'oldFileId', - type: 'keyword', - description: 'An ID associated with the old file could be the inode.', - }, - { - name: 'oldFileModificationTime', - type: 'date', - description: 'Time when old file was last modified.', - }, - { - name: 'oldFileName', - type: 'keyword', - description: 'Name of the old file.', - }, - { - name: 'oldFilePath', - type: 'keyword', - description: 'Full path to the old file, including the file name itself.', - }, - { - name: 'oldFilePermission', - type: 'keyword', - description: 'Permissions of the old file.', - }, - { - name: 'oldFileSize', - type: 'long', - description: 'Size of the old file.', - }, - { - name: 'oldFileType', - type: 'keyword', - description: 'Type of the old file (pipe, socket, etc.)', - }, - { - name: 'rawEvent', - type: 'keyword', - description: '', - }, - { - name: 'Reason', - type: 'keyword', - description: - 'The reason an audit event was generated. For example "bad password" or "unknown user". This could also be an error or return code. Example "0x1234".', - }, - { - name: 'requestClientApplication', - type: 'keyword', - description: 'The User-Agent associated with the request.', - }, - { - name: 'requestContext', - type: 'keyword', - description: - 'Description of the content from which the request originated (for example, HTTP Referrer)', - }, - { - name: 'requestCookies', - type: 'keyword', - description: 'Cookies associated with the request.', - }, - { - name: 'requestMethod', - type: 'keyword', - description: 'The HTTP method used to access a URL.', - }, - { - name: 'requestUrl', - type: 'keyword', - description: - 'In the case of an HTTP request, this field contains the URL accessed. The URL should contain the protocol as well.', - }, - { - name: 'sourceAddress', - type: 'ip', - description: 'Identifies the source that an event refers to in an IP network.', - }, - { - name: 'sourceDnsDomain', - type: 'keyword', - description: - 'The DNS domain part of the complete fully qualified domain name (FQDN).', - }, - { - name: 'sourceGeoLatitude', - type: 'double', - description: '', - }, - { - name: 'sourceGeoLongitude', - type: 'double', - description: '', - }, - { - name: 'sourceHostName', - type: 'keyword', - description: - "Identifies the source that an event refers to in an IP network. The format should be a fully qualified domain name (FQDN) associated with the source node, when a mode is available. Examples: 'host' or 'host.domain.com'.\n", - }, - { - name: 'sourceMacAddress', - type: 'keyword', - example: '00:0d:60:af:1b:61', - description: 'Six colon-separated hexadecimal numbers.', - }, - { - name: 'sourceNtDomain', - type: 'keyword', - description: 'The Windows domain name for the source address.', - }, - { - name: 'sourcePort', - type: 'long', - description: 'The valid port numbers are 0 to 65535.', - }, - { - name: 'sourceProcessId', - type: 'long', - description: 'The ID of the source process associated with the event.', - }, - { - name: 'sourceProcessName', - type: 'keyword', - description: "The name of the event's source process.", - }, - { - name: 'sourceServiceName', - type: 'keyword', - description: 'The service that is responsible for generating this event.', - }, - { - name: 'sourceTranslatedAddress', - type: 'ip', - description: - 'Identifies the translated source that the event refers to in an IP network.', - }, - { - name: 'sourceTranslatedPort', - type: 'long', - description: - 'A port number after being translated by, for example, a firewall. Valid port numbers are 0 to 65535.', - }, - { - name: 'sourceTranslatedZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'sourceTranslatedZoneURI', - type: 'keyword', - description: - 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.', - }, - { - name: 'sourceUserId', - type: 'keyword', - description: - 'Identifies the source user by ID. This is the user associated with the source of the event. For example, in UNIX, the root user is generally associated with user ID 0.', - }, - { - name: 'sourceUserName', - type: 'keyword', - description: - 'Identifies the source user by name. Email addresses are also mapped into the UserName fields. The sender is a candidate to put into this field.', - }, - { - name: 'sourceUserPrivileges', - type: 'keyword', - description: - 'The typical values are "Administrator", "User", and "Guest". It identifies the source user\'s privileges. In UNIX, for example, activity executed by the root user would be identified with "Administrator".', - }, - { - name: 'sourceZoneExternalID', - type: 'keyword', - description: '', - }, - { - name: 'sourceZoneURI', - type: 'keyword', - description: - 'The URI for the Zone that the source asset has been assigned to in ArcSight.', - }, - { - name: 'startTime', - type: 'date', - description: - 'The time when the activity the event referred to started. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)', - }, - { - name: 'transportProtocol', - type: 'keyword', - description: - 'Identifies the Layer-4 protocol used. The possible values are protocols such as TCP or UDP.', - }, - { - name: 'type', - type: 'long', - description: - '0 means base event, 1 means aggregated, 2 means correlation, and 3 means action. This field can be omitted for base events (type 0).', - }, - { - name: 'categoryDeviceType', - type: 'keyword', - description: 'Device type. Examples - Proxy, IDS, Web Server', - }, - { - name: 'categoryObject', - type: 'keyword', - description: - 'Object that the event is about. For example it can be an operating sytem, database, file, etc.', - }, - { - name: 'categoryBehavior', - type: 'keyword', - description: - "Action or a behavior associated with an event. It's what is being done to the object.", - }, - { - name: 'categoryTechnique', - type: 'keyword', - description: 'Technique being used (e.g. /DoS).', - }, - { - name: 'categoryDeviceGroup', - type: 'keyword', - description: 'General device group like Firewall.', - }, - { - name: 'categorySignificance', - type: 'keyword', - description: 'Characterization of the importance of the event.', - }, - { - name: 'categoryOutcome', - type: 'keyword', - description: 'Outcome of the event (e.g. sucess, failure, or attempt).', - }, - { - name: 'managerReceiptTime', - type: 'date', - description: 'When the Arcsight ESM received the event.', - }, - ], - }, - ], - }, - { - name: 'source.service.name', - type: 'keyword', - description: 'Service that is the source of the event.', - }, - { - name: 'destination.service.name', - type: 'keyword', - description: 'Service that is the target of the event.', - }, - ], - }, -]; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/index.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/index.ts deleted file mode 100644 index bd7e7d4eec83b5..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/index.ts +++ /dev/null @@ -1,37 +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. - */ - -export { auditbeatSchema } from './auditbeat'; -export { filebeatSchema } from './filebeat'; -export { packetbeatSchema } from './packetbeat'; -export { winlogbeatSchema } from './winlogbeat'; -export { ecsSchema } from './ecs'; - -export const extraSchemaField = { - _id: { - description: 'Each document has an _id that uniquely identifies it', - example: 'Y-6TfmcB0WOhS6qyMv3s', - footnote: '', - group: 1, - level: 'core', - name: '_id', - required: true, - type: 'keyword', - }, - _index: { - description: - 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', - example: 'auditbeat-8.0.0-2019.02.19-000001', - footnote: '', - group: 1, - level: 'core', - name: '_index', - required: true, - type: 'keyword', - }, -}; - -export const baseCategoryFields = ['@timestamp', 'labels', 'message', 'tags']; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/packetbeat.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/packetbeat.ts deleted file mode 100644 index 0be2e48fe46689..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/packetbeat.ts +++ /dev/null @@ -1,8556 +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. - */ - -/** - * An instance of the unmodified schema exported from auditbeat-8.0.0-SNAPSHOT-darwin-x86_64.tar.gz - * - */ - -import { Schema } from '../type'; - -export const packetbeatSchema: Schema = [ - { - key: 'ecs', - title: 'ECS', - description: 'ECS Fields.', - fields: [ - { - name: '@timestamp', - level: 'core', - required: true, - type: 'date', - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'labels', - level: 'core', - type: 'object', - object_type: 'keyword', - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - }, - { - name: 'tags', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - }, - { - name: 'agent', - title: 'Agent', - group: 2, - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - footnote: - 'Examples: In the case of Beats for logs, the agent.name is filebeat.\nFor APM, it is the agent running in the app/service. The agent information does\nnot change if data is sent through queuing systems like Kafka, Redis, or processing\nsystems such as Logstash or APM Server.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the agent.', - example: '6.0.0-rc2', - }, - ], - }, - { - name: 'as', - title: 'Autonomous System', - group: 2, - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - type: 'group', - fields: [ - { - name: 'number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - ], - }, - { - name: 'client', - title: 'Client', - group: 2, - description: - 'A client is defined as the initiator of a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the client is the initiator of the TCP connection that sends\nthe SYN packet(s). For other protocols, the client is generally the initiator\nor requestor in the network transaction. Some systems use the term "originator"\nto refer the client in TCP connections. The client fields describe details about\nthe system acting as the client in the network event. Client fields are usually\npopulated in conjunction with server fields. Client fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event client addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the client to the server.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Client domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the client.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the client.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated IP of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions (e.g. internal client\nto internet).\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the client to the server.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the client.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered client domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'cloud', - title: 'Cloud', - group: 2, - description: 'Fields related to the cloud or infrastructure the events are coming\nfrom.', - footnote: - 'Examples: If Metricbeat is running on an EC2 host and fetches data\nfrom its host, the cloud info contains the data about this machine. If Metricbeat\nruns on a remote machine outside the cloud and fetches data from a service running\nin the cloud, the field contains cloud data from the machine the service is\nrunning on.', - type: 'group', - fields: [ - { - name: 'account.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The cloud account or organization id used to identify different\nentities in a multi-tenant environment.\n\nExamples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: 666777888999, - }, - { - name: 'availability_zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - }, - { - name: 'instance.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance ID of the host machine.', - example: 'i-1234567890abcdef0', - }, - { - name: 'instance.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Instance name of the host machine.', - }, - { - name: 'machine.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Machine type of the host machine.', - example: 't2.medium', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the cloud provider. Example values are aws, azure, gcp,\nor digitalocean.', - example: 'aws', - }, - { - name: 'region', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Region in which this host is running.', - example: 'us-east-1', - }, - ], - }, - { - name: 'code_signature', - title: 'Code Signature', - group: 2, - description: 'These fields contain information about binary code signatures.', - type: 'group', - fields: [ - { - name: 'exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - ], - }, - { - name: 'container', - title: 'Container', - group: 2, - description: - 'Container fields are used for meta information about the specific\ncontainer that is the source of information.\n\nThese fields help correlate data based containers from any runtime.', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique container id.', - }, - { - name: 'image.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the image the container was built on.', - }, - { - name: 'image.tag', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container image tags.', - }, - { - name: 'labels', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: 'Image labels.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Container name.', - }, - { - name: 'runtime', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Runtime managing this container.', - example: 'docker', - }, - ], - }, - { - name: 'destination', - title: 'Destination', - group: 2, - description: - 'Destination fields describe details about the destination of a packet/event.\n\nDestination fields are usually populated in conjunction with source fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event destination addresses are defined ambiguously. The\nevent will sometimes list an IP, a domain or a unix socket. You should always\nstore the raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the destination to the source.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Destination domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the destination.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the destination.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Port the source session is translated to by NAT Device.\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the destination to the source.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the destination.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered destination domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'dll', - title: 'DLL', - group: 2, - description: - 'These fields contain information about code libraries dynamically\nloaded into processes.\n\n\nMany operating systems refer to "shared code libraries" with different names,\nbut this field set refers to all of the following:\n\n* Dynamic-link library (`.dll`) commonly used on Windows\n\n* Shared Object (`.so`) commonly used on Unix-like operating systems\n\n* Dynamic library (`.dylib`) commonly used on macOS', - type: 'group', - fields: [ - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the library.\n\nThis generally maps to the name of the file on disk.', - example: 'kernel32.dll', - default_field: false, - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Full file path of the library.', - example: 'C:\\Windows\\System32\\kernel32.dll', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'dns', - title: 'DNS', - group: 2, - description: - 'Fields describing DNS queries and answers.\n\nDNS events should either represent a single DNS query prior to getting answers\n(`dns.type:query`) or they should represent a full exchange and contain the\nquery details as well as all of the answers that were provided for this query\n(`dns.type:answer`).', - type: 'group', - fields: [ - { - name: 'answers', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'An array containing an object for each answer section returned\nby the server.\n\nThe main keys that should be present in these objects are defined by ECS.\nRecords that have more information may contain more keys than what ECS defines.\n\nNot all DNS data sources give all details about DNS answers. At minimum, answer\nobjects must contain the `data` key. If more information is available, map\nas much of it to ECS as possible, and add any additional fields to the answer\nobjects as custom fields.', - }, - { - name: 'answers.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of DNS data contained in this resource record.', - example: 'IN', - }, - { - name: 'answers.data', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The data describing the resource.\n\nThe meaning of this data depends on the type and class of the resource record.', - example: '10.10.10.10', - }, - { - name: 'answers.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The domain name to which this resource record pertains.\n\nIf a chain of CNAME is being resolved, each answer `name` should be the\none that corresponds with the answer `data`. It should not simply be the\noriginal `question.name` repeated.', - example: 'www.google.com', - }, - { - name: 'answers.ttl', - level: 'extended', - type: 'long', - description: - 'The time interval in seconds that this resource record may be cached\nbefore it should be discarded. Zero values mean that the data should not be\ncached.', - example: 180, - }, - { - name: 'answers.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of data contained in this resource record.', - example: 'CNAME', - }, - { - name: 'header_flags', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of 2 letter DNS header flags.\n\nExpected values are: AA, TC, RD, RA, AD, CD, DO.', - example: ['RD', 'RA'], - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS packet identifier assigned by the program that generated\nthe query. The identifier is copied to the response.', - example: 62111, - }, - { - name: 'op_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The DNS operation code that specifies the kind of query in the\nmessage. This value is set by the originator of a query and copied into the\nresponse.', - example: 'QUERY', - }, - { - name: 'question.class', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The class of records being queried.', - example: 'IN', - }, - { - name: 'question.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name being queried.\n\nIf the name field contains non-printable characters (below 32 or above 126),\nthose characters should be represented as escaped base 10 integers (\\DDD).\nBack slashes and quotes should be escaped. Tabs, carriage returns, and line\nfeeds should be converted to \\t, \\r, and \\n respectively.', - example: 'www.google.com', - }, - { - name: 'question.registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'question.subdomain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The subdomain is all of the labels under the registered_domain.\n\nIf the domain has multiple levels of subdomain, such as "sub2.sub1.example.com",\nthe subdomain field should contain "sub2.sub1", with no trailing period.', - example: 'www', - }, - { - name: 'question.top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'question.type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of record being queried.', - example: 'AAAA', - }, - { - name: 'resolved_ip', - level: 'extended', - type: 'ip', - description: - 'Array containing all IPs seen in `answers.data`.\n\nThe `answers` array can be difficult to use, because of the variety of data\nformats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip`\nmakes it possible to index them as IP addresses, and makes them easier to\nvisualize and query for.', - example: ['10.10.10.10', '10.10.10.11'], - }, - { - name: 'response_code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The DNS response code.', - example: 'NOERROR', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of DNS event captured, query or answer.\n\nIf your source of DNS events only gives you DNS queries, you should only create\ndns events of type `dns.type:query`.\n\nIf your source of DNS events gives you answers as well, you should create\none event per query (optionally as soon as the query is seen). And a second\nevent containing all query details as well as an array of answers.', - example: 'answer', - }, - ], - }, - { - name: 'ecs', - title: 'ECS', - group: 2, - description: 'Meta-information specific to ECS.', - type: 'group', - fields: [ - { - name: 'version', - level: 'core', - required: true, - type: 'keyword', - ignore_above: 1024, - description: - 'ECS version this event conforms to. `ecs.version` is a required\nfield and must exist in all events.\n\nWhen querying across multiple indices -- which may conform to slightly different\nECS versions -- this field lets integrations adjust to the schema version\nof the events.', - example: '1.0.0', - }, - ], - }, - { - name: 'error', - title: 'Error', - group: 2, - description: - 'These fields can represent errors of any kind.\n\nUse them for errors that happen while fetching events or in cases where the\nevent itself contains an error.', - type: 'group', - fields: [ - { - name: 'code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Error code describing the error.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the error.', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: 'Error message.', - }, - { - name: 'stack_trace', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The stack trace of this error in plain text.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The type of the error, for example the class name of the exception.', - example: 'java.lang.NullPointerException', - }, - ], - }, - { - name: 'event', - title: 'Event', - group: 2, - description: - 'The event fields are used for context information about the log\nor metric event itself.\n\nA log is defined as an event containing details of something that happened.\nLog events must include the time at which the thing happened. Examples of log\nevents include a process starting on a host, a network packet being sent from\na source to a destination, or a network connection between a client and a server\nbeing initiated or closed. A metric is defined as an event containing one or\nmore numerical measurements and the time at which the measurement was taken.\nExamples of metric events include memory pressure measured on a host and device\ntemperature. See the `event.kind` definition in this section for additional\ndetails about metric and state events.', - type: 'group', - fields: [ - { - name: 'action', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.', - example: 'user-password-change', - }, - { - name: 'category', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nsecond level in the ECS category hierarchy.\n\n`event.category` represents the "big buckets" of ECS categories. For example,\nfiltering on `event.category:process` yields all events relating to process\nactivity. This field is closely related to `event.type`, which is used as\na subcategory.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple categories.', - example: 'authentication', - }, - { - name: 'code', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Identification code for this event, if one exists.\n\nSome event sources use event codes to identify messages unambiguously, regardless\nof message language or wording adjustments over time. An example of this is\nthe Windows Event ID.', - example: 4648, - }, - { - name: 'created', - level: 'core', - type: 'date', - description: - 'event.created contains the date/time when the event was first\nread by an agent, or by your pipeline.\n\nThis field is distinct from @timestamp in that @timestamp typically contain\nthe time extracted from the original event.\n\nIn most situations, these two timestamps will be slightly different. The difference\ncan be used to calculate the delay between your source generating an event,\nand the time when your agent first processed it. This can be used to monitor\nyour agent or pipeline ability to keep up with your event source.\n\nIn case the two timestamps are identical, @timestamp should be used.', - example: '2016-05-23T08:05:34.857Z', - }, - { - name: 'dataset', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the dataset.\n\nIf an event source publishes more than one type of log or events (e.g. access\nlog, error log), the dataset is used to specify which one the event comes\nfrom.\n\nIt is recommended but not required to start the dataset name with the module\nname, followed by a dot, then the dataset name.', - example: 'apache.access', - }, - { - name: 'duration', - level: 'core', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - output_format: 'asMilliseconds', - output_precision: 1, - description: - 'Duration of the event in nanoseconds.\n\nIf event.start and event.end are known this value should be the difference\nbetween the end and start time.', - }, - { - name: 'end', - level: 'extended', - type: 'date', - description: - 'event.end contains the date when the event ended or when the activity\nwas last observed.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Hash (perhaps logstash fingerprint) of raw field to be able to\ndemonstrate log integrity.', - example: '123456789012345678901234567890ABCD', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique ID to describe the event.', - example: '8a4f500d', - }, - { - name: 'ingested', - level: 'core', - type: 'date', - description: - 'Timestamp when an event arrived in the central data store.\n\nThis is different from `@timestamp`, which is when the event originally occurred. It is\nalso different from `event.created`, which is meant to capture the first time\nan agent saw the event.\n\nIn normal conditions, assuming no tampering, the timestamps should chronologically\nlook like this: `@timestamp` < `event.created` < `event.ingested`.', - example: '2016-05-23T08:05:35.101Z', - default_field: false, - }, - { - name: 'kind', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nhighest level in the ECS category hierarchy.\n\n`event.kind` gives high-level information about what type of information the\nevent contains, without being specific to the contents of the event. For example,\nvalues of this field distinguish alert events from metric events.\n\nThe value of this field can be used to inform how these kinds of events should\nbe handled. They may warrant different retention, different access control,\nit may also help understand whether the data coming in at a regular interval\nor not.', - example: 'alert', - }, - { - name: 'module', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the module this data is coming from.\n\nIf your monitoring agent supports the concept of modules or plugins to process\nevents of a given source (e.g. Apache logs), `event.module` should contain\nthe name of this module.', - example: 'apache', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Raw text message of entire event. Used to demonstrate log integrity.\n\nThis field is not indexed and doc_values are disabled. It cannot be searched,\nbut it can be retrieved from `_source`.', - example: - 'Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100|\nworm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232', - }, - { - name: 'outcome', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nlowest level in the ECS category hierarchy.\n\n`event.outcome` simply denotes whether the event represents a success or a\nfailure from the perspective of the entity that produced the event.\n\nNote that when a single transaction is described in multiple events, each\nevent may populate different values of `event.outcome`, according to their\nperspective.\n\nAlso note that in the case of a compound event (a single event that contains\nmultiple logical events), this field should be populated with the value that\nbest captures the overall success or failure from the perspective of the event\nproducer.\n\nFurther note that not all events will have an associated outcome. For example,\nthis field is generally not populated for metric events, events with `event.type:info`,\nor any events for which an outcome does not make logical sense.', - example: 'success', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Source of the event.\n\nEvent transports such as Syslog or the Windows Event Log typically mention\nthe source of an event. It can be the name of the software that generated\nthe event (e.g. Sysmon, httpd), or of a subsystem of the operating system\n(kernel, Microsoft-Windows-Security-Auditing).', - example: 'kernel', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL linking to additional information about this event.\n\nThis URL links to a static definition of the this event. Alert events, indicated\nby `event.kind:alert`, are a common use case for this field.', - example: 'https://system.vendor.com/event/#0001234', - default_field: false, - }, - { - name: 'risk_score', - level: 'core', - type: 'float', - description: - "Risk score or priority of the event (e.g. security solutions).\nUse your system's original value here.", - }, - { - name: 'risk_score_norm', - level: 'extended', - type: 'float', - description: - 'Normalized risk score or priority of the event, on a scale of\n0 to 100.\n\nThis is mainly useful if you use more than one system that assigns risk scores,\nand you want to see a normalized value across all systems.', - }, - { - name: 'sequence', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Sequence number of the event.\n\nThe sequence number is a value published by some event sources, to make the\nexact ordering of events unambiguous, regardless of the timestamp precision.', - }, - { - name: 'severity', - level: 'core', - type: 'long', - format: 'string', - description: - 'The numeric severity of the event according to your event source.\n\nWhat the different severity values mean can be different between sources and\nuse cases. It is up to the implementer to make sure severities are consistent\nacross events from the same source.\n\nThe Syslog severity belongs in `log.syslog.severity.code`. `event.severity`\nis meant to represent the severity according to the event source (e.g. firewall,\nIDS). If the event source does not publish its own severity, you may optionally\ncopy the `log.syslog.severity.code` to `event.severity`.', - example: 7, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: - 'event.start contains the date when the event started or when the\nactivity was first observed.', - }, - { - name: 'timezone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'This field should be populated when the event timestamp does\nnot include timezone information already (e.g. default Syslog timestamps).\nIt is optional otherwise.\n\nAcceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"),\nabbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is one of four ECS Categorization Fields, and indicates the\nthird level in the ECS category hierarchy.\n\n`event.type` represents a categorization "sub-bucket" that, when used along\nwith the `event.category` field values, enables filtering events down to a\nlevel appropriate for single visualization.\n\nThis field is an array. This will allow proper categorization of some events\nthat fall in multiple event types.', - }, - { - name: 'url', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'URL linking to an external system to continue investigation of\nthis event.\n\nThis URL links to another system where in-depth investigation of the specific\noccurence of this event can take place. Alert events, indicated by `event.kind:alert`,\nare a common use case for this field.', - example: 'https://mysystem.mydomain.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe', - default_field: false, - }, - ], - }, - { - name: 'file', - title: 'File', - group: 2, - description: - 'A file is defined as a set of information that has been created\non, or has existed on a filesystem.\n\nFile objects can be associated with host events, network events, and/or file\nevents (e.g., those produced by File Integrity Monitoring [FIM] products or\nservices). File fields provide details about the affected file associated with\nthe event or metric.', - type: 'group', - fields: [ - { - name: 'accessed', - level: 'extended', - type: 'date', - description: - 'Last time the file was accessed.\n\nNote that not all filesystems keep track of access time.', - }, - { - name: 'attributes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of file attributes.\n\nAttributes names will vary by platform. Here is a non-exhaustive list of values\nthat are expected in this field: archive, compressed, directory, encrypted,\nexecute, hidden, read, readonly, system, write.', - example: '["readonly", "system"]', - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'created', - level: 'extended', - type: 'date', - description: - 'File creation time.\n\nNote that not all filesystems store the creation time.', - }, - { - name: 'ctime', - level: 'extended', - type: 'date', - description: - 'Last time the file attributes or metadata changed.\n\nNote that changes to the file content will update `mtime`. This implies `ctime`\nwill be adjusted at the same time, since `mtime` is an attribute of the file.', - }, - { - name: 'device', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Device that is the source of the file.', - example: 'sda', - }, - { - name: 'directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Directory where the file is located. It should include the drive\nletter, when appropriate.', - example: '/home/alice', - }, - { - name: 'drive_letter', - level: 'extended', - type: 'keyword', - ignore_above: 1, - description: - 'Drive letter where the file is located. This field is only relevant\non Windows.\n\nThe value should be uppercase, and not include the colon.', - example: 'C', - default_field: false, - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File extension.', - example: 'png', - }, - { - name: 'gid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group ID (GID) of the file.', - example: '1001', - }, - { - name: 'group', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Primary group name of the file.', - example: 'alice', - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'inode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Inode representing the file in the filesystem.', - example: '256383', - }, - { - name: 'mime_type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'MIME type should identify the format of the file or stream of bytes\nusing https://www.iana.org/assignments/media-types/media-types.xhtml[IANA\nofficial types], where possible. When more than one type is applicable, the\nmost specific type should be used.', - default_field: false, - }, - { - name: 'mode', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Mode of the file in octal representation.', - example: '0640', - }, - { - name: 'mtime', - level: 'extended', - type: 'date', - description: 'Last time the file content was modified.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the file including the extension, without the directory.', - example: 'example.png', - }, - { - name: 'owner', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: "File owner's username.", - example: 'alice', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Full path to the file, including the file name. It should include\nthe drive letter, when appropriate.', - example: '/home/alice/example.png', - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - description: 'File size in bytes.\n\nOnly relevant when `file.type` is "file".', - example: 16384, - }, - { - name: 'target_path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Target path for symlinks.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'File type (file, dir, or symlink).', - example: 'file', - }, - { - name: 'uid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The user ID (UID) or security identifier (SID) of the file owner.', - example: '1001', - }, - ], - }, - { - name: 'geo', - title: 'Geo', - group: 2, - description: - 'Geo fields can carry data about a specific location related to an\nevent.\n\nThis geolocation information can be derived from techniques such as Geo IP,\nor be user-supplied.', - type: 'group', - fields: [ - { - name: 'city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - ], - }, - { - name: 'group', - title: 'Group', - group: 2, - description: - 'The group fields are meant to represent groups that are relevant\nto the event.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - ], - }, - { - name: 'hash', - title: 'Hash', - group: 2, - description: - 'The hash fields represent different hash algorithms and their values.\n\nField names for common hashes (e.g. MD5, SHA1) are predefined. Add fields for\nother hashes by lowercasing the hash algorithm name and using underscore separators\nas appropriate (snake case, e.g. sha3_512).', - type: 'group', - fields: [ - { - name: 'md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - ], - }, - { - name: 'host', - title: 'Host', - group: 2, - description: - 'A host is defined as a general computing instance.\n\nECS host.* fields should be populated with details about the host on which the\nevent happened, or from which the measurement was taken. Host types include\nhardware, virtual machines, Docker containers, and Kubernetes nodes.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system architecture.', - example: 'x86_64', - }, - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the domain of which the host is a member.\n\nFor example, on Windows this could be the host Active Directory domain\nor NetBIOS domain name. For Linux this could be the domain of the host\nLDAP provider.', - example: 'CONTOSO', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Hostname of the host.\n\nIt normally contains what the `hostname` command returns on the host machine.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique host id.\n\nAs hostname is not always unique, use values that are meaningful in your environment.\n\nExample: The current usage of `beat.name`.', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'Host ip addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Host mac addresses.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of host.\n\nFor Cloud providers this can be the machine type like `t2.medium`. If vm,\nthis could be the container, for example, or other information meaningful\nin your environment.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the host has been up.', - example: 1325, - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'http', - title: 'HTTP', - group: 2, - description: - 'Fields related to HTTP activity. Use the `url` field set to store\nthe url of the request.', - type: 'group', - fields: [ - { - name: 'request.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the request body.', - example: 887, - }, - { - name: 'request.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP request body.', - example: 'Hello world', - }, - { - name: 'request.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the request (body and headers).', - example: 1437, - }, - { - name: 'request.method', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'HTTP request method.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'get, post, put', - }, - { - name: 'request.referrer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Referrer for this HTTP request.', - example: 'https://blog.example.com/', - }, - { - name: 'response.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the response body.', - example: 887, - }, - { - name: 'response.body.content', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The full HTTP response body.', - example: 'Hello world', - }, - { - name: 'response.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the response (body and headers).', - example: 1437, - }, - { - name: 'response.status_code', - level: 'extended', - type: 'long', - format: 'string', - description: 'HTTP response status code.', - example: 404, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'HTTP version.', - example: 1.1, - }, - ], - }, - { - name: 'interface', - title: 'Interface', - group: 2, - description: - 'The interface fields are used to record ingress and egress interface\ninformation when reported by an observer (e.g. firewall, router, load balancer)\nin the context of the observer handling a network connection. In the case of\na single observer interface (e.g. network sensor on a span port) only the observer.ingress\ninformation should be populated.', - type: 'group', - fields: [ - { - name: 'alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - ], - }, - { - name: 'log', - title: 'Log', - group: 2, - description: - 'Details about the event logging mechanism or logging transport.\n\nThe log.* fields are typically populated with details about the logging mechanism\nused to create and/or transport the event. For example, syslog details belong\nunder `log.syslog.*`.\n\nThe details specific to your event source are typically not logged under `log.*`,\nbut rather in `event.*` or in other ECS fields.', - type: 'group', - fields: [ - { - name: 'level', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Original log level of the log event.\n\nIf the source of the event provides a log level or textual severity, this\nis the one that goes in `log.level`. If your source does not specify one,\nyou may put your event transport severity here (e.g. Syslog severity).\n\nSome examples are `warn`, `err`, `i`, `informational`.', - example: 'error', - }, - { - name: 'logger', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the logger inside an application. This is usually the\nname of the class which initialized the logger, or can be a custom name.', - example: 'org.elasticsearch.bootstrap.Bootstrap', - }, - { - name: 'origin.file.line', - level: 'extended', - type: 'integer', - description: - 'The line number of the file containing the source code which originated\nthe log event.', - example: 42, - }, - { - name: 'origin.file.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The name of the file containing the source code which originated\nthe log event. Note that this is not the name of the log file.', - example: 'Bootstrap.java', - }, - { - name: 'origin.function', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the function or method which originated the log event.', - example: 'init', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'This is the original log message and contains the full log message\nbefore splitting it up in multiple parts.\n\nIn contrast to the `message` field which can contain an extracted part of\nthe log message, this field contains the original, full log message. It can\nhave already some modifications applied like encoding or new lines removed\nto clean up the log message.\n\nThis field is not indexed and doc_values are disabled so it can not be queried\nbut the value can be retrieved from `_source`.', - example: 'Sep 19 08:26:10 localhost My log', - }, - { - name: 'syslog', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'The Syslog metadata of the event, if the event was transmitted\nvia Syslog. Please see RFCs 5424 or 3164.', - }, - { - name: 'syslog.facility.code', - level: 'extended', - type: 'long', - format: 'string', - description: - 'The Syslog numeric facility of the log event, if available.\n\nAccording to RFCs 5424 and 3164, this value should be an integer between 0\nand 23.', - example: 23, - }, - { - name: 'syslog.facility.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The Syslog text-based facility of the log event, if available.', - example: 'local7', - }, - { - name: 'syslog.priority', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Syslog numeric priority of the event, if available.\n\nAccording to RFCs 5424 and 3164, the priority is 8 * facility + severity.\nThis number is therefore expected to contain a value between 0 and 191.', - example: 135, - }, - { - name: 'syslog.severity.code', - level: 'extended', - type: 'long', - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different numeric severity\nvalue (e.g. firewall, IDS), your source numeric severity should go to `event.severity`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `event.severity`.', - example: 3, - }, - { - name: 'syslog.severity.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The Syslog numeric severity of the log event, if available.\n\nIf the event source publishing via Syslog provides a different severity value\n(e.g. firewall, IDS), your source text severity should go to `log.level`.\nIf the event source does not specify a distinct severity, you can optionally\ncopy the Syslog severity to `log.level`.', - example: 'Error', - }, - ], - }, - { - name: 'network', - title: 'Network', - group: 2, - description: - 'The network is defined as the communication path over which a host\nor network event happens.\n\nThe network.* fields should be populated with details about the network activity\nassociated with an event.', - type: 'group', - fields: [ - { - name: 'application', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A name given to an application level protocol. This can be arbitrarily\nassigned for things like microservices, but also apply to things like skype,\nicq, facebook, twitter. This would be used in situations where the vendor\nor service can be decoded such as from the source/dest IP owners, ports, or\nwire format.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'aim', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: - 'Total bytes transferred in both directions.\n\nIf `source.bytes` and `destination.bytes` are known, `network.bytes` is their\nsum.', - example: 368, - }, - { - name: 'community_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash of source and destination IPs and ports, as well as the\nprotocol used in a communication. This is a tool-agnostic standard to identify\nflows.\n\nLearn more at https://github.com/corelight/community-id-spec.', - example: '1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=', - }, - { - name: 'direction', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - "Direction of the network traffic.\nRecommended values are:\n * inbound\n * outbound\n * internal\n * external\n * unknown\n\nWhen mapping events from a host-based monitoring context, populate this field from the host's point of view.\nWhen mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of your network perimeter.", - example: 'inbound', - }, - { - name: 'forwarded_ip', - level: 'core', - type: 'ip', - description: 'Host IP address when the source IP address is the proxy.', - example: '192.1.1.2', - }, - { - name: 'iana_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).\nStandardized list of protocols. This aligns well with NetFlow and sFlow related\nlogs which use the IANA Protocol Number.', - example: 6, - }, - { - name: 'inner', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Network.inner fields are added in addition to network.vlan fields\nto describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed\nfields include vlan.id and vlan.name. Inner vlan fields are typically used\nwhen sending traffic with multiple 802.1q encapsulations to a network sensor\n(e.g. Zeek, Wireshark.)', - default_field: false, - }, - { - name: 'inner.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'inner.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name given by operators to sections of their network.', - example: 'Guest Wifi', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: - 'Total packets transferred in both directions.\n\nIf `source.packets` and `destination.packets` are known, `network.packets`\nis their sum.', - example: 24, - }, - { - name: 'protocol', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'L7 Network protocol name. ex. http, lumberjack, transport protocol.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'http', - }, - { - name: 'transport', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Same as network.iana_number, but instead using the Keyword name\nof the transport layer (udp, tcp, ipv6-icmp, etc.)\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'tcp', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'In the OSI Model this would be the Network Layer. ipv4, ipv6,\nipsec, pim, etc\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'ipv4', - }, - { - name: 'vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'observer', - title: 'Observer', - group: 2, - description: - 'An observer is defined as a special network, security, or application\ndevice used to detect, observe, or create network, security, or application-related\nevents and metrics.\n\nThis could be a custom hardware appliance or a server that has been configured\nto run special network, security, or application software. Examples include\nfirewalls, web proxies, intrusion detection/prevention systems, network monitoring\nsensors, web application firewalls, data loss prevention systems, and APM servers.\nThe observer.* fields shall be populated with details of the system, if any,\nthat detects, observes and/or creates a network, security, or application event\nor metric. Message queues and ETL components used in processing events or metrics\nare not considered observers in ECS.', - type: 'group', - fields: [ - { - name: 'egress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.egress holds information like interface number and name,\nvlan, and zone information to classify egress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'egress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'egress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'egress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'egress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'egress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of outbound traffic as reported by the observer to\ncategorize the destination area of egress traffic, e.g. Internal, External,\nDMZ, HR, Legal, etc.', - example: 'Public_Internet', - default_field: false, - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hostname of the observer.', - }, - { - name: 'ingress', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: - 'Observer.ingress holds information like interface number and name,\nvlan, and zone information to classify ingress traffic. Single armed monitoring\nsuch as a network sensor on a span port should only use observer.ingress\nto categorize traffic.', - default_field: false, - }, - { - name: 'ingress.interface.alias', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Interface alias as reported by the system, typically used in firewall\nimplementations for e.g. inside, outside, or dmz logical interface naming.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.interface.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface ID as reported by an observer (typically SNMP interface\nID).', - example: 10, - default_field: false, - }, - { - name: 'ingress.interface.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Interface name as reported by the system.', - example: 'eth0', - default_field: false, - }, - { - name: 'ingress.vlan.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'ingress.vlan.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - { - name: 'ingress.zone', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Network zone of incoming traffic as reported by the observer to\ncategorize the source area of ingress traffic. e.g. internal, External, DMZ,\nHR, Legal, etc.', - example: 'DMZ', - default_field: false, - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP addresses of the observer.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC addresses of the observer', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Custom name of the observer.\n\nThis is a name that can be given to an observer. This can be helpful for example\nif multiple firewalls of the same model are used in an organization.\n\nIf no custom name is needed, the field can be left empty.', - example: '1_proxySG', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The product name of the observer.', - example: 's200', - }, - { - name: 'serial_number', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Observer serial number.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the observer the data is coming from.\n\nThere is no predefined list of observer types. Some examples are `forwarder`,\n`firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.', - example: 'firewall', - }, - { - name: 'vendor', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Vendor name of the observer.', - example: 'Symantec', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Observer version.', - }, - ], - }, - { - name: 'organization', - title: 'Organization', - group: 2, - description: - 'The organization fields enrich data with information about the company\nor entity the data is associated with.\n\nThese fields help you arrange or filter data stored in an index by one or multiple\norganizations.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the organization.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - }, - ], - }, - { - name: 'os', - title: 'Operating System', - group: 2, - description: 'The OS fields contain information about the operating system.', - type: 'group', - fields: [ - { - name: 'family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - ], - }, - { - name: 'package', - title: 'Package', - group: 2, - description: - 'These fields contain information about an installed software package.\nIt contains general information about a package, such as name, version or size.\nIt also contains installation details, such as time or location.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package architecture.', - example: 'x86_64', - }, - { - name: 'build_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the build version of the installed\npackage.\n\nFor example use the commit SHA of a non-released package.', - example: '36f4f7e89dd61b0988b12ee000b98966867710cd', - default_field: false, - }, - { - name: 'checksum', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Checksum of the installed package for verification.', - example: '68b329da9893e34099c7d8ad5cb9c940', - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Description of the package.', - example: - 'Open source programming language to build simple/reliable/efficient\nsoftware.', - }, - { - name: 'install_scope', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Indicating how the package was installed, e.g. user-local, global.', - example: 'global', - }, - { - name: 'installed', - level: 'extended', - type: 'date', - description: 'Time when package was installed.', - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'License under which the package was released.\n\nUse a short name, e.g. the license identifier from SPDX License List where\npossible (https://spdx.org/licenses/).', - example: 'Apache License 2.0', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package name', - example: 'go', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path where the package is installed.', - example: '/usr/local/Cellar/go/1.12.9/', - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Home page or reference URL of the software in this package, if\navailable.', - example: 'https://golang.org', - default_field: false, - }, - { - name: 'size', - level: 'extended', - type: 'long', - format: 'string', - description: 'Package size in bytes.', - example: 62231, - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Type of package.\n\nThis should contain the package file type, rather than the package manager\nname. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar.', - example: 'rpm', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Package version', - example: '1.12.9', - }, - ], - }, - { - name: 'pe', - title: 'PE Header', - group: 2, - description: 'These fields contain Windows Portable Executable (PE) metadata.', - type: 'group', - fields: [ - { - name: 'company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - ], - }, - { - name: 'process', - title: 'Process', - group: 2, - description: - 'These fields contain information about a process.\n\nThese fields can help you correlate metrics information with a process id/name\nfrom a log message. The `process.pid` often stays in the metric itself and\nis copied to the global field for correlation.', - type: 'group', - fields: [ - { - name: 'args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.', - example: ['/usr/bin/ssh', '-l', 'user', '10.0.0.16'], - }, - { - name: 'args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - }, - { - name: 'exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - }, - { - name: 'hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - }, - { - name: 'hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - }, - { - name: 'hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - }, - { - name: 'parent.args', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of process arguments.\n\nMay be filtered to protect sensitive information.', - example: ['ssh', '-l', 'user', '10.0.0.16'], - default_field: false, - }, - { - name: 'parent.args_count', - level: 'extended', - type: 'long', - description: - 'Length of the process.args array.\n\nThis field can be useful for querying or performing bucket analysis on how\nmany arguments were provided to start a process. More arguments may be an\nindication of suspicious activity.', - example: 4, - default_field: false, - }, - { - name: 'parent.code_signature.exists', - level: 'core', - type: 'boolean', - description: 'Boolean to capture if a signature is present.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.status', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Additional information about the certificate status.\n\nThis is useful for logging cryptographic errors with the certificate validity\nor trust status. Leave unpopulated if the validity or trust of the certificate\nwas unchecked.', - example: 'ERROR_UNTRUSTED_ROOT', - default_field: false, - }, - { - name: 'parent.code_signature.subject_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Subject name of the code signer', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'parent.code_signature.trusted', - level: 'extended', - type: 'boolean', - description: - 'Stores the trust status of the certificate chain.\n\nValidating the trust of the certificate chain may be complicated, and this\nfield should only be populated by tools that actively check the status.', - example: 'true', - default_field: false, - }, - { - name: 'parent.code_signature.valid', - level: 'extended', - type: 'boolean', - description: - 'Boolean to capture if the digital signature is verified against\nthe binary content.\n\nLeave unpopulated if a certificate was unchecked.', - example: 'true', - default_field: false, - }, - { - name: 'parent.command_line', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Full command line that started the process, including the absolute\npath to the executable, and all arguments.\n\nSome arguments may be filtered to protect sensitive information.', - example: '/usr/bin/ssh -l user 10.0.0.16', - default_field: false, - }, - { - name: 'parent.entity_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier for the process.\n\nThe implementation of this is specified by the data source, but some examples\nof what could be used here are a process-generated UUID, Sysmon Process GUIDs,\nor a hash of some uniquely identifying components of a process.\n\nConstructing a globally unique identifier is a common practice to mitigate\nPID reuse as well as to identify a specific process over time, across multiple\nmonitored hosts.', - example: 'c2c455d9f99375d', - default_field: false, - }, - { - name: 'parent.executable', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - default_field: false, - }, - { - name: 'parent.exit_code', - level: 'extended', - type: 'long', - description: - 'The exit code of the process, if this is a termination event.\n\nThe field should be absent if there is no exit code for the event (e.g. process\nstart).', - example: 137, - default_field: false, - }, - { - name: 'parent.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'MD5 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA1 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA256 hash.', - default_field: false, - }, - { - name: 'parent.hash.sha512', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'SHA512 hash.', - default_field: false, - }, - { - name: 'parent.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - default_field: false, - }, - { - name: 'parent.pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - default_field: false, - }, - { - name: 'parent.pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - default_field: false, - }, - { - name: 'parent.ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - default_field: false, - }, - { - name: 'parent.start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - default_field: false, - }, - { - name: 'parent.thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - default_field: false, - }, - { - name: 'parent.thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - default_field: false, - }, - { - name: 'parent.title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - default_field: false, - }, - { - name: 'parent.uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - default_field: false, - }, - { - name: 'parent.working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - default_field: false, - }, - { - name: 'pe.company', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal company name of the file, provided at compile-time.', - example: 'Microsoft Corporation', - default_field: false, - }, - { - name: 'pe.description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal description of the file, provided at compile-time.', - example: 'Paint', - default_field: false, - }, - { - name: 'pe.file_version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal version of the file, provided at compile-time.', - example: '6.3.9600.17415', - default_field: false, - }, - { - name: 'pe.original_file_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal name of the file, provided at compile-time.', - example: 'MSPAINT.EXE', - default_field: false, - }, - { - name: 'pe.product', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Internal product name of the file, provided at compile-time.', - example: 'Microsoft® Windows® Operating System', - default_field: false, - }, - { - name: 'pgid', - level: 'extended', - type: 'long', - format: 'string', - description: 'Identifier of the group of processes the process belongs to.', - }, - { - name: 'pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - }, - { - name: 'ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - }, - { - name: 'thread.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Thread name.', - example: 'thread-0', - }, - { - name: 'title', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - }, - { - name: 'uptime', - level: 'extended', - type: 'long', - description: 'Seconds the process has been up.', - example: 1325, - }, - { - name: 'working_directory', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'The working directory of the process.', - example: '/home/alice', - }, - ], - }, - { - name: 'registry', - title: 'Registry', - group: 2, - description: 'Fields related to Windows Registry operations.', - type: 'group', - fields: [ - { - name: 'data.bytes', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Original bytes written with base64 encoding.\n\nFor Windows registry operations, such as SetValueEx and RegQueryValueEx, this\ncorresponds to the data pointed by `lp_data`. This is optional but provides\nbetter recoverability and should be populated for REG_BINARY encoded values.', - example: 'ZQBuAC0AVQBTAAAAZQBuAAAAAAA=', - default_field: false, - }, - { - name: 'data.strings', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Content when writing string types.\n\nPopulated as an array when writing string data to the registry. For single\nstring registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with\none string. For sequences of string with REG_MULTI_SZ, this array will be\nvariable length. For numeric data, such as REG_DWORD and REG_QWORD, this should\nbe populated with the decimal representation (e.g `"1"`).', - example: '["C:\\rta\\red_ttp\\bin\\myapp.exe"]', - default_field: false, - }, - { - name: 'data.type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Standard registry type for encoding contents', - example: 'REG_SZ', - default_field: false, - }, - { - name: 'hive', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Abbreviated name for the hive.', - example: 'HKLM', - default_field: false, - }, - { - name: 'key', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Hive-relative path of keys.', - example: - 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe', - default_field: false, - }, - { - name: 'path', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Full path, including hive, key and value', - example: - 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution\nOptions\\winword.exe\\Debugger', - default_field: false, - }, - { - name: 'value', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the value written.', - example: 'Debugger', - default_field: false, - }, - ], - }, - { - name: 'related', - title: 'Related', - group: 2, - description: - 'This field set is meant to facilitate pivoting around a piece of\ndata.\n\nSome pieces of information can be seen in many places in an ECS event. To facilitate\nsearching for them, store an array of all seen values to their corresponding\nfield in `related.`.\n\nA concrete example is IP addresses, which can be under host, observer, source,\ndestination, client, server, and network.forwarded_ip. If you append all IPs\nto `related.ip`, you can then search for a given IP trivially, no matter where\nit appeared, by querying `related.ip:192.0.2.15`.', - type: 'group', - fields: [ - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - "All the hashes seen on your event. Populating this field, then\nusing it to search for hashes can help in situations where you're unsure what\nthe hash algorithm is (and therefore which key name to search).", - default_field: false, - }, - { - name: 'ip', - level: 'extended', - type: 'ip', - description: 'All of the IPs seen on your event.', - }, - { - name: 'user', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'All the user names seen on your event.', - default_field: false, - }, - ], - }, - { - name: 'rule', - title: 'Rule', - group: 2, - description: - 'Rule fields are used to capture the specifics of any observer or\nagent rules that generate alerts or other notable events.\n\nExamples of data sources that would populate the rule fields include: network\nadmission control platforms, network or host IDS/IPS, network firewalls, web\napplication firewalls, url filters, endpoint detection and response (EDR) systems,\netc.', - type: 'group', - fields: [ - { - name: 'author', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name, organization, or pseudonym of the author or authors who created\nthe rule used to generate this event.', - example: ['Star-Lord'], - default_field: false, - }, - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A categorization value keyword used by the entity using the rule\nfor detection of this event.', - example: 'Attempted Information Leak', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The description of the rule generating the event.', - example: 'Block requests to public DNS over HTTPS / TLS protocols', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of an agent, observer,\nor other entity using the rule for detection of this event.', - example: 101, - default_field: false, - }, - { - name: 'license', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the license under which the rule used to generate this\nevent is made available.', - example: 'Apache 2.0', - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the rule or signature generating the event.', - example: 'BLOCK_DNS_over_TLS', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Reference URL to additional information about the rule used to\ngenerate this event.\n\nThe URL can point to the vendor documentation about the rule. If that is\nnot available, it can also be a link to a more general page describing this\ntype of alert.', - example: 'https://en.wikipedia.org/wiki/DNS_over_TLS', - default_field: false, - }, - { - name: 'ruleset', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the ruleset, policy, group, or parent category in which\nthe rule used to generate this event is a member.', - example: 'Standard_Protocol_Filters', - default_field: false, - }, - { - name: 'uuid', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A rule ID that is unique within the scope of a set or group of\nagents, observers, or other entities using the rule for detection of this\nevent.', - example: 1100110011, - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The version / revision of the rule being used for analysis.', - example: 1.1, - default_field: false, - }, - ], - }, - { - name: 'server', - title: 'Server', - group: 2, - description: - 'A Server is defined as the responder in a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the server is the receiver of the initial SYN packet(s) of the\nTCP connection. For other protocols, the server is generally the responder in\nthe network transaction. Some systems actually use the term "responder" to refer\nthe server in TCP connections. The server fields describe details about the\nsystem acting as the server in the network event. Server fields are usually\npopulated in conjunction with client fields. Server fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event server addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the server to the client.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Server domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the server.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the server.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of destination based NAT sessions (e.g. internet\nto private DMZ)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the server to the client.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the server.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered server domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'service', - title: 'Service', - group: 2, - description: - 'The service fields describe the service for or from which the data\nwas collected.\n\nThese fields help you find and correlate logs for a specific service and version.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Ephemeral identifier of this service (if one exists).\n\nThis id normally changes across restarts, but `service.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the running service. If the service is comprised\nof many nodes, the `service.id` should be the same for all nodes.\n\nThis id should uniquely identify the service. This makes it possible to correlate\nlogs and metrics for one specific service, no matter which particular node\nemitted the event.\n\nNote that if you need to see the events from one specific host of the service,\nyou should filter on that `host.name` or `host.id` instead.', - example: 'd37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the service data is collected from.\n\nThe name of the service is normally user given. This allows for distributed\nservices that run on multiple hosts to correlate the related instances based\non the name.\n\nIn the case of Elasticsearch the `service.name` could contain the cluster\nname. For Beats the `service.name` is by default a copy of the `service.type`\nfield if no name is specified.', - example: 'elasticsearch-metrics', - }, - { - name: 'node.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of a service node.\n\nThis allows for two nodes of the same service running on the same host to\nbe differentiated. Therefore, `service.node.name` should typically be unique\nacross nodes of a given service.\n\nIn the case of Elasticsearch, the `service.node.name` could contain the unique\nnode name within the Elasticsearch cluster. In cases where the service doe not\nhave the concept of a node name, the host name or container name can be used\nto distinguish running instances that make up this service. If those do not\nprovide uniqueness (e.g. multiple instances of the service running on the\nsame host) - the node name can be manually set.', - example: 'instance-0000000016', - }, - { - name: 'state', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Current state of the service.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of the service data is collected from.\n\nThe type can be used to group and correlate logs and metrics from one service\ntype.\n\nExample: If logs or metrics are collected from Elasticsearch, `service.type`\nwould be `elasticsearch`.', - example: 'elasticsearch', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: - 'Version of the service the data was collected from.\n\nThis allows to look at a data set only for a specific version of a service.', - example: '3.2.4', - }, - ], - }, - { - name: 'source', - title: 'Source', - group: 2, - description: - 'Source fields describe details about the source of a packet/event.\n\nSource fields are usually populated in conjunction with destination fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Some event source addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'as.number', - level: 'extended', - type: 'long', - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - }, - { - name: 'as.organization.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Organization name.', - example: 'Google LLC', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the source to the destination.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Source domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the source.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'MAC address of the source.', - }, - { - name: 'nat.ip', - level: 'extended', - type: 'ip', - description: - 'Translated ip of source based NAT sessions (e.g. internal client\nto internet)\n\nTypically connections traversing load balancers, firewalls, or routers.', - }, - { - name: 'nat.port', - level: 'extended', - type: 'long', - format: 'string', - description: - 'Translated port of source based NAT sessions. (e.g. internal client\nto internet)\n\nTypically used with load balancers, firewalls, or routers.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the source to the destination.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the source.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered source domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'user.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'threat', - title: 'Threat', - group: 2, - description: - 'Fields to classify events and alerts according to a threat taxonomy\nsuch as the Mitre ATT&CK framework.\n\nThese fields are for users to classify alerts from all of their sources (e.g.\nIDS, NGFW, etc.) within a common taxonomy. The threat.tactic.* are meant to\ncapture the high level category of the threat (e.g. "impact"). The threat.technique.*\nfields are meant to capture which kind of approach is used by this detected\nthreat, to accomplish the goal (e.g. "endpoint denial of service").', - type: 'group', - fields: [ - { - name: 'framework', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the threat framework used to further categorize and classify\nthe tactic and technique of the reported threat. Framework classification\ncan be provided by detecting systems, evaluated at ingest time, or retrospectively\ntagged to events.', - example: 'MITRE ATT&CK', - }, - { - name: 'tactic.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of tactic used by this threat. You can use the Mitre ATT&CK\nMatrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'TA0040', - }, - { - name: 'tactic.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the type of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'impact', - }, - { - name: 'tactic.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of tactic used by this threat. You can use the\nMitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/\n)', - example: 'https://attack.mitre.org/tactics/TA0040/', - }, - { - name: 'technique.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The id of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'T1499', - }, - { - name: 'technique.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'The name of technique used by this tactic. You can use the Mitre\nATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'endpoint denial of service', - }, - { - name: 'technique.reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The reference url of technique used by this tactic. You can use\nthe Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/\n)', - example: 'https://attack.mitre.org/techniques/T1499/', - }, - ], - }, - { - name: 'tls', - title: 'TLS', - group: 2, - description: - 'Fields related to a TLS connection. These fields focus on the TLS\nprotocol itself and intentionally avoids in-depth analysis of the related x.509\ncertificate files.', - type: 'group', - fields: [ - { - name: 'cipher', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the cipher used during the current connection.', - example: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', - default_field: false, - }, - { - name: 'client.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the client. This\nis usually mutually-exclusive of `client.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'client.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the client. This is usually mutually-exclusive of `client.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'client.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'client.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the client. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'client.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the client. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'client.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the issuer of the x.509 certificate\npresented by the client.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.ja3', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies clients based on how they perform an SSL/TLS\nhandshake.', - example: 'd4e5b18d6b55c71272893221c96ba240', - default_field: false, - }, - { - name: 'client.not_after', - level: 'extended', - type: 'date', - description: - 'Date/Time indicating when client certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.not_before', - level: 'extended', - type: 'date', - description: 'Date/Time indicating when client certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'client.server_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Also called an SNI, this tells the server which hostname to which\nthe client is attempting to connect. When this value is available, it should\nget copied to `destination.domain`.', - example: 'www.elastic.co', - default_field: false, - }, - { - name: 'client.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Distinguished name of subject of the x.509 certificate presented\nby the client.', - example: 'CN=myclient, OU=Documentation Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'client.supported_ciphers', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Array of ciphers offered by the client during the client hello.', - example: [ - 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', - 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', - '...', - ], - default_field: false, - }, - { - name: 'curve', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'String indicating the curve used for the given cipher, when applicable.', - example: 'secp256r1', - default_field: false, - }, - { - name: 'established', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if the TLS negotiation was successful and\ntransitioned to an encrypted tunnel.', - default_field: false, - }, - { - name: 'next_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'String indicating the protocol being tunneled. Per the values in\nthe IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids),\nthis string should be lower case.', - example: 'http/1.1', - default_field: false, - }, - { - name: 'resumed', - level: 'extended', - type: 'boolean', - description: - 'Boolean flag indicating if this TLS connection was resumed from\nan existing TLS negotiation.', - default_field: false, - }, - { - name: 'server.certificate', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'PEM-encoded stand-alone certificate offered by the server. This\nis usually mutually-exclusive of `server.certificate_chain` since this value\nalso exists in that list.', - example: 'MII...', - default_field: false, - }, - { - name: 'server.certificate_chain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Array of PEM-encoded certificates that make up the certificate\nchain offered by the server. This is usually mutually-exclusive of `server.certificate`\nsince that value should be the first certificate in the chain.', - example: ['MII...', 'MII...'], - default_field: false, - }, - { - name: 'server.hash.md5', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the MD5 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', - default_field: false, - }, - { - name: 'server.hash.sha1', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA1 digest of DER-encoded version\nof certificate offered by the server. For consistency with other hash values,\nthis value should be formatted as an uppercase hash.', - example: '9E393D93138888D288266C2D915214D1D1CCEB2A', - default_field: false, - }, - { - name: 'server.hash.sha256', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Certificate fingerprint using the SHA256 digest of DER-encoded\nversion of certificate offered by the server. For consistency with other hash\nvalues, this value should be formatted as an uppercase hash.', - example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', - default_field: false, - }, - { - name: 'server.issuer', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the issuer of the x.509 certificate presented by the\nserver.', - example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'server.ja3s', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A hash that identifies servers based on how they perform an SSL/TLS\nhandshake.', - example: '394441ab65754e2207b1e1b457b3641d', - default_field: false, - }, - { - name: 'server.not_after', - level: 'extended', - type: 'date', - description: - 'Timestamp indicating when server certificate is no longer considered\nvalid.', - example: '2021-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.not_before', - level: 'extended', - type: 'date', - description: 'Timestamp indicating when server certificate is first considered\nvalid.', - example: '1970-01-01T00:00:00.000Z', - default_field: false, - }, - { - name: 'server.subject', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Subject of the x.509 certificate presented by the server.', - example: 'CN=www.mydomain.com, OU=Infrastructure Team, DC=mydomain, DC=com', - default_field: false, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Numeric part of the version parsed from the original string.', - example: '1.2', - default_field: false, - }, - { - name: 'version_protocol', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Normalized lowercase protocol name parsed from original string.', - example: 'tls', - default_field: false, - }, - ], - }, - { - name: 'tracing', - title: 'Tracing', - group: 2, - description: - 'Distributed tracing makes it possible to analyze performance throughout\na microservice architecture all in one view. This is accomplished by tracing\nall of the requests - from the initial web request in the front-end service\n- to queries made through multiple back-end services.', - type: 'group', - fields: [ - { - name: 'trace.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the trace.\n\nA trace groups multiple events like transactions that belong together. For\nexample, a user request handled by multiple inter-connected services.', - example: '4bf92f3577b34da6a3ce929d0e0e4736', - }, - { - name: 'transaction.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique identifier of the transaction.\n\nA transaction is the highest level of work measured within a service, such\nas a request to a server.', - example: '00f067aa0ba902b7', - }, - ], - }, - { - name: 'url', - title: 'URL', - group: 2, - description: - 'URL fields provide support for complete or partial URLs, and supports\nthe breaking down into scheme, domain, path, and so on.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Domain of the url, such as "www.elastic.co".\n\nIn some cases a URL may refer to an IP and/or port directly, without a domain\nname. In this case, the IP address would go to the `domain` field.', - example: 'www.elastic.co', - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The field contains the file extension from the original request\nurl.\n\nThe file extension is only set if it exists, as not every url has a file extension.\n\nThe leading period must not be included. For example, the value must be "png",\nnot ".png".', - example: 'png', - }, - { - name: 'fragment', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Portion of the url after the `#`, such as "top".\n\nThe `#` is not part of the fragment.', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'If full URLs are important to your use case, they should be stored\nin `url.full`, whether this field is reconstructed or present in the event\nsource.', - example: 'https://www.elastic.co:443/search?q=elasticsearch#top', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: - 'Unmodified original url as seen in the event source.\n\nNote that in network monitoring, the observed URL may be a full URL, whereas\nin access logs, the URL is often just represented as a path.\n\nThis field is meant to represent the URL as it was observed, complete or not.', - example: - 'https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch', - }, - { - name: 'password', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Password of the request.', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Path of the request, such as "/search".', - }, - { - name: 'port', - level: 'extended', - type: 'long', - format: 'string', - description: 'Port of the request, such as 443.', - example: 443, - }, - { - name: 'query', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The query field describes the query string of the request, such\nas "q=elasticsearch".\n\nThe `?` is excluded from the query string. If a URL contains no `?`, there\nis no query field. If there is a `?` but no query, the query field exists\nwith an empty string. The `exists` query can be used to differentiate between\nthe two cases.', - }, - { - name: 'registered_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The highest registered url domain, stripped of the subdomain.\n\nFor example, the registered domain for "foo.google.com" is "google.com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last two labels will not work well for TLDs such as "co.uk".', - example: 'google.com', - }, - { - name: 'scheme', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Scheme of the request, such as "https".\n\nNote: The `:` is not part of the scheme.', - example: 'https', - }, - { - name: 'top_level_domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The effective top level domain (eTLD), also known as the domain\nsuffix, is the last part of the domain name. For example, the top level domain\nfor google.com is "com".\n\nThis value can be determined precisely with a list like the public suffix\nlist (http://publicsuffix.org). Trying to approximate this by simply taking\nthe last label will not work well for effective TLDs such as "co.uk".', - example: 'co.uk', - }, - { - name: 'username', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Username of the request.', - }, - ], - }, - { - name: 'user', - title: 'User', - group: 2, - description: - 'The user fields describe information about the user that is relevant\nto the event.\n\nFields can have one entry or multiple entries. If a user has more than one id,\nprovide an array that includes all of them.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the user is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'email', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'User email address.', - }, - { - name: 'full_name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'group.domain', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Name of the directory the group is a member of.\n\nFor example, an LDAP or Active Directory domain name.', - }, - { - name: 'group.id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'group.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the group.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - ignore_above: 1024, - description: 'Unique identifiers of the user.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'user_agent', - title: 'User agent', - group: 2, - description: - 'The user_agent fields normally come from a browser request.\n\nThey often show up in web service logs coming from the parsed user agent string.', - type: 'group', - fields: [ - { - name: 'device.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the device.', - example: 'iPhone', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Name of the user agent.', - example: 'Safari', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: 'Unparsed user_agent string.', - example: - 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15\n(KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - default_field: false, - }, - ], - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Version of the user agent.', - example: 12, - }, - ], - }, - { - name: 'vlan', - title: 'VLAN', - group: 2, - description: - 'The VLAN fields are used to identify 802.1q tag(s) of a packet,\nas well as ingress and egress VLAN associations of an observer in relation to\na specific packet or connection.\n\nNetwork.vlan fields are used to record a single VLAN tag, or the outer tag in\nthe case of q-in-q encapsulations, for a packet or connection as observed, typically\nprovided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic.\n\nNetwork.inner VLAN fields are used to report inner q-in-q 802.1q tags (multiple\n802.1q encapsulations) as observed, typically provided by a network sensor (e.g.\nZeek, Wireshark) passively reporting on traffic. Network.inner VLAN fields should\nonly be used in addition to network.vlan fields to indicate q-in-q tagging.\n\nObserver.ingress and observer.egress VLAN values are used to record observer\nspecific information when observer events contain discrete ingress and egress\nVLAN information, typically provided by firewalls, routers, or load balancers.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'VLAN ID as reported by the observer.', - example: 10, - default_field: false, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'Optional VLAN name as reported by the observer.', - example: 'outside', - default_field: false, - }, - ], - }, - { - name: 'vulnerability', - title: 'Vulnerability', - group: 2, - description: - 'The vulnerability fields describe information about a vulnerability\nthat is relevant to an event.', - type: 'group', - fields: [ - { - name: 'category', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of system or architecture that the vulnerability affects.\nThese may be platform-specific (for example, Debian or SUSE) or general (for\nexample, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys\nvulnerability categories])\n\nThis field must be an array.', - example: '["Firewall"]', - default_field: false, - }, - { - name: 'classification', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The classification of the vulnerability scoring system. For example\n(https://www.first.org/cvss/)', - example: 'CVSS', - default_field: false, - }, - { - name: 'description', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - multi_fields: [ - { - name: 'text', - type: 'text', - norms: false, - }, - ], - description: - 'The description of the vulnerability that provides additional context\nof the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common\nVulnerabilities and Exposure CVE description])', - example: 'In macOS before 2.12.6, there is a vulnerability in the RPC...', - default_field: false, - }, - { - name: 'enumeration', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The type of identifier used for this vulnerability. For example\n(https://cve.mitre.org/about/)', - example: 'CVE', - default_field: false, - }, - { - name: 'id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The identification (ID) is the number portion of a vulnerability\nentry. It includes a unique identification number for the vulnerability. For\nexample (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities\nand Exposure CVE ID]', - example: 'CVE-2019-00001', - default_field: false, - }, - { - name: 'reference', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'A resource that provides additional information, context, and mitigations\nfor the identified vulnerability.', - example: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111', - default_field: false, - }, - { - name: 'report_id', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The report or scan identification number.', - example: 20191018.0001, - default_field: false, - }, - { - name: 'scanner.vendor', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: 'The name of the vulnerability scanner vendor.', - example: 'Tenable', - default_field: false, - }, - { - name: 'score.base', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nBase scores cover an assessment for exploitability metrics (attack vector,\ncomplexity, privileges, and user interaction), impact metrics (confidentiality,\nintegrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.environmental', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nEnvironmental scores cover an assessment for any modified Base metrics, confidentiality,\nintegrity, and availability requirements. For example (https://www.first.org/cvss/specification-document)', - example: 5.5, - default_field: false, - }, - { - name: 'score.temporal', - level: 'extended', - type: 'float', - description: - 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe.\n\nTemporal scores cover an assessment for code maturity, remediation level,\nand confidence. For example (https://www.first.org/cvss/specification-document)', - default_field: false, - }, - { - name: 'score.version', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The National Vulnerability Database (NVD) provides qualitative\nseverity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score\nranges in addition to the severity ratings for CVSS v3.0 as they are defined\nin the CVSS v3.0 specification.\n\nCVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit\norganization, whose mission is to help computer security incident response\nteams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 2, - default_field: false, - }, - { - name: 'severity', - level: 'extended', - type: 'keyword', - ignore_above: 1024, - description: - 'The severity of the vulnerability can help with metrics and internal\nprioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss)', - example: 'Critical', - default_field: false, - }, - ], - }, - ], - }, - { - key: 'beat', - anchor: 'beat-common', - title: 'Beat', - description: 'Contains common beat fields available in all event types.\n', - fields: [ - { - name: 'agent.hostname', - type: 'keyword', - description: 'Hostname of the agent.', - }, - { - name: 'beat.timezone', - type: 'alias', - path: 'event.timezone', - migration: true, - }, - { - name: 'fields', - type: 'object', - object_type: 'keyword', - description: 'Contains user configurable fields.\n', - }, - { - name: 'beat.name', - type: 'alias', - path: 'host.name', - migration: true, - }, - { - name: 'beat.hostname', - type: 'alias', - path: 'agent.hostname', - migration: true, - }, - { - name: 'timeseries.instance', - type: 'keyword', - description: 'Time series instance id', - }, - ], - }, - { - key: 'cloud', - title: 'Cloud provider metadata', - description: 'Metadata from cloud providers added by the add_cloud_metadata processor.\n', - fields: [ - { - name: 'cloud.project.id', - example: 'project-x', - description: 'Name of the project in Google Cloud.\n', - }, - { - name: 'cloud.image.id', - example: 'ami-abcd1234', - description: 'Image ID for the cloud instance.\n', - }, - { - name: 'meta.cloud.provider', - type: 'alias', - path: 'cloud.provider', - migration: true, - }, - { - name: 'meta.cloud.instance_id', - type: 'alias', - path: 'cloud.instance.id', - migration: true, - }, - { - name: 'meta.cloud.instance_name', - type: 'alias', - path: 'cloud.instance.name', - migration: true, - }, - { - name: 'meta.cloud.machine_type', - type: 'alias', - path: 'cloud.machine.type', - migration: true, - }, - { - name: 'meta.cloud.availability_zone', - type: 'alias', - path: 'cloud.availability_zone', - migration: true, - }, - { - name: 'meta.cloud.project_id', - type: 'alias', - path: 'cloud.project.id', - migration: true, - }, - { - name: 'meta.cloud.region', - type: 'alias', - path: 'cloud.region', - migration: true, - }, - ], - }, - { - key: 'docker', - title: 'Docker', - description: 'Docker stats collected from Docker.\n', - short_config: false, - anchor: 'docker-processor', - fields: [ - { - name: 'docker', - type: 'group', - fields: [ - { - name: 'container.id', - type: 'alias', - path: 'container.id', - migration: true, - }, - { - name: 'container.image', - type: 'alias', - path: 'container.image.name', - migration: true, - }, - { - name: 'container.name', - type: 'alias', - path: 'container.name', - migration: true, - }, - { - name: 'container.labels', - type: 'object', - object_type: 'keyword', - description: 'Image labels.\n', - }, - ], - }, - ], - }, - { - key: 'host', - title: 'Host', - description: 'Info collected for the host machine.\n', - anchor: 'host-processor', - fields: [ - { - name: 'host', - type: 'group', - fields: [ - { - name: 'containerized', - type: 'boolean', - description: 'If the host is a container.\n', - }, - { - name: 'os.build', - type: 'keyword', - example: '18D109', - description: 'OS build information.\n', - }, - { - name: 'os.codename', - type: 'keyword', - example: 'stretch', - description: 'OS codename, if any.\n', - }, - ], - }, - ], - }, - { - key: 'kubernetes', - title: 'Kubernetes', - description: 'Kubernetes metadata added by the kubernetes processor\n', - short_config: false, - anchor: 'kubernetes-processor', - fields: [ - { - name: 'kubernetes', - type: 'group', - fields: [ - { - name: 'pod.name', - type: 'keyword', - description: 'Kubernetes pod name\n', - }, - { - name: 'pod.uid', - type: 'keyword', - description: 'Kubernetes Pod UID\n', - }, - { - name: 'namespace', - type: 'keyword', - description: 'Kubernetes namespace\n', - }, - { - name: 'node.name', - type: 'keyword', - description: 'Kubernetes node name\n', - }, - { - name: 'labels.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Kubernetes labels map\n', - }, - { - name: 'annotations.*', - type: 'object', - object_type: 'keyword', - object_type_mapping_type: '*', - description: 'Kubernetes annotations map\n', - }, - { - name: 'replicaset.name', - type: 'keyword', - description: 'Kubernetes replicaset name\n', - }, - { - name: 'deployment.name', - type: 'keyword', - description: 'Kubernetes deployment name\n', - }, - { - name: 'statefulset.name', - type: 'keyword', - description: 'Kubernetes statefulset name\n', - }, - { - name: 'container.name', - type: 'keyword', - description: 'Kubernetes container name\n', - }, - { - name: 'container.image', - type: 'keyword', - description: 'Kubernetes container image\n', - }, - ], - }, - ], - }, - { - key: 'process', - title: 'Process', - description: 'Process metadata fields\n', - fields: [ - { - name: 'process', - type: 'group', - fields: [ - { - name: 'exe', - type: 'alias', - path: 'process.executable', - migration: true, - }, - ], - }, - ], - }, - { - key: 'jolokia-autodiscover', - title: 'Jolokia Discovery autodiscover provider', - description: 'Metadata from Jolokia Discovery added by the jolokia provider.\n', - fields: [ - { - name: 'jolokia.agent.version', - type: 'keyword', - description: 'Version number of jolokia agent.\n', - }, - { - name: 'jolokia.agent.id', - type: 'keyword', - description: - 'Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type.\n', - }, - { - name: 'jolokia.server.product', - type: 'keyword', - description: 'The container product if detected.\n', - }, - { - name: 'jolokia.server.version', - type: 'keyword', - description: "The container's version (if detected).\n", - }, - { - name: 'jolokia.server.vendor', - type: 'keyword', - description: 'The vendor of the container the agent is running in.\n', - }, - { - name: 'jolokia.url', - type: 'keyword', - description: 'The URL how this agent can be contacted.\n', - }, - { - name: 'jolokia.secured', - type: 'boolean', - description: 'Whether the agent was configured for authentication or not.\n', - }, - ], - }, - { - key: 'common', - title: 'Common', - description: - 'These fields contain data about the environment in which the transaction or flow was captured.\n', - fields: [ - { - name: 'type', - description: - 'The type of the transaction (for example, HTTP, MySQL, Redis, or RUM) or "flow" in case of flows.\n', - required: true, - }, - { - name: 'server.process.name', - description: 'The name of the process that served the transaction.\n', - }, - { - name: 'server.process.args', - description: 'The command-line of the process that served the transaction.\n', - }, - { - name: 'server.process.executable', - description: 'Absolute path to the server process executable.\n', - }, - { - name: 'server.process.working_directory', - description: 'The working directory of the server process.\n', - }, - { - name: 'server.process.start', - description: 'The time the server process started.\n', - }, - { - name: 'client.process.name', - description: 'The name of the process that initiated the transaction.\n', - }, - { - name: 'client.process.args', - description: 'The command-line of the process that initiated the transaction.\n', - }, - { - name: 'client.process.executable', - description: 'Absolute path to the client process executable.\n', - }, - { - name: 'client.process.working_directory', - description: 'The working directory of the client process.\n', - }, - { - name: 'client.process.start', - description: 'The time the client process started.\n', - }, - { - name: 'real_ip', - type: 'alias', - path: 'network.forwarded_ip', - migration: true, - description: - 'If the server initiating the transaction is a proxy, this field contains the original client IP address. For HTTP, for example, the IP address extracted from a configurable HTTP header, by default `X-Forwarded-For`.\nUnless this field is disabled, it always has a value, and it matches the `client_ip` for non proxy clients.\n', - }, - { - name: 'transport', - type: 'alias', - path: 'network.transport', - migration: true, - description: - 'The transport protocol used for the transaction. If not specified, then tcp is assumed.\n', - }, - ], - }, - { - key: 'flows_event', - title: 'Flow Event', - description: 'These fields contain data about the flow itself.\n', - fields: [ - { - name: 'flow.final', - type: 'boolean', - description: - 'Indicates if event is last event in flow. If final is false, the event reports an intermediate flow state only.\n', - }, - { - name: 'flow.id', - description: 'Internal flow ID based on connection meta data and address.\n', - }, - { - name: 'flow.vlan', - type: 'long', - description: - "VLAN identifier from the 802.1q frame. In case of a multi-tagged frame this field will be an array with the outer tag's VLAN identifier listed first.\n", - }, - { - name: 'flow_id', - type: 'alias', - path: 'flow.id', - migration: true, - }, - { - name: 'final', - type: 'alias', - path: 'flow.final', - migration: true, - }, - { - name: 'vlan', - type: 'alias', - path: 'flow.vlan', - migration: true, - }, - { - name: 'source.stats.net_bytes_total', - type: 'alias', - path: 'source.bytes', - migration: true, - }, - { - name: 'source.stats.net_packets_total', - type: 'alias', - path: 'source.packets', - migration: true, - }, - { - name: 'dest.stats.net_bytes_total', - type: 'alias', - path: 'destination.bytes', - migration: true, - }, - { - name: 'dest.stats.net_packets_total', - type: 'alias', - path: 'destination.packets', - migration: true, - }, - ], - }, - { - key: 'trans_event', - title: 'Transaction Event', - description: 'These fields contain data about the transaction itself.\n', - fields: [ - { - name: 'status', - description: - 'The high level status of the transaction. The way to compute this value depends on the protocol, but the result has a meaning independent of the protocol.\n', - required: true, - possible_values: ['OK', 'Error', 'Server Error', 'Client Error'], - }, - { - name: 'method', - description: - 'The command/verb/method of the transaction. For HTTP, this is the method name (GET, POST, PUT, and so on), for SQL this is the verb (SELECT, UPDATE, DELETE, and so on).\n', - }, - { - name: 'resource', - description: - 'The logical resource that this transaction refers to. For HTTP, this is the URL path up to the last slash (/). For example, if the URL is `/users/1`, the resource is `/users`. For databases, the resource is typically the table name. The field is not filled for all transaction types.\n', - }, - { - name: 'path', - required: true, - description: - 'The path the transaction refers to. For HTTP, this is the URL. For SQL databases, this is the table name. For key-value stores, this is the key.\n', - }, - { - name: 'query', - type: 'keyword', - description: - 'The query in a human readable format. For HTTP, it will typically be something like `GET /users/_search?name=test`. For MySQL, it is something like `SELECT id from users where name=test`.\n', - }, - { - name: 'params', - type: 'text', - description: - 'The request parameters. For HTTP, these are the POST or GET parameters. For Thrift-RPC, these are the parameters from the request.\n', - }, - { - name: 'notes', - type: 'alias', - path: 'error.message', - description: - 'Messages from Packetbeat itself. This field usually contains error messages for interpreting the raw data. This information can be helpful for troubleshooting.\n', - }, - ], - }, - { - key: 'raw', - title: 'Raw', - description: 'These fields contain the raw transaction data.', - fields: [ - { - name: 'request', - type: 'text', - description: - 'For text protocols, this is the request as seen on the wire (application layer only). For binary protocols this is our representation of the request.\n', - }, - { - name: 'response', - type: 'text', - description: - 'For text protocols, this is the response as seen on the wire (application layer only). For binary protocols this is our representation of the request.\n', - }, - ], - }, - { - key: 'trans_measurements', - title: 'Measurements (Transactions)', - description: 'These fields contain measurements related to the transaction.\n', - fields: [ - { - name: 'bytes_in', - type: 'alias', - path: 'source.bytes', - description: - 'The number of bytes of the request. Note that this size is the application layer message length, without the length of the IP or TCP headers.\n', - }, - { - name: 'bytes_out', - type: 'alias', - path: 'destination.bytes', - description: - 'The number of bytes of the response. Note that this size is the application layer message length, without the length of the IP or TCP headers.\n', - }, - ], - }, - { - key: 'amqp', - title: 'AMQP', - description: 'AMQP specific event fields.', - fields: [ - { - name: 'amqp', - type: 'group', - fields: [ - { - name: 'reply-code', - type: 'long', - description: 'AMQP reply code to an error, similar to http reply-code\n', - example: 404, - }, - { - name: 'reply-text', - type: 'keyword', - description: 'Text explaining the error.\n', - }, - { - name: 'class-id', - type: 'long', - description: 'Failing method class.\n', - }, - { - name: 'method-id', - type: 'long', - description: 'Failing method ID.\n', - }, - { - name: 'exchange', - type: 'keyword', - description: 'Name of the exchange.\n', - }, - { - name: 'exchange-type', - type: 'keyword', - description: 'Exchange type.\n', - example: 'fanout', - }, - { - name: 'passive', - type: 'boolean', - description: 'If set, do not create exchange/queue.\n', - }, - { - name: 'durable', - type: 'boolean', - description: 'If set, request a durable exchange/queue.\n', - }, - { - name: 'exclusive', - type: 'boolean', - description: 'If set, request an exclusive queue.\n', - }, - { - name: 'auto-delete', - type: 'boolean', - description: 'If set, auto-delete queue when unused.\n', - }, - { - name: 'no-wait', - type: 'boolean', - description: 'If set, the server will not respond to the method.\n', - }, - { - name: 'consumer-tag', - description: 'Identifier for the consumer, valid within the current channel.\n', - }, - { - name: 'delivery-tag', - type: 'long', - description: 'The server-assigned and channel-specific delivery tag.\n', - }, - { - name: 'message-count', - type: 'long', - description: - 'The number of messages in the queue, which will be zero for newly-declared queues.\n', - }, - { - name: 'consumer-count', - type: 'long', - description: 'The number of consumers of a queue.\n', - }, - { - name: 'routing-key', - type: 'keyword', - description: 'Message routing key.\n', - }, - { - name: 'no-ack', - type: 'boolean', - description: 'If set, the server does not expect acknowledgements for messages.\n', - }, - { - name: 'no-local', - type: 'boolean', - description: - 'If set, the server will not send messages to the connection that published them.\n', - }, - { - name: 'if-unused', - type: 'boolean', - description: 'Delete only if unused.\n', - }, - { - name: 'if-empty', - type: 'boolean', - description: 'Delete only if empty.\n', - }, - { - name: 'queue', - type: 'keyword', - description: 'The queue name identifies the queue within the vhost.\n', - }, - { - name: 'redelivered', - type: 'boolean', - description: - 'Indicates that the message has been previously delivered to this or another client.\n', - }, - { - name: 'multiple', - type: 'boolean', - description: 'Acknowledge multiple messages.\n', - }, - { - name: 'arguments', - type: 'object', - description: - 'Optional additional arguments passed to some methods. Can be of various types.\n', - }, - { - name: 'mandatory', - type: 'boolean', - description: 'Indicates mandatory routing.\n', - }, - { - name: 'immediate', - type: 'boolean', - description: 'Request immediate delivery.\n', - }, - { - name: 'content-type', - type: 'keyword', - description: 'MIME content type.\n', - example: 'text/plain', - }, - { - name: 'content-encoding', - type: 'keyword', - description: 'MIME content encoding.\n', - }, - { - name: 'headers', - type: 'object', - object_type: 'keyword', - description: 'Message header field table.\n', - }, - { - name: 'delivery-mode', - type: 'keyword', - description: 'Non-persistent (1) or persistent (2).\n', - }, - { - name: 'priority', - type: 'long', - description: 'Message priority, 0 to 9.\n', - }, - { - name: 'correlation-id', - type: 'keyword', - description: 'Application correlation identifier.\n', - }, - { - name: 'reply-to', - type: 'keyword', - description: 'Address to reply to.\n', - }, - { - name: 'expiration', - type: 'keyword', - description: 'Message expiration specification.\n', - }, - { - name: 'message-id', - type: 'keyword', - description: 'Application message identifier.\n', - }, - { - name: 'timestamp', - type: 'keyword', - description: 'Message timestamp.\n', - }, - { - name: 'type', - type: 'keyword', - description: 'Message type name.\n', - }, - { - name: 'user-id', - type: 'keyword', - description: 'Creating user id.\n', - }, - { - name: 'app-id', - type: 'keyword', - description: 'Creating application id.\n', - }, - ], - }, - ], - }, - { - key: 'cassandra', - title: 'Cassandra', - description: 'Cassandra v4/3 specific event fields.', - fields: [ - { - name: 'no_request', - type: 'alias', - path: 'cassandra.no_request', - migration: true, - }, - { - name: 'cassandra', - type: 'group', - description: 'Information about the Cassandra request and response.', - fields: [ - { - name: 'no_request', - type: 'boolean', - description: 'Indicates that there is no request because this is a PUSH message.\n', - }, - { - name: 'request', - type: 'group', - description: 'Cassandra request.', - fields: [ - { - name: 'headers', - type: 'group', - description: 'Cassandra request headers.', - fields: [ - { - name: 'version', - type: 'long', - description: 'The version of the protocol.', - }, - { - name: 'flags', - type: 'keyword', - description: 'Flags applying to this frame.', - }, - { - name: 'stream', - type: 'keyword', - description: - 'A frame has a stream id. If a client sends a request message with the stream id X, it is guaranteed that the stream id of the response to that message will be X.', - }, - { - name: 'op', - type: 'keyword', - description: 'An operation type that distinguishes the actual message.', - }, - { - name: 'length', - type: 'long', - description: - 'A integer representing the length of the body of the frame (a frame is limited to 256MB in length).', - }, - ], - }, - { - name: 'query', - type: 'keyword', - description: 'The CQL query which client send to cassandra.', - }, - ], - }, - { - name: 'response', - type: 'group', - description: 'Cassandra response.', - fields: [ - { - name: 'headers', - type: 'group', - description: - "Cassandra response headers, the structure is as same as request's header.", - fields: [ - { - name: 'version', - type: 'long', - description: 'The version of the protocol.', - }, - { - name: 'flags', - type: 'keyword', - description: 'Flags applying to this frame.', - }, - { - name: 'stream', - type: 'keyword', - description: - 'A frame has a stream id. If a client sends a request message with the stream id X, it is guaranteed that the stream id of the response to that message will be X.', - }, - { - name: 'op', - type: 'keyword', - description: 'An operation type that distinguishes the actual message.', - }, - { - name: 'length', - type: 'long', - description: - 'A integer representing the length of the body of the frame (a frame is limited to 256MB in length).', - }, - ], - }, - { - name: 'result', - type: 'group', - description: 'Details about the returned result.', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'Cassandra result type.', - }, - { - name: 'rows', - type: 'group', - description: 'Details about the rows.', - fields: [ - { - name: 'num_rows', - type: 'long', - description: 'Representing the number of rows present in this result.', - }, - { - name: 'meta', - type: 'group', - description: 'Composed of result metadata.', - fields: [ - { - name: 'keyspace', - type: 'keyword', - description: - 'Only present after set Global_tables_spec, the keyspace name.', - }, - { - name: 'table', - type: 'keyword', - description: - 'Only present after set Global_tables_spec, the table name.', - }, - { - name: 'flags', - type: 'keyword', - description: - 'Provides information on the formatting of the remaining information.', - }, - { - name: 'col_count', - type: 'long', - description: - 'Representing the number of columns selected by the query that produced this result.', - }, - { - name: 'pkey_columns', - type: 'long', - description: 'Representing the PK columns index and counts.', - }, - { - name: 'paging_state', - type: 'keyword', - description: - 'The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query.', - }, - ], - }, - ], - }, - { - name: 'keyspace', - type: 'keyword', - description: 'Indicating the name of the keyspace that has been set.', - }, - { - name: 'schema_change', - type: 'group', - description: 'The result to a schema_change message.', - fields: [ - { - name: 'change', - type: 'keyword', - description: 'Representing the type of changed involved.', - }, - { - name: 'keyspace', - type: 'keyword', - description: 'This describes which keyspace has changed.', - }, - { - name: 'table', - type: 'keyword', - description: 'This describes which table has changed.', - }, - { - name: 'object', - type: 'keyword', - description: - 'This describes the name of said affected object (either the table, user type, function, or aggregate name).', - }, - { - name: 'target', - type: 'keyword', - description: - 'Target could be "FUNCTION" or "AGGREGATE", multiple arguments.', - }, - { - name: 'name', - type: 'keyword', - description: 'The function/aggregate name.', - }, - { - name: 'args', - type: 'keyword', - description: 'One string for each argument type (as CQL type).', - }, - ], - }, - { - name: 'prepared', - type: 'group', - description: 'The result to a PREPARE message.', - fields: [ - { - name: 'prepared_id', - type: 'keyword', - description: 'Representing the prepared query ID.', - }, - { - name: 'req_meta', - type: 'group', - description: 'This describes the request metadata.', - fields: [ - { - name: 'keyspace', - type: 'keyword', - description: - 'Only present after set Global_tables_spec, the keyspace name.', - }, - { - name: 'table', - type: 'keyword', - description: - 'Only present after set Global_tables_spec, the table name.', - }, - { - name: 'flags', - type: 'keyword', - description: - 'Provides information on the formatting of the remaining information.', - }, - { - name: 'col_count', - type: 'long', - description: - 'Representing the number of columns selected by the query that produced this result.', - }, - { - name: 'pkey_columns', - type: 'long', - description: 'Representing the PK columns index and counts.', - }, - { - name: 'paging_state', - type: 'keyword', - description: - 'The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query.', - }, - ], - }, - { - name: 'resp_meta', - type: 'group', - description: 'This describes the metadata for the result set.', - fields: [ - { - name: 'keyspace', - type: 'keyword', - description: - 'Only present after set Global_tables_spec, the keyspace name.', - }, - { - name: 'table', - type: 'keyword', - description: - 'Only present after set Global_tables_spec, the table name.', - }, - { - name: 'flags', - type: 'keyword', - description: - 'Provides information on the formatting of the remaining information.', - }, - { - name: 'col_count', - type: 'long', - description: - 'Representing the number of columns selected by the query that produced this result.', - }, - { - name: 'pkey_columns', - type: 'long', - description: 'Representing the PK columns index and counts.', - }, - { - name: 'paging_state', - type: 'keyword', - description: - 'The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query.', - }, - ], - }, - ], - }, - ], - }, - { - name: 'supported', - type: 'object', - object_type: 'keyword', - description: - 'Indicates which startup options are supported by the server. This message comes as a response to an OPTIONS message.', - }, - { - name: 'authentication', - type: 'group', - description: - 'Indicates that the server requires authentication, and which authentication mechanism to use.', - fields: [ - { - name: 'class', - type: 'keyword', - description: 'Indicates the full class name of the IAuthenticator in use', - }, - ], - }, - { - name: 'warnings', - type: 'keyword', - description: 'The text of the warnings, only occur when Warning flag was set.', - }, - { - name: 'event', - type: 'group', - description: - 'Event pushed by the server. A client will only receive events for the types it has REGISTERed to.', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'Representing the event type.', - }, - { - name: 'change', - type: 'keyword', - description: - 'The message corresponding respectively to the type of change followed by the address of the new/removed node.', - }, - { - name: 'host', - type: 'keyword', - description: 'Representing the node ip.', - }, - { - name: 'port', - type: 'long', - description: 'Representing the node port.', - }, - { - name: 'schema_change', - type: 'group', - description: 'The events details related to schema change.', - fields: [ - { - name: 'change', - type: 'keyword', - description: 'Representing the type of changed involved.', - }, - { - name: 'keyspace', - type: 'keyword', - description: 'This describes which keyspace has changed.', - }, - { - name: 'table', - type: 'keyword', - description: 'This describes which table has changed.', - }, - { - name: 'object', - type: 'keyword', - description: - 'This describes the name of said affected object (either the table, user type, function, or aggregate name).', - }, - { - name: 'target', - type: 'keyword', - description: - 'Target could be "FUNCTION" or "AGGREGATE", multiple arguments.', - }, - { - name: 'name', - type: 'keyword', - description: 'The function/aggregate name.', - }, - { - name: 'args', - type: 'keyword', - description: 'One string for each argument type (as CQL type).', - }, - ], - }, - ], - }, - { - name: 'error', - type: 'group', - description: - 'Indicates an error processing a request. The body of the message will be an error code followed by a error message. Then, depending on the exception, more content may follow.', - fields: [ - { - name: 'code', - type: 'long', - description: 'The error code of the Cassandra response.', - }, - { - name: 'msg', - type: 'keyword', - description: 'The error message of the Cassandra response.', - }, - { - name: 'type', - type: 'keyword', - description: 'The error type of the Cassandra response.', - }, - { - name: 'details', - type: 'group', - description: 'The details of the error.', - fields: [ - { - name: 'read_consistency', - type: 'keyword', - description: - 'Representing the consistency level of the query that triggered the exception.', - }, - { - name: 'required', - type: 'long', - description: - 'Representing the number of nodes that should be alive to respect consistency level.', - }, - { - name: 'alive', - type: 'long', - description: - 'Representing the number of replicas that were known to be alive when the request had been processed (since an unavailable exception has been triggered).', - }, - { - name: 'received', - type: 'long', - description: - 'Representing the number of nodes having acknowledged the request.', - }, - { - name: 'blockfor', - type: 'long', - description: - 'Representing the number of replicas whose acknowledgement is required to achieve consistency level.', - }, - { - name: 'write_type', - type: 'keyword', - description: 'Describe the type of the write that timed out.', - }, - { - name: 'data_present', - type: 'boolean', - description: 'It means the replica that was asked for data had responded.', - }, - { - name: 'keyspace', - type: 'keyword', - description: 'The keyspace of the failed function.', - }, - { - name: 'table', - type: 'keyword', - description: 'The keyspace of the failed function.', - }, - { - name: 'stmt_id', - type: 'keyword', - description: 'Representing the unknown ID.', - }, - { - name: 'num_failures', - type: 'keyword', - description: - 'Representing the number of nodes that experience a failure while executing the request.', - }, - { - name: 'function', - type: 'keyword', - description: 'The name of the failed function.', - }, - { - name: 'arg_types', - type: 'keyword', - description: - 'One string for each argument type (as CQL type) of the failed function.', - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - key: 'dhcpv4', - title: 'DHCPv4', - description: 'DHCPv4 event fields', - fields: [ - { - name: 'dhcpv4', - type: 'group', - fields: [ - { - name: 'transaction_id', - type: 'keyword', - description: - 'Transaction ID, a random number chosen by the\nclient, used by the client and server to associate\nmessages and responses between a client and a\nserver.\n', - }, - { - name: 'seconds', - type: 'long', - description: - 'Number of seconds elapsed since client began address acquisition or\nrenewal process.\n', - }, - { - name: 'flags', - type: 'keyword', - description: - 'Flags are set by the client to indicate how the DHCP server should\nits reply -- either unicast or broadcast.\n', - }, - { - name: 'client_ip', - type: 'ip', - description: 'The current IP address of the client.', - }, - { - name: 'assigned_ip', - type: 'ip', - description: - 'The IP address that the DHCP server is assigning to the client.\nThis field is also known as "your" IP address.\n', - }, - { - name: 'server_ip', - type: 'ip', - description: - 'The IP address of the DHCP server that the client should use for the\nnext step in the bootstrap process.\n', - }, - { - name: 'relay_ip', - type: 'ip', - description: - 'The relay IP address used by the client to contact the server\n(i.e. a DHCP relay server).\n', - }, - { - name: 'client_mac', - type: 'keyword', - description: "The client's MAC address (layer two).", - }, - { - name: 'server_name', - type: 'keyword', - description: - 'The name of the server sending the message. Optional. Used in\nDHCPOFFER or DHCPACK messages.\n', - }, - { - name: 'op_code', - type: 'keyword', - example: 'bootreply', - description: 'The message op code (bootrequest or bootreply).\n', - }, - { - name: 'hops', - type: 'long', - description: 'The number of hops the DHCP message went through.', - }, - { - name: 'hardware_type', - type: 'keyword', - description: - 'The type of hardware used for the local network (Ethernet,\nLocalTalk, etc).\n', - }, - { - name: 'option', - type: 'group', - fields: [ - { - name: 'message_type', - type: 'keyword', - example: 'ack', - description: - 'The specific type of DHCP message being sent (e.g. discover,\noffer, request, decline, ack, nak, release, inform).\n', - }, - { - name: 'parameter_request_list', - type: 'keyword', - description: - 'This option is used by a DHCP client to request values for\nspecified configuration parameters.\n', - }, - { - name: 'requested_ip_address', - type: 'ip', - description: - 'This option is used in a client request (DHCPDISCOVER) to allow\nthe client to request that a particular IP address be assigned.\n', - }, - { - name: 'server_identifier', - type: 'ip', - description: - 'IP address of the individual DHCP server which handled this\nmessage.\n', - }, - { - name: 'broadcast_address', - type: 'ip', - description: - "This option specifies the broadcast address in use on the\nclient's subnet.\n", - }, - { - name: 'max_dhcp_message_size', - type: 'long', - description: - 'This option specifies the maximum length DHCP message that the\nclient is willing to accept.\n', - }, - { - name: 'class_identifier', - type: 'keyword', - description: - "This option is used by DHCP clients to optionally identify the\nvendor type and configuration of a DHCP client. Vendors may\nchoose to define specific vendor class identifiers to convey\nparticular configuration or other identification information\nabout a client. For example, the identifier may encode the\nclient's hardware configuration.\n", - }, - { - name: 'domain_name', - type: 'keyword', - description: - 'This option specifies the domain name that client should use\nwhen resolving hostnames via the Domain Name System.\n', - }, - { - name: 'dns_servers', - type: 'ip', - description: - 'The domain name server option specifies a list of Domain Name\nSystem servers available to the client.\n', - }, - { - name: 'vendor_identifying_options', - type: 'object', - description: - 'A DHCP client may use this option to unambiguously identify the\nvendor that manufactured the hardware on which the client is\nrunning, the software in use, or an industry consortium to which\nthe vendor belongs. This field is described in RFC 3925.\n', - }, - { - name: 'subnet_mask', - type: 'ip', - description: - 'The subnet mask that the client should use on the currnet\nnetwork.\n', - }, - { - name: 'utc_time_offset_sec', - type: 'long', - description: - "The time offset field specifies the offset of the client's\nsubnet in seconds from Coordinated Universal Time (UTC).\n", - }, - { - name: 'router', - type: 'ip', - description: - "The router option specifies a list of IP addresses for routers\non the client's subnet.\n", - }, - { - name: 'time_servers', - type: 'ip', - description: - 'The time server option specifies a list of RFC 868 time servers\navailable to the client.\n', - }, - { - name: 'ntp_servers', - type: 'ip', - description: - 'This option specifies a list of IP addresses indicating NTP\nservers available to the client.\n', - }, - { - name: 'hostname', - type: 'keyword', - description: 'This option specifies the name of the client.\n', - }, - { - name: 'ip_address_lease_time_sec', - type: 'long', - description: - 'This option is used in a client request (DHCPDISCOVER or\nDHCPREQUEST) to allow the client to request a lease time for the\nIP address. In a server reply (DHCPOFFER), a DHCP server uses\nthis option to specify the lease time it is willing to offer.\n', - }, - { - name: 'message', - type: 'text', - description: - 'This option is used by a DHCP server to provide an error message\nto a DHCP client in a DHCPNAK message in the event of a failure.\nA client may use this option in a DHCPDECLINE message to\nindicate the why the client declined the offered parameters.\n', - }, - { - name: 'renewal_time_sec', - type: 'long', - description: - 'This option specifies the time interval from address assignment\nuntil the client transitions to the RENEWING state.\n', - }, - { - name: 'rebinding_time_sec', - type: 'long', - description: - 'This option specifies the time interval from address assignment\nuntil the client transitions to the REBINDING state.\n', - }, - { - name: 'boot_file_name', - type: 'keyword', - description: - "This option is used to identify a bootfile when the 'file' field\nin the DHCP header has been used for DHCP options.\n", - }, - ], - }, - ], - }, - ], - }, - { - key: 'dns', - title: 'DNS', - description: 'DNS-specific event fields.', - fields: [ - { - name: 'dns', - type: 'group', - fields: [ - { - name: 'flags.authoritative', - type: 'boolean', - description: - 'A DNS flag specifying that the responding server is an authority for the domain name used in the question.\n', - }, - { - name: 'flags.recursion_available', - type: 'boolean', - description: - 'A DNS flag specifying whether recursive query support is available in the name server.\n', - }, - { - name: 'flags.recursion_desired', - type: 'boolean', - description: - 'A DNS flag specifying that the client directs the server to pursue a query recursively. Recursive query support is optional.\n', - }, - { - name: 'flags.authentic_data', - type: 'boolean', - description: - 'A DNS flag specifying that the recursive server considers the response authentic.\n', - }, - { - name: 'flags.checking_disabled', - type: 'boolean', - description: - 'A DNS flag specifying that the client disables the server signature validation of the query.\n', - }, - { - name: 'flags.truncated_response', - type: 'boolean', - description: - 'A DNS flag specifying that only the first 512 bytes of the reply were returned.\n', - }, - { - name: 'question.etld_plus_one', - description: - 'The effective top-level domain (eTLD) plus one more label.\nFor example, the eTLD+1 for "foo.bar.golang.org." is "golang.org.".\nThe data for determining the eTLD comes from an embedded copy of the\ndata from http://publicsuffix.org.', - example: 'amazon.co.uk.', - }, - { - name: 'answers_count', - type: 'long', - description: 'The number of resource records contained in the `dns.answers` field.\n', - }, - { - name: 'authorities', - type: 'object', - description: - 'An array containing a dictionary for each authority section from the answer.\n', - }, - { - name: 'authorities_count', - type: 'long', - description: - 'The number of resource records contained in the `dns.authorities` field. The `dns.authorities` field may or may not be included depending on the configuration of Packetbeat.\n', - }, - { - name: 'authorities.name', - description: 'The domain name to which this resource record pertains.', - example: 'example.com.', - }, - { - name: 'authorities.type', - description: 'The type of data contained in this resource record.', - example: 'NS', - }, - { - name: 'authorities.class', - description: 'The class of DNS data contained in this resource record.', - example: 'IN', - }, - { - name: 'additionals', - type: 'object', - description: - 'An array containing a dictionary for each additional section from the answer.\n', - }, - { - name: 'additionals_count', - type: 'long', - description: - 'The number of resource records contained in the `dns.additionals` field. The `dns.additionals` field may or may not be included depending on the configuration of Packetbeat.\n', - }, - { - name: 'additionals.name', - description: 'The domain name to which this resource record pertains.', - example: 'example.com.', - }, - { - name: 'additionals.type', - description: 'The type of data contained in this resource record.', - example: 'NS', - }, - { - name: 'additionals.class', - description: 'The class of DNS data contained in this resource record.', - example: 'IN', - }, - { - name: 'additionals.ttl', - description: - 'The time interval in seconds that this resource record may be cached before it should be discarded. Zero values mean that the data should not be cached.\n', - type: 'long', - }, - { - name: 'additionals.data', - description: - 'The data describing the resource. The meaning of this data depends on the type and class of the resource record.\n', - }, - { - name: 'opt.version', - description: 'The EDNS version.', - example: '0', - }, - { - name: 'opt.do', - type: 'boolean', - description: 'If set, the transaction uses DNSSEC.', - }, - { - name: 'opt.ext_rcode', - description: 'Extended response code field.', - example: 'BADVERS', - }, - { - name: 'opt.udp_size', - type: 'long', - description: "Requestor's UDP payload size (in bytes).", - }, - ], - }, - ], - }, - { - key: 'http', - title: 'HTTP', - description: 'HTTP-specific event fields.', - fields: [ - { - name: 'http', - type: 'group', - description: 'Information about the HTTP request and response.', - fields: [ - { - name: 'request', - description: 'HTTP request', - type: 'group', - fields: [ - { - name: 'headers', - type: 'object', - object_type: 'keyword', - description: - 'A map containing the captured header fields from the request. Which headers to capture is configurable. If headers with the same header name are present in the message, they will be separated by commas.\n', - }, - { - name: 'params', - type: 'alias', - migration: true, - path: 'url.query', - }, - ], - }, - { - name: 'response', - description: 'HTTP response', - type: 'group', - fields: [ - { - name: 'status_phrase', - description: 'The HTTP status phrase.', - example: 'Not Found', - }, - { - name: 'headers', - type: 'object', - object_type: 'keyword', - description: - 'A map containing the captured header fields from the response. Which headers to capture is configurable. If headers with the same header name are present in the message, they will be separated by commas.\n', - }, - { - name: 'code', - type: 'alias', - migration: true, - path: 'http.response.status_code', - }, - { - name: 'phrase', - type: 'alias', - migration: true, - path: 'http.response.status_phrase', - }, - ], - }, - ], - }, - ], - }, - { - key: 'icmp', - title: 'ICMP', - description: 'ICMP specific event fields.\n', - fields: [ - { - name: 'icmp', - type: 'group', - fields: [ - { - name: 'version', - description: 'The version of the ICMP protocol.', - possible_values: [4, 6], - }, - { - name: 'request.message', - type: 'keyword', - description: 'A human readable form of the request.', - }, - { - name: 'request.type', - type: 'long', - description: 'The request type.', - }, - { - name: 'request.code', - type: 'long', - description: 'The request code.', - }, - { - name: 'response.message', - type: 'keyword', - description: 'A human readable form of the response.', - }, - { - name: 'response.type', - type: 'long', - description: 'The response type.', - }, - { - name: 'response.code', - type: 'long', - description: 'The response code.', - }, - ], - }, - ], - }, - { - key: 'memcache', - title: 'Memcache', - description: 'Memcached-specific event fields', - fields: [ - { - name: 'memcache', - type: 'group', - fields: [ - { - name: 'protocol_type', - type: 'keyword', - description: - 'The memcache protocol implementation. The value can be "binary" for binary-based, "text" for text-based, or "unknown" for an unknown memcache protocol type.\n', - }, - { - name: 'request.line', - type: 'keyword', - description: 'The raw command line for unknown commands ONLY.\n', - }, - { - name: 'request.command', - type: 'keyword', - description: - 'The memcache command being requested in the memcache text protocol. For example "set" or "get". The binary protocol opcodes are translated into memcache text protocol commands.\n', - }, - { - name: 'response.command', - type: 'keyword', - description: - 'Either the text based protocol response message type or the name of the originating request if binary protocol is used.\n', - }, - { - name: 'request.type', - type: 'keyword', - description: - 'The memcache command classification. This value can be "UNKNOWN", "Load", "Store", "Delete", "Counter", "Info", "SlabCtrl", "LRUCrawler", "Stats", "Success", "Fail", or "Auth".\n', - }, - { - name: 'response.type', - type: 'keyword', - description: - 'The memcache command classification. This value can be "UNKNOWN", "Load", "Store", "Delete", "Counter", "Info", "SlabCtrl", "LRUCrawler", "Stats", "Success", "Fail", or "Auth". The text based protocol will employ any of these, whereas the binary based protocol will mirror the request commands only (see `memcache.response.status` for binary protocol).\n', - }, - { - name: 'response.error_msg', - type: 'keyword', - description: - 'The optional error message in the memcache response (text based protocol only).\n', - }, - { - name: 'request.opcode', - type: 'keyword', - description: 'The binary protocol message opcode name.\n', - }, - { - name: 'response.opcode', - type: 'keyword', - description: 'The binary protocol message opcode name.\n', - }, - { - name: 'request.opcode_value', - type: 'long', - description: 'The binary protocol message opcode value.\n', - }, - { - name: 'response.opcode_value', - type: 'long', - description: 'The binary protocol message opcode value.\n', - }, - { - name: 'request.opaque', - type: 'long', - description: - 'The binary protocol opaque header value used for correlating request with response messages.\n', - }, - { - name: 'response.opaque', - type: 'long', - description: - 'The binary protocol opaque header value used for correlating request with response messages.\n', - }, - { - name: 'request.vbucket', - type: 'long', - description: 'The vbucket index sent in the binary message.\n', - }, - { - name: 'response.status', - type: 'keyword', - description: - 'The textual representation of the response error code (binary protocol only).\n', - }, - { - name: 'response.status_code', - type: 'long', - description: 'The status code value returned in the response (binary protocol only).\n', - }, - { - name: 'request.keys', - type: 'array', - description: 'The list of keys sent in the store or load commands.\n', - }, - { - name: 'response.keys', - type: 'array', - description: 'The list of keys returned for the load command (if present).\n', - }, - { - name: 'request.count_values', - type: 'long', - description: - 'The number of values found in the memcache request message. If the command does not send any data, this field is missing.\n', - }, - { - name: 'response.count_values', - type: 'long', - description: - 'The number of values found in the memcache response message. If the command does not send any data, this field is missing.\n', - }, - { - name: 'request.values', - type: 'array', - description: 'The list of base64 encoded values sent with the request (if present).\n', - }, - { - name: 'response.values', - type: 'array', - description: 'The list of base64 encoded values sent with the response (if present).\n', - }, - { - name: 'request.bytes', - type: 'long', - format: 'bytes', - description: 'The byte count of the values being transferred.\n', - }, - { - name: 'response.bytes', - type: 'long', - format: 'bytes', - description: 'The byte count of the values being transferred.\n', - }, - { - name: 'request.delta', - type: 'long', - description: 'The counter increment/decrement delta value.\n', - }, - { - name: 'request.initial', - type: 'long', - description: - 'The counter increment/decrement initial value parameter (binary protocol only).\n', - }, - { - name: 'request.verbosity', - type: 'long', - description: 'The value of the memcache "verbosity" command.\n', - }, - { - name: 'request.raw_args', - type: 'keyword', - description: - 'The text protocol raw arguments for the "stats ..." and "lru crawl ..." commands.\n', - }, - { - name: 'request.source_class', - type: 'long', - description: "The source class id in 'slab reassign' command.\n", - }, - { - name: 'request.dest_class', - type: 'long', - description: "The destination class id in 'slab reassign' command.\n", - }, - { - name: 'request.automove', - type: 'keyword', - description: - 'The automove mode in the \'slab automove\' command expressed as a string. This value can be "standby"(=0), "slow"(=1), "aggressive"(=2), or the raw value if the value is unknown.\n', - }, - { - name: 'request.flags', - type: 'long', - description: 'The memcache command flags sent in the request (if present).\n', - }, - { - name: 'response.flags', - type: 'long', - description: 'The memcache message flags sent in the response (if present).\n', - }, - { - name: 'request.exptime', - type: 'long', - description: - 'The data expiry time in seconds sent with the memcache command (if present). If the value is <30 days, the expiry time is relative to "now", or else it is an absolute Unix time in seconds (32-bit).\n', - }, - { - name: 'request.sleep_us', - type: 'long', - description: "The sleep setting in microseconds for the 'lru_crawler sleep' command.\n", - }, - { - name: 'response.value', - type: 'long', - description: 'The counter value returned by a counter operation.\n', - }, - { - name: 'request.noreply', - type: 'boolean', - description: - 'Set to true if noreply was set in the request. The `memcache.response` field will be missing.\n', - }, - { - name: 'request.quiet', - type: 'boolean', - description: - 'Set to true if the binary protocol message is to be treated as a quiet message.\n', - }, - { - name: 'request.cas_unique', - type: 'long', - description: 'The CAS (compare-and-swap) identifier if present.\n', - }, - { - name: 'response.cas_unique', - type: 'long', - description: - 'The CAS (compare-and-swap) identifier to be used with CAS-based updates (if present).\n', - }, - { - name: 'response.stats', - type: 'array', - description: - 'The list of statistic values returned. Each entry is a dictionary with the fields "name" and "value".\n', - }, - { - name: 'response.version', - type: 'keyword', - description: 'The returned memcache version string.\n', - }, - ], - }, - ], - }, - { - key: 'mongodb', - title: 'MongoDb', - description: - 'MongoDB-specific event fields. These fields mirror closely the fields for the MongoDB wire protocol. The higher level fields (for example, `query` and `resource`) apply to MongoDB events as well.\n', - fields: [ - { - name: 'mongodb', - type: 'group', - fields: [ - { - name: 'error', - description: - 'If the MongoDB request has resulted in an error, this field contains the error message returned by the server.\n', - }, - { - name: 'fullCollectionName', - description: - 'The full collection name. The full collection name is the concatenation of the database name with the collection name, using a dot (.) for the concatenation. For example, for the database foo and the collection bar, the full collection name is foo.bar.\n', - }, - { - name: 'numberToSkip', - type: 'long', - description: - 'Sets the number of documents to omit - starting from the first document in the resulting dataset - when returning the result of the query.\n', - }, - { - name: 'numberToReturn', - type: 'long', - description: 'The requested maximum number of documents to be returned.\n', - }, - { - name: 'numberReturned', - type: 'long', - description: 'The number of documents in the reply.\n', - }, - { - name: 'startingFrom', - description: 'Where in the cursor this reply is starting.\n', - }, - { - name: 'query', - description: - 'A JSON document that represents the query. The query will contain one or more elements, all of which must match for a document to be included in the result set. Possible elements include $query, $orderby, $hint, $explain, and $snapshot.\n', - }, - { - name: 'returnFieldsSelector', - description: - 'A JSON document that limits the fields in the returned documents. The returnFieldsSelector contains one or more elements, each of which is the name of a field that should be returned, and the integer value 1.\n', - }, - { - name: 'selector', - description: - 'A BSON document that specifies the query for selecting the document to update or delete.\n', - }, - { - name: 'update', - description: - 'A BSON document that specifies the update to be performed. For information on specifying updates, see the Update Operations documentation from the MongoDB Manual.\n', - }, - { - name: 'cursorId', - description: - 'The cursor identifier returned in the OP_REPLY. This must be the value that was returned from the database.\n', - }, - ], - }, - ], - }, - { - key: 'mysql', - title: 'MySQL', - description: 'MySQL-specific event fields.\n', - fields: [ - { - name: 'mysql', - type: 'group', - fields: [ - { - name: 'affected_rows', - type: 'long', - description: - 'If the MySQL command is successful, this field contains the affected number of rows of the last statement.\n', - }, - { - name: 'insert_id', - description: - 'If the INSERT query is successful, this field contains the id of the newly inserted row.\n', - }, - { - name: 'num_fields', - description: - 'If the SELECT query is successful, this field is set to the number of fields returned.\n', - }, - { - name: 'num_rows', - description: - 'If the SELECT query is successful, this field is set to the number of rows returned.\n', - }, - { - name: 'query', - description: "The row mysql query as read from the transaction's request.\n", - }, - { - name: 'error_code', - type: 'long', - description: 'The error code returned by MySQL.\n', - }, - { - name: 'error_message', - description: 'The error info message returned by MySQL.\n', - }, - ], - }, - ], - }, - { - key: 'nfs', - title: 'NFS', - description: 'NFS v4/3 specific event fields.', - fields: [ - { - name: 'nfs', - type: 'group', - fields: [ - { - name: 'version', - type: 'long', - description: 'NFS protocol version number.', - }, - { - name: 'minor_version', - type: 'long', - description: 'NFS protocol minor version number.', - }, - { - name: 'tag', - description: 'NFS v4 COMPOUND operation tag.', - }, - { - name: 'opcode', - description: 'NFS operation name, or main operation name, in case of COMPOUND calls.\n', - }, - { - name: 'status', - description: 'NFS operation reply status.', - }, - ], - }, - { - name: 'rpc', - type: 'group', - description: 'ONC RPC specific event fields.', - fields: [ - { - name: 'xid', - description: 'RPC message transaction identifier.', - }, - { - name: 'status', - description: 'RPC message reply status.', - }, - { - name: 'auth_flavor', - description: 'RPC authentication flavor.', - }, - { - name: 'cred.uid', - type: 'long', - description: "RPC caller's user id, in case of auth-unix.", - }, - { - name: 'cred.gid', - type: 'long', - description: "RPC caller's group id, in case of auth-unix.", - }, - { - name: 'cred.gids', - description: "RPC caller's secondary group ids, in case of auth-unix.", - }, - { - name: 'cred.stamp', - type: 'long', - description: 'Arbitrary ID which the caller machine may generate.', - }, - { - name: 'cred.machinename', - description: "The name of the caller's machine.", - }, - { - name: 'call_size', - type: 'alias', - path: 'source.bytes', - migration: true, - description: 'RPC call size with argument.', - }, - { - name: 'reply_size', - type: 'alias', - path: 'destination.bytes', - migration: true, - description: 'RPC reply size with argument.', - }, - ], - }, - ], - }, - { - key: 'pgsql', - title: 'PostgreSQL', - description: 'PostgreSQL-specific event fields.\n', - fields: [ - { - name: 'pgsql', - type: 'group', - fields: [ - { - name: 'error_code', - description: 'The PostgreSQL error code.', - type: 'long', - }, - { - name: 'error_message', - description: 'The PostgreSQL error message.', - }, - { - name: 'error_severity', - description: 'The PostgreSQL error severity.', - possible_values: ['ERROR', 'FATAL', 'PANIC'], - }, - { - name: 'num_fields', - description: - 'If the SELECT query if successful, this field is set to the number of fields returned.\n', - }, - { - name: 'num_rows', - description: - 'If the SELECT query if successful, this field is set to the number of rows returned.\n', - }, - ], - }, - ], - }, - { - key: 'redis', - title: 'Redis', - description: 'Redis-specific event fields.\n', - fields: [ - { - name: 'redis', - type: 'group', - fields: [ - { - name: 'return_value', - description: 'The return value of the Redis command in a human readable format.\n', - }, - { - name: 'error', - description: - 'If the Redis command has resulted in an error, this field contains the error message returned by the Redis server.\n', - }, - ], - }, - ], - }, - { - key: 'thrift', - title: 'Thrift-RPC', - description: 'Thrift-RPC specific event fields.\n', - fields: [ - { - name: 'thrift', - type: 'group', - fields: [ - { - name: 'params', - description: - 'The RPC method call parameters in a human readable format. If the IDL files are available, the parameters use names whenever possible. Otherwise, the IDs from the message are used.\n', - }, - { - name: 'service', - description: 'The name of the Thrift-RPC service as defined in the IDL files.\n', - }, - { - name: 'return_value', - description: - 'The value returned by the Thrift-RPC call. This is encoded in a human readable format.\n', - }, - { - name: 'exceptions', - description: - 'If the call resulted in exceptions, this field contains the exceptions in a human readable format.\n', - }, - ], - }, - ], - }, - { - key: 'tls_detailed', - title: 'Detailed TLS', - description: 'Detailed TLS-specific event fields.\n', - fields: [ - { - name: 'tls', - type: 'group', - fields: [ - { - name: 'detailed', - type: 'group', - default_fields: false, - fields: [ - { - name: 'version', - type: 'keyword', - description: 'The version of the TLS protocol used.\n', - example: 'TLS 1.3', - }, - { - name: 'resumption_method', - type: 'keyword', - description: - 'If the session has been resumed, the underlying method used. One of "id" for TLS session ID or "ticket" for TLS ticket extension.\n', - }, - { - name: 'client_certificate_requested', - type: 'boolean', - description: - 'Whether the server has requested the client to authenticate itself using a client certificate.\n', - }, - { - name: 'client_hello', - type: 'group', - fields: [ - { - name: 'version', - type: 'keyword', - description: - 'The version of the TLS protocol by which the client wishes to communicate during this session.\n', - }, - { - name: 'session_id', - type: 'keyword', - description: - 'Unique number to identify the session for the corresponding connection with the client.\n', - }, - { - name: 'supported_compression_methods', - type: 'keyword', - description: - 'The list of compression methods the client supports. See https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml\n', - }, - { - name: 'extensions', - type: 'group', - description: 'The hello extensions provided by the client.', - fields: [ - { - name: 'server_name_indication', - type: 'keyword', - description: 'List of hostnames', - }, - { - name: 'application_layer_protocol_negotiation', - type: 'keyword', - description: - 'List of application-layer protocols the client is willing to use.\n', - }, - { - name: 'session_ticket', - type: 'keyword', - description: - 'Length of the session ticket, if provided, or an empty string to advertise support for tickets.\n', - }, - { - name: 'supported_versions', - type: 'keyword', - description: 'List of TLS versions that the client is willing to use.\n', - }, - { - name: 'supported_groups', - type: 'keyword', - description: - 'List of Elliptic Curve Cryptography (ECC) curve groups supported by the client.\n', - }, - { - name: 'signature_algorithms', - type: 'keyword', - description: - 'List of signature algorithms that may be use in digital signatures.\n', - }, - { - name: 'ec_points_formats', - type: 'keyword', - description: - 'List of Elliptic Curve (EC) point formats. Indicates the set of point formats that the client can parse.\n', - }, - { - name: '_unparsed_', - type: 'keyword', - description: 'List of extensions that were left unparsed by Packetbeat.\n', - }, - ], - }, - ], - }, - { - name: 'server_hello', - type: 'group', - fields: [ - { - name: 'version', - type: 'keyword', - description: - 'The version of the TLS protocol that is used for this session. It is the highest version supported by the server not exceeding the version requested in the client hello.\n', - }, - { - name: 'selected_compression_method', - type: 'keyword', - description: - 'The compression method selected by the server from the list provided in the client hello.\n', - }, - { - name: 'session_id', - type: 'keyword', - description: - 'Unique number to identify the session for the corresponding connection with the client.\n', - }, - { - name: 'extensions', - type: 'group', - description: 'The hello extensions provided by the server.', - fields: [ - { - name: 'application_layer_protocol_negotiation', - type: 'keyword', - description: 'Negotiated application layer protocol', - }, - { - name: 'session_ticket', - type: 'keyword', - description: - 'Used to announce that a session ticket will be provided by the server. Always an empty string.\n', - }, - { - name: 'supported_versions', - type: 'keyword', - description: 'Negotiated TLS version to be used.\n', - }, - { - name: 'ec_points_formats', - type: 'keyword', - description: - 'List of Elliptic Curve (EC) point formats. Indicates the set of point formats that the server can parse.\n', - }, - { - name: '_unparsed_', - type: 'keyword', - description: 'List of extensions that were left unparsed by Packetbeat.\n', - }, - ], - }, - ], - }, - { - name: 'client_certificate', - type: 'group', - description: 'Certificate provided by the client for authentication.', - fields: [ - { - name: 'version', - type: 'long', - description: 'X509 format version.', - }, - { - name: 'serial_number', - type: 'keyword', - description: "The certificate's serial number.", - }, - { - name: 'not_before', - type: 'date', - description: 'Date before which the certificate is not valid.', - }, - { - name: 'not_after', - type: 'date', - description: 'Date after which the certificate expires.', - }, - { - name: 'public_key_algorithm', - type: 'keyword', - description: - "The algorithm used for this certificate's public key. One of RSA, DSA or ECDSA.\n", - }, - { - name: 'public_key_size', - type: 'long', - description: 'Size of the public key.', - }, - { - name: 'signature_algorithm', - type: 'keyword', - description: "The algorithm used for the certificate's signature.\n", - }, - { - name: 'alternative_names', - type: 'keyword', - description: 'Subject Alternative Names for this certificate.', - }, - { - name: 'subject', - type: 'group', - description: 'Subject represented by this certificate.', - fields: [ - { - name: 'country', - type: 'keyword', - description: 'Country code.', - }, - { - name: 'organization', - type: 'keyword', - description: 'Organization name.', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: 'Unit within organization.', - }, - { - name: 'province', - type: 'keyword', - description: 'Province or region within country.', - }, - { - name: 'common_name', - type: 'keyword', - description: 'Name or host name identified by the certificate.', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality.', - }, - ], - }, - { - name: 'issuer', - type: 'group', - description: 'Entity that issued and signed this certificate.', - fields: [ - { - name: 'country', - type: 'keyword', - description: 'Country code.', - }, - { - name: 'organization', - type: 'keyword', - description: 'Organization name.', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: 'Unit within organization.', - }, - { - name: 'province', - type: 'keyword', - description: 'Province or region within country.', - }, - { - name: 'common_name', - type: 'keyword', - description: 'Name or host name identified by the certificate.', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality.', - }, - ], - }, - ], - }, - { - name: 'server_certificate', - type: 'group', - description: 'Certificate provided by the server for authentication.', - fields: [ - { - name: 'version', - type: 'long', - description: 'X509 format version.', - }, - { - name: 'serial_number', - type: 'keyword', - description: "The certificate's serial number.", - }, - { - name: 'not_before', - type: 'date', - description: 'Date before which the certificate is not valid.', - }, - { - name: 'not_after', - type: 'date', - description: 'Date after which the certificate expires.', - }, - { - name: 'public_key_algorithm', - type: 'keyword', - description: - "The algorithm used for this certificate's public key. One of RSA, DSA or ECDSA.\n", - }, - { - name: 'public_key_size', - type: 'long', - description: 'Size of the public key.', - }, - { - name: 'signature_algorithm', - type: 'keyword', - description: "The algorithm used for the certificate's signature.\n", - }, - { - name: 'alternative_names', - type: 'keyword', - description: 'Subject Alternative Names for this certificate.', - }, - { - name: 'subject', - type: 'group', - description: 'Subject represented by this certificate.', - fields: [ - { - name: 'country', - type: 'keyword', - description: 'Country code.', - }, - { - name: 'organization', - type: 'keyword', - description: 'Organization name.', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: 'Unit within organization.', - }, - { - name: 'province', - type: 'keyword', - description: 'Province or region within country.', - }, - { - name: 'common_name', - type: 'keyword', - description: 'Name or host name identified by the certificate.', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality.', - }, - ], - }, - { - name: 'issuer', - type: 'group', - description: 'Entity that issued and signed this certificate.', - fields: [ - { - name: 'country', - type: 'keyword', - description: 'Country code.', - }, - { - name: 'organization', - type: 'keyword', - description: 'Organization name.', - }, - { - name: 'organizational_unit', - type: 'keyword', - description: 'Unit within organization.', - }, - { - name: 'province', - type: 'keyword', - description: 'Province or region within country.', - }, - { - name: 'common_name', - type: 'keyword', - description: 'Name or host name identified by the certificate.', - }, - { - name: 'locality', - type: 'keyword', - description: 'Locality.', - }, - ], - }, - ], - }, - { - name: 'server_certificate_chain', - type: 'array', - description: 'Chain of trust for the server certificate.', - }, - { - name: 'client_certificate_chain', - type: 'array', - description: 'Chain of trust for the client certificate.', - }, - { - name: 'alert_types', - type: 'keyword', - description: 'An array containing the TLS alert type for every alert received.\n', - }, - ], - }, - ], - }, - { - name: 'tls.handshake_completed', - type: 'alias', - path: 'tls.established', - }, - { - name: 'tls.client_hello.supported_ciphers', - type: 'alias', - path: 'tls.client.supported_ciphers', - }, - { - name: 'tls.server_hello.selected_cipher', - type: 'alias', - path: 'tls.cipher', - }, - { - name: 'tls.fingerprints.ja3', - type: 'alias', - path: 'tls.client.ja3', - }, - { - name: 'tls.resumption_method', - type: 'alias', - path: 'tls.detailed.resumption_method', - }, - { - name: 'tls.client_certificate_requested', - type: 'alias', - path: 'tls.detailed.client_certificate_requested', - }, - { - name: 'tls.client_hello.version', - type: 'alias', - path: 'tls.detailed.client_hello.version', - }, - { - name: 'tls.client_hello.session_id', - type: 'alias', - path: 'tls.detailed.client_hello.session_id', - }, - { - name: 'tls.client_hello.supported_compression_methods', - type: 'alias', - path: 'tls.detailed.client_hello.supported_compression_methods', - }, - { - name: 'tls.client_hello.extensions.server_name_indication', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.server_name_indication', - }, - { - name: 'tls.client_hello.extensions.application_layer_protocol_negotiation', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.application_layer_protocol_negotiation', - }, - { - name: 'tls.client_hello.extensions.session_ticket', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.session_ticket', - }, - { - name: 'tls.client_hello.extensions.supported_versions', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.supported_versions', - }, - { - name: 'tls.client_hello.extensions.supported_groups', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.supported_groups', - }, - { - name: 'tls.client_hello.extensions.signature_algorithms', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.signature_algorithms', - }, - { - name: 'tls.client_hello.extensions.ec_points_formats', - type: 'alias', - path: 'tls.detailed.client_hello.extensions.ec_points_formats', - }, - { - name: 'tls.client_hello.extensions._unparsed_', - type: 'alias', - path: 'tls.detailed.client_hello.extensions._unparsed_', - }, - { - name: 'tls.server_hello.version', - type: 'alias', - path: 'tls.detailed.server_hello.version', - }, - { - name: 'tls.server_hello.selected_compression_method', - type: 'alias', - path: 'tls.detailed.server_hello.selected_compression_method', - }, - { - name: 'tls.server_hello.session_id', - type: 'alias', - path: 'tls.detailed.server_hello.session_id', - }, - { - name: 'tls.server_hello.extensions.application_layer_protocol_negotiation', - type: 'alias', - path: 'tls.detailed.server_hello.extensions.application_layer_protocol_negotiation', - }, - { - name: 'tls.server_hello.extensions.session_ticket', - type: 'alias', - path: 'tls.detailed.server_hello.extensions.session_ticket', - }, - { - name: 'tls.server_hello.extensions.supported_versions', - type: 'alias', - path: 'tls.detailed.server_hello.extensions.supported_versions', - }, - { - name: 'tls.server_hello.extensions.ec_points_formats', - type: 'alias', - path: 'tls.detailed.server_hello.extensions.ec_points_formats', - }, - { - name: 'tls.server_hello.extensions._unparsed_', - type: 'alias', - path: 'tls.detailed.server_hello.extensions._unparsed_', - }, - { - name: 'tls.client_certificate.version', - type: 'alias', - path: 'tls.detailed.client_certificate.version', - }, - { - name: 'tls.client_certificate.serial_number', - type: 'alias', - path: 'tls.detailed.client_certificate.serial_number', - }, - { - name: 'tls.client_certificate.not_before', - type: 'alias', - path: 'tls.detailed.client_certificate.not_before', - }, - { - name: 'tls.client_certificate.not_after', - type: 'alias', - path: 'tls.detailed.client_certificate.not_after', - }, - { - name: 'tls.client_certificate.public_key_algorithm', - type: 'alias', - path: 'tls.detailed.client_certificate.public_key_algorithm', - }, - { - name: 'tls.client_certificate.public_key_size', - type: 'alias', - path: 'tls.detailed.client_certificate.public_key_size', - }, - { - name: 'tls.client_certificate.signature_algorithm', - type: 'alias', - path: 'tls.detailed.client_certificate.signature_algorithm', - }, - { - name: 'tls.client_certificate.alternative_names', - type: 'alias', - path: 'tls.detailed.client_certificate.alternative_names', - }, - { - name: 'tls.client_certificate.subject.country', - type: 'alias', - path: 'tls.detailed.client_certificate.subject.country', - }, - { - name: 'tls.client_certificate.subject.organization', - type: 'alias', - path: 'tls.detailed.client_certificate.subject.organization', - }, - { - name: 'tls.client_certificate.subject.organizational_unit', - type: 'alias', - path: 'tls.detailed.client_certificate.subject.organizational_unit', - }, - { - name: 'tls.client_certificate.subject.province', - type: 'alias', - path: 'tls.detailed.client_certificate.subject.province', - }, - { - name: 'tls.client_certificate.subject.common_name', - type: 'alias', - path: 'tls.detailed.client_certificate.subject.common_name', - }, - { - name: 'tls.client_certificate.subject.locality', - type: 'alias', - path: 'tls.detailed.client_certificate.subject.locality', - }, - { - name: 'tls.client_certificate.issuer.country', - type: 'alias', - path: 'tls.detailed.client_certificate.issuer.country', - }, - { - name: 'tls.client_certificate.issuer.organization', - type: 'alias', - path: 'tls.detailed.client_certificate.issuer.organization', - }, - { - name: 'tls.client_certificate.issuer.organizational_unit', - type: 'alias', - path: 'tls.detailed.client_certificate.issuer.organizational_unit', - }, - { - name: 'tls.client_certificate.issuer.province', - type: 'alias', - path: 'tls.detailed.client_certificate.issuer.province', - }, - { - name: 'tls.client_certificate.issuer.common_name', - type: 'alias', - path: 'tls.detailed.client_certificate.issuer.common_name', - }, - { - name: 'tls.client_certificate.issuer.locality', - type: 'alias', - path: 'tls.detailed.client_certificate.issuer.locality', - }, - { - name: 'tls.server_certificate.version', - type: 'alias', - path: 'tls.detailed.server_certificate.version', - }, - { - name: 'tls.server_certificate.serial_number', - type: 'alias', - path: 'tls.detailed.server_certificate.serial_number', - }, - { - name: 'tls.server_certificate.not_before', - type: 'alias', - path: 'tls.detailed.server_certificate.not_before', - }, - { - name: 'tls.server_certificate.not_after', - type: 'alias', - path: 'tls.detailed.server_certificate.not_after', - }, - { - name: 'tls.server_certificate.public_key_algorithm', - type: 'alias', - path: 'tls.detailed.server_certificate.public_key_algorithm', - }, - { - name: 'tls.server_certificate.public_key_size', - type: 'alias', - path: 'tls.detailed.server_certificate.public_key_size', - }, - { - name: 'tls.server_certificate.signature_algorithm', - type: 'alias', - path: 'tls.detailed.server_certificate.signature_algorithm', - }, - { - name: 'tls.server_certificate.alternative_names', - type: 'alias', - path: 'tls.detailed.server_certificate.alternative_names', - }, - { - name: 'tls.server_certificate.subject.country', - type: 'alias', - path: 'tls.detailed.server_certificate.subject.country', - }, - { - name: 'tls.server_certificate.subject.organization', - type: 'alias', - path: 'tls.detailed.server_certificate.subject.organization', - }, - { - name: 'tls.server_certificate.subject.organizational_unit', - type: 'alias', - path: 'tls.detailed.server_certificate.subject.organizational_unit', - }, - { - name: 'tls.server_certificate.subject.province', - type: 'alias', - path: 'tls.detailed.server_certificate.subject.province', - }, - { - name: 'tls.server_certificate.subject.common_name', - type: 'alias', - path: 'tls.detailed.server_certificate.subject.common_name', - }, - { - name: 'tls.server_certificate.subject.locality', - type: 'alias', - path: 'tls.detailed.server_certificate.subject.locality', - }, - { - name: 'tls.server_certificate.issuer.country', - type: 'alias', - path: 'tls.detailed.server_certificate.issuer.country', - }, - { - name: 'tls.server_certificate.issuer.organization', - type: 'alias', - path: 'tls.detailed.server_certificate.issuer.organization', - }, - { - name: 'tls.server_certificate.issuer.organizational_unit', - type: 'alias', - path: 'tls.detailed.server_certificate.issuer.organizational_unit', - }, - { - name: 'tls.server_certificate.issuer.province', - type: 'alias', - path: 'tls.detailed.server_certificate.issuer.province', - }, - { - name: 'tls.server_certificate.issuer.common_name', - type: 'alias', - path: 'tls.detailed.server_certificate.issuer.common_name', - }, - { - name: 'tls.server_certificate.issuer.locality', - type: 'alias', - path: 'tls.detailed.server_certificate.issuer.locality', - }, - { - name: 'tls.alert_types', - type: 'alias', - path: 'tls.detailed.alert_types', - }, - ], - }, -]; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/winlogbeat.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/winlogbeat.ts deleted file mode 100644 index 7457cb3f4428fd..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/8.0.0/winlogbeat.ts +++ /dev/null @@ -1,2844 +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. - */ - -/** - * An instance of the unmodified schema exported from winlogbeat-8.0.0-SNAPSHOT-windows-x86_64.zip - * - */ - -import { Schema } from '../type'; - -export const winlogbeatSchema: Schema = [ - { - key: 'ecs', - title: 'ECS', - description: 'ECS Fields.', - fields: [ - { - name: '@timestamp', - level: 'core', - required: true, - type: 'date', - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'labels', - level: 'core', - type: 'object', - object_type: 'keyword', - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: { - application: 'foo-bar', - env: 'production', - }, - }, - { - name: 'message', - level: 'core', - type: 'text', - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - }, - { - name: 'tags', - level: 'core', - type: 'keyword', - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - }, - { - name: 'agent', - title: 'Agent', - group: 2, - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - footnote: - 'Examples: In the case of Beats for logs, the agent.name is filebeat.\nFor APM, it is the agent running in the app/service. The agent information does\nnot change if data is sent through queuing systems like Kafka, Redis, or processing\nsystems such as Logstash or APM Server.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - description: 'Version of the agent.', - example: '6.0.0-rc2', - }, - ], - }, - { - name: 'client', - title: 'Client', - group: 2, - description: - 'A client is defined as the initiator of a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the client is the initiator of the TCP connection that sends\nthe SYN packet(s). For other protocols, the client is generally the initiator\nor requestor in the network transaction. Some systems use the term "originator"\nto refer the client in TCP connections. The client fields describe details about\nthe system acting as the client in the network event. Client fields are usually\npopulated in conjunction with server fields. Client fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - description: - 'Some event client addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the client to the server.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - description: 'Client domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the client.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - description: 'MAC address of the client.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the client to the server.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the client.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'cloud', - title: 'Cloud', - group: 2, - description: 'Fields related to the cloud or infrastructure the events are coming\nfrom.', - footnote: - 'Examples: If Metricbeat is running on an EC2 host and fetches data\nfrom its host, the cloud info contains the data about this machine. If Metricbeat\nruns on a remote machine outside the cloud and fetches data from a service running\nin the cloud, the field contains cloud data from the machine the service is\nrunning on.', - type: 'group', - fields: [ - { - name: 'account.id', - level: 'extended', - type: 'keyword', - description: - 'The cloud account or organization id used to identify different\nentities in a multi-tenant environment.\n\nExamples: AWS account id, Google Cloud ORG Id, or other unique identifier.', - example: 666777888999, - }, - { - name: 'availability_zone', - level: 'extended', - type: 'keyword', - description: 'Availability zone in which this host is running.', - example: 'us-east-1c', - }, - { - name: 'instance.id', - level: 'extended', - type: 'keyword', - description: 'Instance ID of the host machine.', - example: 'i-1234567890abcdef0', - }, - { - name: 'instance.name', - level: 'extended', - type: 'keyword', - description: 'Instance name of the host machine.', - }, - { - name: 'machine.type', - level: 'extended', - type: 'keyword', - description: 'Machine type of the host machine.', - example: 't2.medium', - }, - { - name: 'provider', - level: 'extended', - type: 'keyword', - description: - 'Name of the cloud provider. Example values are aws, azure, gcp,\nor digitalocean.', - example: 'aws', - }, - { - name: 'region', - level: 'extended', - type: 'keyword', - description: 'Region in which this host is running.', - example: 'us-east-1', - }, - ], - }, - { - name: 'container', - title: 'Container', - group: 2, - description: - 'Container fields are used for meta information about the specific\ncontainer that is the source of information.\n\nThese fields help correlate data based containers from any runtime.', - type: 'group', - fields: [ - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Unique container id.', - }, - { - name: 'image.name', - level: 'extended', - type: 'keyword', - description: 'Name of the image the container was built on.', - }, - { - name: 'image.tag', - level: 'extended', - type: 'keyword', - description: 'Container image tag.', - }, - { - name: 'labels', - level: 'extended', - type: 'object', - object_type: 'keyword', - description: 'Image labels.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Container name.', - }, - { - name: 'runtime', - level: 'extended', - type: 'keyword', - description: 'Runtime managing this container.', - example: 'docker', - }, - ], - }, - { - name: 'destination', - title: 'Destination', - group: 2, - description: - 'Destination fields describe details about the destination of a packet/event.\n\nDestination fields are usually populated in conjunction with source fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - description: - 'Some event destination addresses are defined ambiguously. The\nevent will sometimes list an IP, a domain or a unix socket. You should always\nstore the raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the destination to the source.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - description: 'Destination domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the destination.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - description: 'MAC address of the destination.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the destination to the source.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the destination.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'ecs', - title: 'ECS', - group: 2, - description: 'Meta-information specific to ECS.', - type: 'group', - fields: [ - { - name: 'version', - level: 'core', - required: true, - type: 'keyword', - description: - 'ECS version this event conforms to. `ecs.version` is a required\nfield and must exist in all events.\n\nWhen querying across multiple indices -- which may conform to slightly different\nECS versions -- this field lets integrations adjust to the schema version\nof the events.', - example: '1.0.0', - }, - ], - }, - { - name: 'error', - title: 'Error', - group: 2, - description: - 'These fields can represent errors of any kind.\n\nUse them for errors that happen while fetching events or in cases where the\nevent itself contains an error.', - type: 'group', - fields: [ - { - name: 'code', - level: 'core', - type: 'keyword', - description: 'Error code describing the error.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Unique identifier for the error.', - }, - { - name: 'message', - level: 'core', - type: 'text', - description: 'Error message.', - }, - ], - }, - { - name: 'event', - title: 'Event', - group: 2, - description: - 'The event fields are used for context information about the log\nor metric event itself.\n\nA log is defined as an event containing details of something that happened.\nLog events must include the time at which the thing happened. Examples of log\nevents include a process starting on a host, a network packet being sent from\na source to a destination, or a network connection between a client and a server\nbeing initiated or closed. A metric is defined as an event containing one or\nmore numerical or categorical measurements and the time at which the measurement\nwas taken. Examples of metric events include memory pressure measured on a host,\nor vulnerabilities measured on a scanned host.', - type: 'group', - fields: [ - { - name: 'action', - level: 'core', - type: 'keyword', - description: - 'The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.', - example: 'user-password-change', - }, - { - name: 'category', - level: 'core', - type: 'keyword', - description: - 'Event category.\n\nThis contains high-level information about the contents of the event. It is\nmore generic than `event.action`, in the sense that typically a category contains\nmultiple actions. Warning: In future versions of ECS, we plan to provide a\nlist of acceptable values for this field, please use with caution.', - example: 'user-management', - }, - { - name: 'created', - level: 'core', - type: 'date', - description: - 'event.created contains the date/time when the event was first\nread by an agent, or by your pipeline.\n\nThis field is distinct from @timestamp in that @timestamp typically contain\nthe time extracted from the original event.\n\nIn most situations, these two timestamps will be slightly different. The difference\ncan be used to calculate the delay between your source generating an event,\nand the time when your agent first processed it. This can be used to monitor\nyour agents or pipelines ability to keep up with your event source.\n\nIn case the two timestamps are identical, @timestamp should be used.', - }, - { - name: 'dataset', - level: 'core', - type: 'keyword', - description: - 'Name of the dataset.\n\nThe concept of a `dataset` (fileset / metricset) is used in Beats as a subset\nof modules. It contains the information which is currently stored in metricset.name\nand metricset.module or fileset.name.', - example: 'stats', - }, - { - name: 'duration', - level: 'core', - type: 'long', - format: 'duration', - input_format: 'nanoseconds', - description: - 'Duration of the event in nanoseconds.\n\nIf event.start and event.end are known this value should be the difference\nbetween the end and start time.', - }, - { - name: 'end', - level: 'extended', - type: 'date', - description: - 'event.end contains the date when the event ended or when the activity\nwas last observed.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - description: - 'Hash (perhaps logstash fingerprint) of raw field to be able to\ndemonstrate log integrity.', - example: '123456789012345678901234567890ABCD', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'Unique ID to describe the event.', - example: '8a4f500d', - }, - { - name: 'kind', - level: 'extended', - type: 'keyword', - description: - 'The kind of the event.\n\nThis gives information about what type of information the event contains,\nwithout being specific to the contents of the event. Examples are `event`,\n`state`, `alarm`. Warning: In future versions of ECS, we plan to provide a\nlist of acceptable values for this field, please use with caution.', - example: 'state', - }, - { - name: 'module', - level: 'core', - type: 'keyword', - description: - 'Name of the module this data is coming from.\n\nThis information is coming from the modules used in Beats or Logstash.', - example: 'mysql', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - description: - 'Raw text message of entire event. Used to demonstrate log integrity.\n\nThis field is not indexed and doc_values are disabled. It cannot be searched,\nbut it can be retrieved from `_source`.', - example: - 'Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100|\nworm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232', - }, - { - name: 'outcome', - level: 'extended', - type: 'keyword', - description: - 'The outcome of the event.\n\nIf the event describes an action, this fields contains the outcome of that\naction. Examples outcomes are `success` and `failure`. Warning: In future\nversions of ECS, we plan to provide a list of acceptable values for this field,\nplease use with caution.', - example: 'success', - }, - { - name: 'risk_score', - level: 'core', - type: 'float', - description: - "Risk score or priority of the event (e.g. security solutions).\nUse your system's original value here.", - }, - { - name: 'risk_score_norm', - level: 'extended', - type: 'float', - description: - 'Normalized risk score or priority of the event, on a scale of\n0 to 100.\n\nThis is mainly useful if you use more than one system that assigns risk scores,\nand you want to see a normalized value across all systems.', - }, - { - name: 'severity', - level: 'core', - type: 'long', - format: 'string', - description: - "Severity describes the original severity of the event. What the\ndifferent severity values mean can very different between use cases. It's\nup to the implementer to make sure severities are consistent across events.", - example: '7', - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: - 'event.start contains the date when the event started or when the\nactivity was first observed.', - }, - { - name: 'timezone', - level: 'extended', - type: 'keyword', - description: - 'This field should be populated when the events timestamp does\nnot include timezone information already (e.g. default Syslog timestamps).\nIts optional otherwise.\n\nAcceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"),\nabbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: - 'Reserved for future usage.\n\nPlease avoid using this field for user data.', - }, - ], - }, - { - name: 'file', - title: 'File', - group: 2, - description: - 'A file is defined as a set of information that has been created\non, or has existed on a filesystem.\n\nFile objects can be associated with host events, network events, and/or file\nevents (e.g., those produced by File Integrity Monitoring [FIM] products or\nservices). File fields provide details about the affected file associated with\nthe event or metric.', - type: 'group', - fields: [ - { - name: 'ctime', - level: 'extended', - type: 'date', - description: 'Last time file metadata changed.', - }, - { - name: 'device', - level: 'extended', - type: 'keyword', - description: 'Device that is the source of the file.', - }, - { - name: 'extension', - level: 'extended', - type: 'keyword', - description: 'File extension.\n\nThis should allow easy filtering by file extensions.', - example: 'png', - }, - { - name: 'gid', - level: 'extended', - type: 'keyword', - description: 'Primary group ID (GID) of the file.', - }, - { - name: 'group', - level: 'extended', - type: 'keyword', - description: 'Primary group name of the file.', - }, - { - name: 'inode', - level: 'extended', - type: 'keyword', - description: 'Inode representing the file in the filesystem.', - }, - { - name: 'mode', - level: 'extended', - type: 'keyword', - description: 'Mode of the file in octal representation.', - example: 416, - }, - { - name: 'mtime', - level: 'extended', - type: 'date', - description: 'Last time file content was modified.', - }, - { - name: 'owner', - level: 'extended', - type: 'keyword', - description: "File owner's username.", - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - description: 'Path to the file.', - }, - { - name: 'size', - level: 'extended', - type: 'long', - description: 'File size in bytes (field is only added when `type` is `file`).', - }, - { - name: 'target_path', - level: 'extended', - type: 'keyword', - description: 'Target path for symlinks.', - }, - { - name: 'type', - level: 'extended', - type: 'keyword', - description: 'File type (file, dir, or symlink).', - }, - { - name: 'uid', - level: 'extended', - type: 'keyword', - description: 'The user ID (UID) or security identifier (SID) of the file owner.', - }, - ], - }, - { - name: 'geo', - title: 'Geo', - group: 2, - description: - 'Geo fields can carry data about a specific location related to an\nevent.\n\nThis geolocation information can be derived from techniques such as Geo IP,\nor be user-supplied.', - type: 'group', - fields: [ - { - name: 'city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - ], - }, - { - name: 'group', - title: 'Group', - group: 2, - description: - 'The group fields are meant to represent groups that are relevant\nto the event.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - ], - }, - { - name: 'host', - title: 'Host', - group: 2, - description: - 'A host is defined as a general computing instance.\n\nECS host.* fields should be populated with details about the host on which the\nevent happened, or from which the measurement was taken. Host types include\nhardware, virtual machines, Docker containers, and Kubernetes nodes.', - type: 'group', - fields: [ - { - name: 'architecture', - level: 'core', - type: 'keyword', - description: 'Operating system architecture.', - example: 'x86_64', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - description: - 'Hostname of the host.\n\nIt normally contains what the `hostname` command returns on the host machine.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: - 'Unique host id.\n\nAs hostname is not always unique, use values that are meaningful in your environment.\n\nExample: The current usage of `beat.name`.', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'Host ip address.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - description: 'Host mac address.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: - 'Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: - 'Type of host.\n\nFor Cloud providers this can be the machine type like `t2.medium`. If vm,\nthis could be the container, for example, or other information meaningful\nin your environment.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'http', - title: 'HTTP', - group: 2, - description: - 'Fields related to HTTP activity. Use the `url` field set to store\nthe url of the request.', - type: 'group', - fields: [ - { - name: 'request.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the request body.', - example: 887, - }, - { - name: 'request.body.content', - level: 'extended', - type: 'keyword', - description: 'The full HTTP request body.', - example: 'Hello world', - }, - { - name: 'request.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the request (body and headers).', - example: 1437, - }, - { - name: 'request.method', - level: 'extended', - type: 'keyword', - description: - 'HTTP request method.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'get, post, put', - }, - { - name: 'request.referrer', - level: 'extended', - type: 'keyword', - description: 'Referrer for this HTTP request.', - example: 'https://blog.example.com/', - }, - { - name: 'response.body.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Size in bytes of the response body.', - example: 887, - }, - { - name: 'response.body.content', - level: 'extended', - type: 'keyword', - description: 'The full HTTP response body.', - example: 'Hello world', - }, - { - name: 'response.bytes', - level: 'extended', - type: 'long', - format: 'bytes', - description: 'Total size in bytes of the response (body and headers).', - example: 1437, - }, - { - name: 'response.status_code', - level: 'extended', - type: 'long', - format: 'string', - description: 'HTTP response status code.', - example: 404, - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - description: 'HTTP version.', - example: 1.1, - }, - ], - }, - { - name: 'log', - title: 'Log', - group: 2, - description: 'Fields which are specific to log events.', - type: 'group', - fields: [ - { - name: 'level', - level: 'core', - type: 'keyword', - description: - 'Original log level of the log event.\n\nSome examples are `warn`, `error`, `i`.', - example: 'err', - }, - { - name: 'original', - level: 'core', - type: 'keyword', - description: - 'This is the original log message and contains the full log message\nbefore splitting it up in multiple parts.\n\nIn contrast to the `message` field which can contain an extracted part of\nthe log message, this field contains the original, full log message. It can\nhave already some modifications applied like encoding or new lines removed\nto clean up the log message.\n\nThis field is not indexed and doc_values are disabled so it cant be queried\nbut the value can be retrieved from `_source`.', - example: 'Sep 19 08:26:10 localhost My log', - }, - ], - }, - { - name: 'network', - title: 'Network', - group: 2, - description: - 'The network is defined as the communication path over which a host\nor network event happens.\n\nThe network.* fields should be populated with details about the network activity\nassociated with an event.', - type: 'group', - fields: [ - { - name: 'application', - level: 'extended', - type: 'keyword', - description: - 'A name given to an application level protocol. This can be arbitrarily\nassigned for things like microservices, but also apply to things like skype,\nicq, facebook, twitter. This would be used in situations where the vendor\nor service can be decoded such as from the source/dest IP owners, ports, or\nwire format.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'aim', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: - 'Total bytes transferred in both directions.\n\nIf `source.bytes` and `destination.bytes` are known, `network.bytes` is their\nsum.', - example: 368, - }, - { - name: 'community_id', - level: 'extended', - type: 'keyword', - description: - 'A hash of source and destination IPs and ports, as well as the\nprotocol used in a communication. This is a tool-agnostic standard to identify\nflows.\n\nLearn more at https://github.com/corelight/community-id-spec.', - example: '1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=', - }, - { - name: 'direction', - level: 'core', - type: 'keyword', - description: - "Direction of the network traffic. Recommended values are: * inbound * outbound * internal * external * unknown When mapping events from a host-based monitoring context, populate this field from the host's point of view. When mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of your network perimeter.", - example: 'inbound', - }, - { - name: 'forwarded_ip', - level: 'core', - type: 'ip', - description: 'Host IP address when the source IP address is the proxy.', - example: '192.1.1.2', - }, - { - name: 'iana_number', - level: 'extended', - type: 'keyword', - description: - 'IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).\nStandardized list of protocols. This aligns well with NetFlow and sFlow related\nlogs which use the IANA Protocol Number.', - example: 6, - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Name given by operators to sections of their network.', - example: 'Guest Wifi', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: - 'Total packets transferred in both directions.\n\nIf `source.packets` and `destination.packets` are known, `network.packets`\nis their sum.', - example: 24, - }, - { - name: 'protocol', - level: 'core', - type: 'keyword', - description: - 'L7 Network protocol name. ex. http, lumberjack, transport protocol.\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'http', - }, - { - name: 'transport', - level: 'core', - type: 'keyword', - description: - 'Same as network.iana_number, but instead using the Keyword name\nof the transport layer (udp, tcp, ipv6-icmp, etc.)\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'tcp', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: - 'In the OSI Model this would be the Network Layer. ipv4, ipv6,\nipsec, pim, etc\n\nThe field value must be normalized to lowercase for querying. See the documentation\nsection "Implementing ECS".', - example: 'ipv4', - }, - ], - }, - { - name: 'observer', - title: 'Observer', - group: 2, - description: - 'An observer is defined as a special network, security, or application\ndevice used to detect, observe, or create network, security, or application-related\nevents and metrics.\n\nThis could be a custom hardware appliance or a server that has been configured\nto run special network, security, or application software. Examples include\nfirewalls, intrusion detection/prevention systems, network monitoring sensors,\nweb application firewalls, data loss prevention systems, and APM servers. The\nobserver.* fields shall be populated with details of the system, if any, that\ndetects, observes and/or creates a network, security, or application event or\nmetric. Message queues and ETL components used in processing events or metrics\nare not considered observers in ECS.', - type: 'group', - fields: [ - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'hostname', - level: 'core', - type: 'keyword', - description: 'Hostname of the observer.', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: 'IP address of the observer.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - description: 'MAC address of the observer', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'serial_number', - level: 'extended', - type: 'keyword', - description: 'Observer serial number.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: - 'The type of the observer the data is coming from.\n\nThere is no predefined list of observer types. Some examples are `forwarder`,\n`firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.', - example: 'firewall', - }, - { - name: 'vendor', - level: 'core', - type: 'keyword', - description: 'observer vendor information.', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - description: 'Observer version.', - }, - ], - }, - { - name: 'organization', - title: 'Organization', - group: 2, - description: - 'The organization fields enrich data with information about the company\nor entity the data is associated with.\n\nThese fields help you arrange or filter data stored in an index by one or multiple\norganizations.', - type: 'group', - fields: [ - { - name: 'id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the organization.', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Organization name.', - }, - ], - }, - { - name: 'os', - title: 'Operating System', - group: 2, - description: 'The OS fields contain information about the operating system.', - type: 'group', - fields: [ - { - name: 'family', - level: 'extended', - type: 'keyword', - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'kernel', - level: 'extended', - type: 'keyword', - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'platform', - level: 'extended', - type: 'keyword', - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - ], - }, - { - name: 'process', - title: 'Process', - group: 2, - description: - 'These fields contain information about a process.\n\nThese fields can help you correlate metrics information with a process id/name\nfrom a log message. The `process.pid` often stays in the metric itself and\nis copied to the global field for correlation.', - type: 'group', - fields: [ - { - name: 'args', - level: 'extended', - type: 'keyword', - description: - 'Array of process arguments.\n\nMay be filtered to protect sensitive information.', - example: ['ssh', '-l', 'user', '10.0.0.16'], - }, - { - name: 'executable', - level: 'extended', - type: 'keyword', - description: 'Absolute path to the process executable.', - example: '/usr/bin/ssh', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Process name.\n\nSometimes called program name or similar.', - example: 'ssh', - }, - { - name: 'pid', - level: 'core', - type: 'long', - format: 'string', - description: 'Process id.', - example: 4242, - }, - { - name: 'ppid', - level: 'extended', - type: 'long', - format: 'string', - description: "Parent process' pid.", - example: 4241, - }, - { - name: 'start', - level: 'extended', - type: 'date', - description: 'The time the process started.', - example: '2016-05-23T08:05:34.853Z', - }, - { - name: 'thread.id', - level: 'extended', - type: 'long', - format: 'string', - description: 'Thread ID.', - example: 4242, - }, - { - name: 'title', - level: 'extended', - type: 'keyword', - description: - 'Process title.\n\nThe proctitle, some times the same as process name. Can also be different:\nfor example a browser setting its title to the web page currently opened.', - }, - { - name: 'working_directory', - level: 'extended', - type: 'keyword', - description: 'The working directory of the process.', - example: '/home/alice', - }, - ], - }, - { - name: 'related', - title: 'Related', - group: 2, - description: - 'This field set is meant to facilitate pivoting around a piece of\ndata.\n\nSome pieces of information can be seen in many places in an ECS event. To facilitate\nsearching for them, store an array of all seen values to their corresponding\nfield in `related.`.\n\nA concrete example is IP addresses, which can be under host, observer, source,\ndestination, client, server, and network.forwarded_ip. If you append all IPs\nto `related.ip`, you can then search for a given IP trivially, no matter where\nit appeared, by querying `related.ip:a.b.c.d`.', - type: 'group', - fields: [ - { - name: 'ip', - level: 'extended', - type: 'ip', - description: 'All of the IPs seen on your event.', - }, - ], - }, - { - name: 'server', - title: 'Server', - group: 2, - description: - 'A Server is defined as the responder in a network connection for\nevents regarding sessions, connections, or bidirectional flow records.\n\nFor TCP events, the server is the receiver of the initial SYN packet(s) of the\nTCP connection. For other protocols, the server is generally the responder in\nthe network transaction. Some systems actually use the term "responder" to refer\nthe server in TCP connections. The server fields describe details about the\nsystem acting as the server in the network event. Server fields are usually\npopulated in conjunction with client fields. Server fields are generally not\npopulated for packet-level events.\n\nClient / server representations can add semantic context to an exchange, which\nis helpful to visualize the data in certain situations. If your context falls\nin that category, you should still ensure that source and destination are filled\nappropriately.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - description: - 'Some event server addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the server to the client.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - description: 'Server domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the server.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - description: 'MAC address of the server.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the server to the client.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the server.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'service', - title: 'Service', - group: 2, - description: - 'The service fields describe the service for or from which the data\nwas collected.\n\nThese fields help you find and correlate logs for a specific service and version.', - type: 'group', - fields: [ - { - name: 'ephemeral_id', - level: 'extended', - type: 'keyword', - description: - 'Ephemeral identifier of this service (if one exists).\n\nThis id normally changes across restarts, but `service.id` does not.', - example: '8a4f500f', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: - 'Unique identifier of the running service.\n\nThis id should uniquely identify this service. This makes it possible to correlate\nlogs and metrics for one specific service.\n\nExample: If you are experiencing issues with one redis instance, you can filter\non that id to see metrics and logs for that single instance.', - example: 'd37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: - 'Name of the service data is collected from.\n\nThe name of the service is normally user given. This allows if two instances\nof the same service are running on the same machine they can be differentiated\nby the `service.name`.\n\nAlso it allows for distributed services that run on multiple hosts to correlate\nthe related instances based on the name.\n\nIn the case of Elasticsearch the service.name could contain the cluster name.\nFor Beats the service.name is by default a copy of the `service.type` field\nif no name is specified.', - example: 'elasticsearch-metrics', - }, - { - name: 'state', - level: 'core', - type: 'keyword', - description: 'Current state of the service.', - }, - { - name: 'type', - level: 'core', - type: 'keyword', - description: - 'The type of the service data is collected from.\n\nThe type can be used to group and correlate logs and metrics from one service\ntype.\n\nExample: If logs or metrics are collected from Elasticsearch, `service.type`\nwould be `elasticsearch`.', - example: 'elasticsearch', - }, - { - name: 'version', - level: 'core', - type: 'keyword', - description: - 'Version of the service the data was collected from.\n\nThis allows to look at a data set only for a specific version of a service.', - example: '3.2.4', - }, - ], - }, - { - name: 'source', - title: 'Source', - group: 2, - description: - 'Source fields describe details about the source of a packet/event.\n\nSource fields are usually populated in conjunction with destination fields.', - type: 'group', - fields: [ - { - name: 'address', - level: 'extended', - type: 'keyword', - description: - 'Some event source addresses are defined ambiguously. The event\nwill sometimes list an IP, a domain or a unix socket. You should always store\nthe raw address in the `.address` field.\n\nThen it should be duplicated to `.ip` or `.domain`, depending on which one\nit is.', - }, - { - name: 'bytes', - level: 'core', - type: 'long', - format: 'bytes', - description: 'Bytes sent from the source to the destination.', - example: 184, - }, - { - name: 'domain', - level: 'core', - type: 'keyword', - description: 'Source domain.', - }, - { - name: 'geo.city_name', - level: 'core', - type: 'keyword', - description: 'City name.', - example: 'Montreal', - }, - { - name: 'geo.continent_name', - level: 'core', - type: 'keyword', - description: 'Name of the continent.', - example: 'North America', - }, - { - name: 'geo.country_iso_code', - level: 'core', - type: 'keyword', - description: 'Country ISO code.', - example: 'CA', - }, - { - name: 'geo.country_name', - level: 'core', - type: 'keyword', - description: 'Country name.', - example: 'Canada', - }, - { - name: 'geo.location', - level: 'core', - type: 'geo_point', - description: 'Longitude and latitude.', - example: '{ "lon": -73.614830, "lat": 45.505918 }', - }, - { - name: 'geo.name', - level: 'extended', - type: 'keyword', - description: - 'User-defined description of a location, at the level of granularity\nthey care about.\n\nCould be the name of their data centers, the floor number, if this describes\na local physical entity, city names.\n\nNot typically used in automated geolocation.', - example: 'boston-dc', - }, - { - name: 'geo.region_iso_code', - level: 'core', - type: 'keyword', - description: 'Region ISO code.', - example: 'CA-QC', - }, - { - name: 'geo.region_name', - level: 'core', - type: 'keyword', - description: 'Region name.', - example: 'Quebec', - }, - { - name: 'ip', - level: 'core', - type: 'ip', - description: - 'IP address of the source.\n\nCan be one or multiple IPv4 or IPv6 addresses.', - }, - { - name: 'mac', - level: 'core', - type: 'keyword', - description: 'MAC address of the source.', - }, - { - name: 'packets', - level: 'core', - type: 'long', - description: 'Packets sent from the source to the destination.', - example: 12, - }, - { - name: 'port', - level: 'core', - type: 'long', - format: 'string', - description: 'Port of the source.', - }, - { - name: 'user.email', - level: 'extended', - type: 'keyword', - description: 'User email address.', - }, - { - name: 'user.full_name', - level: 'extended', - type: 'keyword', - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'user.group.id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'user.group.name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - { - name: 'user.hash', - level: 'extended', - type: 'keyword', - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'user.id', - level: 'core', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.', - }, - { - name: 'user.name', - level: 'core', - type: 'keyword', - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'url', - title: 'URL', - group: 2, - description: - 'URL fields provide support for complete or partial URLs, and supports\nthe breaking down into scheme, domain, path, and so on.', - type: 'group', - fields: [ - { - name: 'domain', - level: 'extended', - type: 'keyword', - description: - 'Domain of the url, such as "www.elastic.co".\n\nIn some cases a URL may refer to an IP and/or port directly, without a domain\nname. In this case, the IP address would go to the `domain` field.', - example: 'www.elastic.co', - }, - { - name: 'fragment', - level: 'extended', - type: 'keyword', - description: - 'Portion of the url after the `#`, such as "top".\n\nThe `#` is not part of the fragment.', - }, - { - name: 'full', - level: 'extended', - type: 'keyword', - description: - 'If full URLs are important to your use case, they should be stored\nin `url.full`, whether this field is reconstructed or present in the event\nsource.', - example: 'https://www.elastic.co:443/search?q=elasticsearch#top', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - description: - 'Unmodified original url as seen in the event source.\n\nNote that in network monitoring, the observed URL may be a full URL, whereas\nin access logs, the URL is often just represented as a path.\n\nThis field is meant to represent the URL as it was observed, complete or not.', - example: - 'https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch', - }, - { - name: 'password', - level: 'extended', - type: 'keyword', - description: 'Password of the request.', - }, - { - name: 'path', - level: 'extended', - type: 'keyword', - description: 'Path of the request, such as "/search".', - }, - { - name: 'port', - level: 'extended', - type: 'long', - format: 'string', - description: 'Port of the request, such as 443.', - example: 443, - }, - { - name: 'query', - level: 'extended', - type: 'keyword', - description: - 'The query field describes the query string of the request, such\nas "q=elasticsearch".\n\nThe `?` is excluded from the query string. If a URL contains no `?`, there\nis no query field. If there is a `?` but no query, the query field exists\nwith an empty string. The `exists` query can be used to differentiate between\nthe two cases.', - }, - { - name: 'scheme', - level: 'extended', - type: 'keyword', - description: - 'Scheme of the request, such as "https".\n\nNote: The `:` is not part of the scheme.', - example: 'https', - }, - { - name: 'username', - level: 'extended', - type: 'keyword', - description: 'Username of the request.', - }, - ], - }, - { - name: 'user', - title: 'User', - group: 2, - description: - 'The user fields describe information about the user that is relevant\nto the event.\n\nFields can have one entry or multiple entries. If a user has more than one id,\nprovide an array that includes all of them.', - type: 'group', - fields: [ - { - name: 'email', - level: 'extended', - type: 'keyword', - description: 'User email address.', - }, - { - name: 'full_name', - level: 'extended', - type: 'keyword', - description: "User's full name, if available.", - example: 'Albert Einstein', - }, - { - name: 'group.id', - level: 'extended', - type: 'keyword', - description: 'Unique identifier for the group on the system/platform.', - }, - { - name: 'group.name', - level: 'extended', - type: 'keyword', - description: 'Name of the group.', - }, - { - name: 'hash', - level: 'extended', - type: 'keyword', - description: - 'Unique user hash to correlate information for a user in anonymized\nform.\n\nUseful if `user.id` or `user.name` contain confidential information and cannot\nbe used.', - }, - { - name: 'id', - level: 'core', - type: 'keyword', - description: 'One or multiple unique identifiers of the user.', - }, - { - name: 'name', - level: 'core', - type: 'keyword', - description: 'Short name or login of the user.', - example: 'albert', - }, - ], - }, - { - name: 'user_agent', - title: 'User agent', - group: 2, - description: - 'The user_agent fields normally come from a browser request.\n\nThey often show up in web service logs coming from the parsed user agent string.', - type: 'group', - fields: [ - { - name: 'device.name', - level: 'extended', - type: 'keyword', - description: 'Name of the device.', - example: 'iPhone', - }, - { - name: 'name', - level: 'extended', - type: 'keyword', - description: 'Name of the user agent.', - example: 'Safari', - }, - { - name: 'original', - level: 'extended', - type: 'keyword', - description: 'Unparsed version of the user_agent.', - example: - 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15\n(KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', - }, - { - name: 'os.family', - level: 'extended', - type: 'keyword', - description: 'OS family (such as redhat, debian, freebsd, windows).', - example: 'debian', - }, - { - name: 'os.full', - level: 'extended', - type: 'keyword', - description: 'Operating system name, including the version or code name.', - example: 'Mac OS Mojave', - }, - { - name: 'os.kernel', - level: 'extended', - type: 'keyword', - description: 'Operating system kernel version as a raw string.', - example: '4.4.0-112-generic', - }, - { - name: 'os.name', - level: 'extended', - type: 'keyword', - description: 'Operating system name, without the version.', - example: 'Mac OS X', - }, - { - name: 'os.platform', - level: 'extended', - type: 'keyword', - description: 'Operating system platform (such centos, ubuntu, windows).', - example: 'darwin', - }, - { - name: 'os.version', - level: 'extended', - type: 'keyword', - description: 'Operating system version as a raw string.', - example: '10.14.1', - }, - { - name: 'version', - level: 'extended', - type: 'keyword', - description: 'Version of the user agent.', - example: 12, - }, - ], - }, - ], - }, - { - key: 'beat', - title: 'Beat', - description: 'Contains common beat fields available in all event types.\n', - fields: [ - { - name: 'agent.hostname', - type: 'keyword', - description: 'Hostname of the agent.', - }, - { - name: 'beat.timezone', - type: 'alias', - path: 'event.timezone', - migration: true, - }, - { - name: 'fields', - type: 'object', - object_type: 'keyword', - description: 'Contains user configurable fields.\n', - }, - { - name: 'error', - type: 'group', - description: 'Error fields containing additional info in case of errors.\n', - fields: [ - { - name: 'type', - type: 'keyword', - description: 'Error type.\n', - }, - ], - }, - { - name: 'beat.name', - type: 'alias', - path: 'host.name', - migration: true, - }, - { - name: 'beat.hostname', - type: 'alias', - path: 'agent.hostname', - migration: true, - }, - { - name: 'timeseries.instance', - type: 'keyword', - description: 'Time series instance id', - }, - ], - }, - { - key: 'cloud', - title: 'Cloud provider metadata', - description: 'Metadata from cloud providers added by the add_cloud_metadata processor.\n', - fields: [ - { - name: 'cloud.project.id', - example: 'project-x', - description: 'Name of the project in Google Cloud.\n', - }, - { - name: 'meta.cloud.provider', - type: 'alias', - path: 'cloud.provider', - migration: true, - }, - { - name: 'meta.cloud.instance_id', - type: 'alias', - path: 'cloud.instance.id', - migration: true, - }, - { - name: 'meta.cloud.instance_name', - type: 'alias', - path: 'cloud.instance.name', - migration: true, - }, - { - name: 'meta.cloud.machine_type', - type: 'alias', - path: 'cloud.machine.type', - migration: true, - }, - { - name: 'meta.cloud.availability_zone', - type: 'alias', - path: 'cloud.availability_zone', - migration: true, - }, - { - name: 'meta.cloud.project_id', - type: 'alias', - path: 'cloud.project.id', - migration: true, - }, - { - name: 'meta.cloud.region', - type: 'alias', - path: 'cloud.region', - migration: true, - }, - ], - }, - { - key: 'docker', - title: 'Docker', - description: 'Docker stats collected from Docker.\n', - short_config: false, - anchor: 'docker-processor', - fields: [ - { - name: 'docker', - type: 'group', - fields: [ - { - name: 'container.id', - type: 'alias', - path: 'container.id', - migration: true, - }, - { - name: 'container.image', - type: 'alias', - path: 'container.image.name', - migration: true, - }, - { - name: 'container.name', - type: 'alias', - path: 'container.name', - migration: true, - }, - { - name: 'container.labels', - type: 'object', - object_type: 'keyword', - description: 'Image labels.\n', - }, - ], - }, - ], - }, - { - key: 'host', - title: 'Host', - description: 'Info collected for the host machine.\n', - anchor: 'host-processor', - fields: [ - { - name: 'host', - type: 'group', - fields: [ - { - name: 'containerized', - type: 'boolean', - description: 'If the host is a container.\n', - }, - { - name: 'os.build', - type: 'keyword', - example: '18D109', - description: 'OS build information.\n', - }, - { - name: 'os.codename', - type: 'keyword', - example: 'stretch', - description: 'OS codename, if any.\n', - }, - ], - }, - ], - }, - { - key: 'kubernetes', - title: 'Kubernetes', - description: 'Kubernetes metadata added by the kubernetes processor\n', - short_config: false, - anchor: 'kubernetes-processor', - fields: [ - { - name: 'kubernetes', - type: 'group', - fields: [ - { - name: 'pod.name', - type: 'keyword', - description: 'Kubernetes pod name\n', - }, - { - name: 'pod.uid', - type: 'keyword', - description: 'Kubernetes Pod UID\n', - }, - { - name: 'namespace', - type: 'keyword', - description: 'Kubernetes namespace\n', - }, - { - name: 'node.name', - type: 'keyword', - description: 'Kubernetes node name\n', - }, - { - name: 'labels', - type: 'object', - description: 'Kubernetes labels map\n', - }, - { - name: 'annotations', - type: 'object', - description: 'Kubernetes annotations map\n', - }, - { - name: 'replicaset.name', - type: 'keyword', - description: 'Kubernetes replicaset name\n', - }, - { - name: 'deployment.name', - type: 'keyword', - description: 'Kubernetes deployment name\n', - }, - { - name: 'statefulset.name', - type: 'keyword', - description: 'Kubernetes statefulset name\n', - }, - { - name: 'container.name', - type: 'keyword', - description: 'Kubernetes container name\n', - }, - { - name: 'container.image', - type: 'keyword', - description: 'Kubernetes container image\n', - }, - ], - }, - ], - }, - { - key: 'process', - title: 'Process', - description: 'Process metadata fields\n', - fields: [ - { - name: 'process', - type: 'group', - fields: [ - { - name: 'exe', - type: 'alias', - path: 'process.executable', - migration: true, - }, - ], - }, - ], - }, - { - key: 'jolokia-autodiscover', - title: 'Jolokia Discovery autodiscover provider', - description: 'Metadata from Jolokia Discovery added by the jolokia provider.\n', - fields: [ - { - name: 'jolokia.agent.version', - type: 'keyword', - description: 'Version number of jolokia agent.\n', - }, - { - name: 'jolokia.agent.id', - type: 'keyword', - description: - 'Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type.\n', - }, - { - name: 'jolokia.server.product', - type: 'keyword', - description: 'The container product if detected.\n', - }, - { - name: 'jolokia.server.version', - type: 'keyword', - description: "The container's version (if detected).\n", - }, - { - name: 'jolokia.server.vendor', - type: 'keyword', - description: 'The vendor of the container the agent is running in.\n', - }, - { - name: 'jolokia.url', - type: 'keyword', - description: 'The URL how this agent can be contacted.\n', - }, - { - name: 'jolokia.secured', - type: 'boolean', - description: 'Whether the agent was configured for authentication or not.\n', - }, - ], - }, - { - key: 'winlog', - title: 'Windows Event Log fields emitted by Winlogbeat', - description: 'Fields from the Windows Event Log.\n', - fields: [ - { - name: 'log.file.path', - type: 'keyword', - required: false, - description: - 'The name of the file the event was read from when Winlogbeat is reading directly from an .evtx file.\n', - }, - { - name: 'event.code', - type: 'keyword', - required: false, - description: 'The code for this log message (Windows event ID).\n', - }, - { - name: 'event.original', - description: - 'The raw XML representation of the event obtained from Windows. This field is only available on operating systems supporting the Windows Event Log API (Microsoft Windows Vista and newer). This field is not included by default and must be enabled by setting `include_xml: true` as a configuration option for an individual event log.\nThe XML representation of the event is useful for troubleshooting purposes. The data in the fields reported by Winlogbeat can be compared to the data in the XML to diagnose problems.\n', - }, - { - name: 'winlog', - type: 'group', - description: 'All fields specific to the Windows Event Log are defined here.\n', - fields: [ - { - name: 'api', - required: true, - description: - 'The event log API type used to read the record. The possible values are "wineventlog" for the Windows Event Log API or "eventlogging" for the Event Logging API.\nThe Event Logging API was designed for Windows Server 2003 or Windows 2000 operating systems. In Windows Vista, the event logging infrastructure was redesigned. On Windows Vista or later operating systems, the Windows Event Log API is used. Winlogbeat automatically detects which API to use for reading event logs.\n', - }, - { - name: 'activity_id', - type: 'keyword', - required: false, - description: - 'A globally unique identifier that identifies the current activity. The events that are published with this identifier are part of the same activity.\n', - }, - { - name: 'computer_name', - type: 'keyword', - required: true, - description: - 'The name of the computer that generated the record. When using Windows event forwarding, this name can differ from `agent.hostname`.\n', - }, - { - name: 'event_data', - type: 'object', - object_type: 'keyword', - required: false, - description: - 'The event-specific data. This field is mutually exclusive with `user_data`. If you are capturing event data on versions prior to Windows Vista, the parameters in `event_data` are named `param1`, `param2`, and so on, because event log parameters are unnamed in earlier versions of Windows.\n', - }, - { - name: 'event_id', - type: 'keyword', - required: true, - description: - 'The event identifier. The value is specific to the source of the event.\n', - }, - { - name: 'keywords', - type: 'keyword', - required: false, - description: 'The keywords are used to classify an event.\n', - }, - { - name: 'channel', - type: 'keyword', - required: true, - description: - 'The name of the channel from which this record was read. This value is one of the names from the `event_logs` collection in the configuration.\n', - }, - { - name: 'record_id', - type: 'keyword', - required: true, - description: - 'The record ID of the event log record. The first record written to an event log is record number 1, and other records are numbered sequentially. If the record number reaches the maximum value (2^32^ for the Event Logging API and 2^64^ for the Windows Event Log API), the next record number will be 0.\n', - }, - { - name: 'related_activity_id', - type: 'keyword', - required: false, - description: - 'A globally unique identifier that identifies the activity to which control was transferred to. The related events would then have this identifier as their `activity_id` identifier.\n', - }, - { - name: 'opcode', - type: 'keyword', - required: false, - description: - 'The opcode defined in the event. Task and opcode are typically used to identify the location in the application from where the event was logged.\n', - }, - { - name: 'provider_guid', - type: 'keyword', - required: false, - description: - 'A globally unique identifier that identifies the provider that logged the event.\n', - }, - { - name: 'process.pid', - type: 'long', - required: false, - description: 'The process_id of the Client Server Runtime Process.\n', - }, - { - name: 'provider_name', - type: 'keyword', - required: true, - description: - 'The source of the event log record (the application or service that logged the record).\n', - }, - { - name: 'task', - type: 'keyword', - required: false, - description: - 'The task defined in the event. Task and opcode are typically used to identify the location in the application from where the event was logged. The category used by the Event Logging API (on pre Windows Vista operating systems) is written to this field.\n', - }, - { - name: 'process.thread.id', - type: 'long', - required: false, - }, - { - name: 'user_data', - type: 'object', - object_type: 'keyword', - required: false, - description: - 'The event specific data. This field is mutually exclusive with `event_data`.\n', - }, - { - name: 'user.identifier', - type: 'keyword', - required: false, - example: 'S-1-5-21-3541430928-2051711210-1391384369-1001', - description: - 'The Windows security identifier (SID) of the account associated with this event.\n\nIf Winlogbeat cannot resolve the SID to a name, then the `user.name`, `user.domain`, and `user.type` fields will be omitted from the event. If you discover Winlogbeat not resolving SIDs, review the log for clues as to what the problem may be.\n', - }, - { - name: 'user.domain', - type: 'keyword', - required: false, - description: 'The domain that the account associated with this event is a member of.\n', - }, - { - name: 'user.type', - type: 'keyword', - required: false, - description: 'The type of account associated with this event.\n', - }, - { - name: 'version', - type: 'long', - required: false, - description: "The version number of the event's definition.", - }, - ], - }, - ], - }, - { - key: 'eventlog', - title: 'Event log record', - description: 'Contains data from a Windows event log record.\n', - fields: [ - { - name: 'type', - type: 'alias', - path: 'winlog.api', - migration: true, - }, - { - name: 'activity_id', - type: 'alias', - path: 'winlog.activity_id', - migration: true, - }, - { - name: 'computer_name', - type: 'alias', - path: 'winlog.computer_name', - migration: true, - }, - { - name: 'event_id', - type: 'alias', - path: 'winlog.event_id', - migration: true, - }, - { - name: 'keywords', - type: 'alias', - path: 'winlog.keywords', - migration: true, - }, - { - name: 'log_name', - type: 'alias', - path: 'winlog.channel', - migration: true, - }, - { - name: 'message_error', - type: 'alias', - path: 'error.message', - migration: true, - }, - { - name: 'record_number', - type: 'alias', - path: 'winlog.record_id', - migration: true, - }, - { - name: 'related_activity_id', - type: 'alias', - path: 'winlog.related_activity_id', - migration: true, - }, - { - name: 'opcode', - type: 'alias', - path: 'winlog.opcode', - migration: true, - }, - { - name: 'provider_guid', - type: 'alias', - path: 'winlog.provider_guid', - migration: true, - }, - { - name: 'process_id', - type: 'alias', - path: 'winlog.process.pid', - migration: true, - }, - { - name: 'source_name', - type: 'alias', - path: 'winlog.provider_name', - migration: true, - }, - { - name: 'task', - type: 'alias', - path: 'winlog.task', - migration: true, - }, - { - name: 'thread_id', - type: 'alias', - path: 'winlog.process.thread.id', - migration: true, - }, - { - name: 'user.identifier', - type: 'alias', - path: 'winlog.user.identifier', - migration: true, - }, - { - name: 'user.domain', - type: 'alias', - path: 'winlog.user.domain', - migration: true, - }, - { - name: 'user.type', - type: 'alias', - path: 'winlog.user.type', - migration: true, - }, - { - name: 'version', - type: 'alias', - path: 'winlog.version', - migration: true, - }, - { - name: 'xml', - type: 'alias', - path: 'event.original', - migration: true, - }, - ], - }, -]; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/fields.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/fields.ts new file mode 100644 index 00000000000000..e61b9ae008a623 --- /dev/null +++ b/x-pack/plugins/security_solution/server/utils/beat_schema/fields.ts @@ -0,0 +1,36118 @@ +/* + * 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 { BeatFields } from '../../../common/search_strategy/index_fields'; + +/* eslint-disable @typescript-eslint/naming-convention */ +export const fieldsBeat: BeatFields = { + _id: { + category: 'base', + description: 'Each document has an _id that uniquely identifies it', + example: 'Y-6TfmcB0WOhS6qyMv3s', + name: '_id', + type: 'keyword', + }, + _index: { + category: 'base', + description: + 'An index is like a ‘database’ in a relational database. It has a mapping which defines multiple types. An index is a logical namespace which maps to one or more primary shards and can have zero or more replica shards.', + example: 'auditbeat-8.0.0-2019.02.19-000001', + name: '_index', + type: 'keyword', + }, + '@timestamp': { + category: 'base', + description: + 'Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events.', + example: '2016-05-23T08:05:34.853Z', + name: '@timestamp', + type: 'date', + }, + labels: { + category: 'base', + description: + 'Custom key/value pairs. Can be used to add meta information to events. Should not contain nested objects. All values are stored as keyword. Example: `docker` and `k8s` labels.', + example: '{"application": "foo-bar", "env": "production"}', + name: 'labels', + type: 'object', + }, + message: { + category: 'base', + description: + 'For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message.', + example: 'Hello World', + name: 'message', + type: 'text', + }, + tags: { + category: 'base', + description: 'List of keywords used to tag each event.', + example: '["production", "env2"]', + name: 'tags', + type: 'keyword', + }, + 'agent.ephemeral_id': { + category: 'agent', + description: + 'Ephemeral identifier of this agent (if one exists). This id normally changes across restarts, but `agent.id` does not.', + example: '8a4f500f', + name: 'agent.ephemeral_id', + type: 'keyword', + }, + 'agent.id': { + category: 'agent', + description: + 'Unique identifier of this agent (if one exists). Example: For Beats this would be beat.id.', + example: '8a4f500d', + name: 'agent.id', + type: 'keyword', + }, + 'agent.name': { + category: 'agent', + description: + 'Custom name of the agent. This is a name that can be given to an agent. This can be helpful if for example two Filebeat instances are running on the same host but a human readable separation is needed on which Filebeat instance data is coming from. If no name is given, the name is often left empty.', + example: 'foo', + name: 'agent.name', + type: 'keyword', + }, + 'agent.type': { + category: 'agent', + description: + 'Type of the agent. The agent type stays always the same and should be given by the agent used. In case of Filebeat the agent would always be Filebeat also if two Filebeat instances are run on the same machine.', + example: 'filebeat', + name: 'agent.type', + type: 'keyword', + }, + 'agent.version': { + category: 'agent', + description: 'Version of the agent.', + example: '6.0.0-rc2', + name: 'agent.version', + type: 'keyword', + }, + 'as.number': { + category: 'as', + description: + 'Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet.', + example: 15169, + name: 'as.number', + type: 'long', + }, + 'as.organization.name': { + category: 'as', + description: 'Organization name.', + example: 'Google LLC', + name: 'as.organization.name', + type: 'keyword', + }, + 'client.address': { + category: 'client', + description: + 'Some event client addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', + name: 'client.address', + type: 'keyword', + }, + 'client.as.number': { + category: 'client', + description: + 'Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet.', + example: 15169, + name: 'client.as.number', + type: 'long', + }, + 'client.as.organization.name': { + category: 'client', + description: 'Organization name.', + example: 'Google LLC', + name: 'client.as.organization.name', + type: 'keyword', + }, + 'client.bytes': { + category: 'client', + description: 'Bytes sent from the client to the server.', + example: 184, + name: 'client.bytes', + type: 'long', + format: 'bytes', + }, + 'client.domain': { + category: 'client', + description: 'Client domain.', + name: 'client.domain', + type: 'keyword', + }, + 'client.geo.city_name': { + category: 'client', + description: 'City name.', + example: 'Montreal', + name: 'client.geo.city_name', + type: 'keyword', + }, + 'client.geo.continent_name': { + category: 'client', + description: 'Name of the continent.', + example: 'North America', + name: 'client.geo.continent_name', + type: 'keyword', + }, + 'client.geo.country_iso_code': { + category: 'client', + description: 'Country ISO code.', + example: 'CA', + name: 'client.geo.country_iso_code', + type: 'keyword', + }, + 'client.geo.country_name': { + category: 'client', + description: 'Country name.', + example: 'Canada', + name: 'client.geo.country_name', + type: 'keyword', + }, + 'client.geo.location': { + category: 'client', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'client.geo.location', + type: 'geo_point', + }, + 'client.geo.name': { + category: 'client', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'client.geo.name', + type: 'keyword', + }, + 'client.geo.region_iso_code': { + category: 'client', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'client.geo.region_iso_code', + type: 'keyword', + }, + 'client.geo.region_name': { + category: 'client', + description: 'Region name.', + example: 'Quebec', + name: 'client.geo.region_name', + type: 'keyword', + }, + 'client.ip': { + category: 'client', + description: 'IP address of the client. Can be one or multiple IPv4 or IPv6 addresses.', + name: 'client.ip', + type: 'ip', + }, + 'client.mac': { + category: 'client', + description: 'MAC address of the client.', + name: 'client.mac', + type: 'keyword', + }, + 'client.nat.ip': { + category: 'client', + description: + 'Translated IP of source based NAT sessions (e.g. internal client to internet). Typically connections traversing load balancers, firewalls, or routers.', + name: 'client.nat.ip', + type: 'ip', + }, + 'client.nat.port': { + category: 'client', + description: + 'Translated port of source based NAT sessions (e.g. internal client to internet). Typically connections traversing load balancers, firewalls, or routers.', + name: 'client.nat.port', + type: 'long', + format: 'string', + }, + 'client.packets': { + category: 'client', + description: 'Packets sent from the client to the server.', + example: 12, + name: 'client.packets', + type: 'long', + }, + 'client.port': { + category: 'client', + description: 'Port of the client.', + name: 'client.port', + type: 'long', + format: 'string', + }, + 'client.registered_domain': { + category: 'client', + description: + 'The highest registered client domain, stripped of the subdomain. For example, the registered domain for "foo.google.com" is "google.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk".', + example: 'google.com', + name: 'client.registered_domain', + type: 'keyword', + }, + 'client.top_level_domain': { + category: 'client', + description: + 'The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for google.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk".', + example: 'co.uk', + name: 'client.top_level_domain', + type: 'keyword', + }, + 'client.user.domain': { + category: 'client', + description: + 'Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name.', + name: 'client.user.domain', + type: 'keyword', + }, + 'client.user.email': { + category: 'client', + description: 'User email address.', + name: 'client.user.email', + type: 'keyword', + }, + 'client.user.full_name': { + category: 'client', + description: "User's full name, if available.", + example: 'Albert Einstein', + name: 'client.user.full_name', + type: 'keyword', + }, + 'client.user.group.domain': { + category: 'client', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'client.user.group.domain', + type: 'keyword', + }, + 'client.user.group.id': { + category: 'client', + description: 'Unique identifier for the group on the system/platform.', + name: 'client.user.group.id', + type: 'keyword', + }, + 'client.user.group.name': { + category: 'client', + description: 'Name of the group.', + name: 'client.user.group.name', + type: 'keyword', + }, + 'client.user.hash': { + category: 'client', + description: + 'Unique user hash to correlate information for a user in anonymized form. Useful if `user.id` or `user.name` contain confidential information and cannot be used.', + name: 'client.user.hash', + type: 'keyword', + }, + 'client.user.id': { + category: 'client', + description: 'Unique identifiers of the user.', + name: 'client.user.id', + type: 'keyword', + }, + 'client.user.name': { + category: 'client', + description: 'Short name or login of the user.', + example: 'albert', + name: 'client.user.name', + type: 'keyword', + }, + 'cloud.account.id': { + category: 'cloud', + description: + 'The cloud account or organization id used to identify different entities in a multi-tenant environment. Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.', + example: 666777888999, + name: 'cloud.account.id', + type: 'keyword', + }, + 'cloud.availability_zone': { + category: 'cloud', + description: 'Availability zone in which this host is running.', + example: 'us-east-1c', + name: 'cloud.availability_zone', + type: 'keyword', + }, + 'cloud.instance.id': { + category: 'cloud', + description: 'Instance ID of the host machine.', + example: 'i-1234567890abcdef0', + name: 'cloud.instance.id', + type: 'keyword', + }, + 'cloud.instance.name': { + category: 'cloud', + description: 'Instance name of the host machine.', + name: 'cloud.instance.name', + type: 'keyword', + }, + 'cloud.machine.type': { + category: 'cloud', + description: 'Machine type of the host machine.', + example: 't2.medium', + name: 'cloud.machine.type', + type: 'keyword', + }, + 'cloud.provider': { + category: 'cloud', + description: 'Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean.', + example: 'aws', + name: 'cloud.provider', + type: 'keyword', + }, + 'cloud.region': { + category: 'cloud', + description: 'Region in which this host is running.', + example: 'us-east-1', + name: 'cloud.region', + type: 'keyword', + }, + 'code_signature.exists': { + category: 'code_signature', + description: 'Boolean to capture if a signature is present.', + example: 'true', + name: 'code_signature.exists', + type: 'boolean', + }, + 'code_signature.status': { + category: 'code_signature', + description: + 'Additional information about the certificate status. This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked.', + example: 'ERROR_UNTRUSTED_ROOT', + name: 'code_signature.status', + type: 'keyword', + }, + 'code_signature.subject_name': { + category: 'code_signature', + description: 'Subject name of the code signer', + example: 'Microsoft Corporation', + name: 'code_signature.subject_name', + type: 'keyword', + }, + 'code_signature.trusted': { + category: 'code_signature', + description: + 'Stores the trust status of the certificate chain. Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status.', + example: 'true', + name: 'code_signature.trusted', + type: 'boolean', + }, + 'code_signature.valid': { + category: 'code_signature', + description: + 'Boolean to capture if the digital signature is verified against the binary content. Leave unpopulated if a certificate was unchecked.', + example: 'true', + name: 'code_signature.valid', + type: 'boolean', + }, + 'container.id': { + category: 'container', + description: 'Unique container id.', + name: 'container.id', + type: 'keyword', + }, + 'container.image.name': { + category: 'container', + description: 'Name of the image the container was built on.', + name: 'container.image.name', + type: 'keyword', + }, + 'container.image.tag': { + category: 'container', + description: 'Container image tags.', + name: 'container.image.tag', + type: 'keyword', + }, + 'container.labels': { + category: 'container', + description: 'Image labels.', + name: 'container.labels', + type: 'object', + }, + 'container.name': { + category: 'container', + description: 'Container name.', + name: 'container.name', + type: 'keyword', + }, + 'container.runtime': { + category: 'container', + description: 'Runtime managing this container.', + example: 'docker', + name: 'container.runtime', + type: 'keyword', + }, + 'destination.address': { + category: 'destination', + description: + 'Some event destination addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', + name: 'destination.address', + type: 'keyword', + }, + 'destination.as.number': { + category: 'destination', + description: + 'Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet.', + example: 15169, + name: 'destination.as.number', + type: 'long', + }, + 'destination.as.organization.name': { + category: 'destination', + description: 'Organization name.', + example: 'Google LLC', + name: 'destination.as.organization.name', + type: 'keyword', + }, + 'destination.bytes': { + category: 'destination', + description: 'Bytes sent from the destination to the source.', + example: 184, + name: 'destination.bytes', + type: 'long', + format: 'bytes', + }, + 'destination.domain': { + category: 'destination', + description: 'Destination domain.', + name: 'destination.domain', + type: 'keyword', + }, + 'destination.geo.city_name': { + category: 'destination', + description: 'City name.', + example: 'Montreal', + name: 'destination.geo.city_name', + type: 'keyword', + }, + 'destination.geo.continent_name': { + category: 'destination', + description: 'Name of the continent.', + example: 'North America', + name: 'destination.geo.continent_name', + type: 'keyword', + }, + 'destination.geo.country_iso_code': { + category: 'destination', + description: 'Country ISO code.', + example: 'CA', + name: 'destination.geo.country_iso_code', + type: 'keyword', + }, + 'destination.geo.country_name': { + category: 'destination', + description: 'Country name.', + example: 'Canada', + name: 'destination.geo.country_name', + type: 'keyword', + }, + 'destination.geo.location': { + category: 'destination', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'destination.geo.location', + type: 'geo_point', + }, + 'destination.geo.name': { + category: 'destination', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'destination.geo.name', + type: 'keyword', + }, + 'destination.geo.region_iso_code': { + category: 'destination', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'destination.geo.region_iso_code', + type: 'keyword', + }, + 'destination.geo.region_name': { + category: 'destination', + description: 'Region name.', + example: 'Quebec', + name: 'destination.geo.region_name', + type: 'keyword', + }, + 'destination.ip': { + category: 'destination', + description: 'IP address of the destination. Can be one or multiple IPv4 or IPv6 addresses.', + name: 'destination.ip', + type: 'ip', + }, + 'destination.mac': { + category: 'destination', + description: 'MAC address of the destination.', + name: 'destination.mac', + type: 'keyword', + }, + 'destination.nat.ip': { + category: 'destination', + description: + 'Translated ip of destination based NAT sessions (e.g. internet to private DMZ) Typically used with load balancers, firewalls, or routers.', + name: 'destination.nat.ip', + type: 'ip', + }, + 'destination.nat.port': { + category: 'destination', + description: + 'Port the source session is translated to by NAT Device. Typically used with load balancers, firewalls, or routers.', + name: 'destination.nat.port', + type: 'long', + format: 'string', + }, + 'destination.packets': { + category: 'destination', + description: 'Packets sent from the destination to the source.', + example: 12, + name: 'destination.packets', + type: 'long', + }, + 'destination.port': { + category: 'destination', + description: 'Port of the destination.', + name: 'destination.port', + type: 'long', + format: 'string', + }, + 'destination.registered_domain': { + category: 'destination', + description: + 'The highest registered destination domain, stripped of the subdomain. For example, the registered domain for "foo.google.com" is "google.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk".', + example: 'google.com', + name: 'destination.registered_domain', + type: 'keyword', + }, + 'destination.top_level_domain': { + category: 'destination', + description: + 'The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for google.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk".', + example: 'co.uk', + name: 'destination.top_level_domain', + type: 'keyword', + }, + 'destination.user.domain': { + category: 'destination', + description: + 'Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name.', + name: 'destination.user.domain', + type: 'keyword', + }, + 'destination.user.email': { + category: 'destination', + description: 'User email address.', + name: 'destination.user.email', + type: 'keyword', + }, + 'destination.user.full_name': { + category: 'destination', + description: "User's full name, if available.", + example: 'Albert Einstein', + name: 'destination.user.full_name', + type: 'keyword', + }, + 'destination.user.group.domain': { + category: 'destination', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'destination.user.group.domain', + type: 'keyword', + }, + 'destination.user.group.id': { + category: 'destination', + description: 'Unique identifier for the group on the system/platform.', + name: 'destination.user.group.id', + type: 'keyword', + }, + 'destination.user.group.name': { + category: 'destination', + description: 'Name of the group.', + name: 'destination.user.group.name', + type: 'keyword', + }, + 'destination.user.hash': { + category: 'destination', + description: + 'Unique user hash to correlate information for a user in anonymized form. Useful if `user.id` or `user.name` contain confidential information and cannot be used.', + name: 'destination.user.hash', + type: 'keyword', + }, + 'destination.user.id': { + category: 'destination', + description: 'Unique identifiers of the user.', + name: 'destination.user.id', + type: 'keyword', + }, + 'destination.user.name': { + category: 'destination', + description: 'Short name or login of the user.', + example: 'albert', + name: 'destination.user.name', + type: 'keyword', + }, + 'dll.code_signature.exists': { + category: 'dll', + description: 'Boolean to capture if a signature is present.', + example: 'true', + name: 'dll.code_signature.exists', + type: 'boolean', + }, + 'dll.code_signature.status': { + category: 'dll', + description: + 'Additional information about the certificate status. This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked.', + example: 'ERROR_UNTRUSTED_ROOT', + name: 'dll.code_signature.status', + type: 'keyword', + }, + 'dll.code_signature.subject_name': { + category: 'dll', + description: 'Subject name of the code signer', + example: 'Microsoft Corporation', + name: 'dll.code_signature.subject_name', + type: 'keyword', + }, + 'dll.code_signature.trusted': { + category: 'dll', + description: + 'Stores the trust status of the certificate chain. Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status.', + example: 'true', + name: 'dll.code_signature.trusted', + type: 'boolean', + }, + 'dll.code_signature.valid': { + category: 'dll', + description: + 'Boolean to capture if the digital signature is verified against the binary content. Leave unpopulated if a certificate was unchecked.', + example: 'true', + name: 'dll.code_signature.valid', + type: 'boolean', + }, + 'dll.hash.md5': { + category: 'dll', + description: 'MD5 hash.', + name: 'dll.hash.md5', + type: 'keyword', + }, + 'dll.hash.sha1': { + category: 'dll', + description: 'SHA1 hash.', + name: 'dll.hash.sha1', + type: 'keyword', + }, + 'dll.hash.sha256': { + category: 'dll', + description: 'SHA256 hash.', + name: 'dll.hash.sha256', + type: 'keyword', + }, + 'dll.hash.sha512': { + category: 'dll', + description: 'SHA512 hash.', + name: 'dll.hash.sha512', + type: 'keyword', + }, + 'dll.name': { + category: 'dll', + description: 'Name of the library. This generally maps to the name of the file on disk.', + example: 'kernel32.dll', + name: 'dll.name', + type: 'keyword', + }, + 'dll.path': { + category: 'dll', + description: 'Full file path of the library.', + example: 'C:\\Windows\\System32\\kernel32.dll', + name: 'dll.path', + type: 'keyword', + }, + 'dll.pe.company': { + category: 'dll', + description: 'Internal company name of the file, provided at compile-time.', + example: 'Microsoft Corporation', + name: 'dll.pe.company', + type: 'keyword', + }, + 'dll.pe.description': { + category: 'dll', + description: 'Internal description of the file, provided at compile-time.', + example: 'Paint', + name: 'dll.pe.description', + type: 'keyword', + }, + 'dll.pe.file_version': { + category: 'dll', + description: 'Internal version of the file, provided at compile-time.', + example: '6.3.9600.17415', + name: 'dll.pe.file_version', + type: 'keyword', + }, + 'dll.pe.original_file_name': { + category: 'dll', + description: 'Internal name of the file, provided at compile-time.', + example: 'MSPAINT.EXE', + name: 'dll.pe.original_file_name', + type: 'keyword', + }, + 'dll.pe.product': { + category: 'dll', + description: 'Internal product name of the file, provided at compile-time.', + example: 'Microsoft® Windows® Operating System', + name: 'dll.pe.product', + type: 'keyword', + }, + 'dns.answers': { + category: 'dns', + description: + 'An array containing an object for each answer section returned by the server. The main keys that should be present in these objects are defined by ECS. Records that have more information may contain more keys than what ECS defines. Not all DNS data sources give all details about DNS answers. At minimum, answer objects must contain the `data` key. If more information is available, map as much of it to ECS as possible, and add any additional fields to the answer objects as custom fields.', + name: 'dns.answers', + type: 'object', + }, + 'dns.answers.class': { + category: 'dns', + description: 'The class of DNS data contained in this resource record.', + example: 'IN', + name: 'dns.answers.class', + type: 'keyword', + }, + 'dns.answers.data': { + category: 'dns', + description: + 'The data describing the resource. The meaning of this data depends on the type and class of the resource record.', + example: '10.10.10.10', + name: 'dns.answers.data', + type: 'keyword', + }, + 'dns.answers.name': { + category: 'dns', + description: + "The domain name to which this resource record pertains. If a chain of CNAME is being resolved, each answer's `name` should be the one that corresponds with the answer's `data`. It should not simply be the original `question.name` repeated.", + example: 'www.google.com', + name: 'dns.answers.name', + type: 'keyword', + }, + 'dns.answers.ttl': { + category: 'dns', + description: + 'The time interval in seconds that this resource record may be cached before it should be discarded. Zero values mean that the data should not be cached.', + example: 180, + name: 'dns.answers.ttl', + type: 'long', + }, + 'dns.answers.type': { + category: 'dns', + description: 'The type of data contained in this resource record.', + example: 'CNAME', + name: 'dns.answers.type', + type: 'keyword', + }, + 'dns.header_flags': { + category: 'dns', + description: + 'Array of 2 letter DNS header flags. Expected values are: AA, TC, RD, RA, AD, CD, DO.', + example: '["RD","RA"]', + name: 'dns.header_flags', + type: 'keyword', + }, + 'dns.id': { + category: 'dns', + description: + 'The DNS packet identifier assigned by the program that generated the query. The identifier is copied to the response.', + example: 62111, + name: 'dns.id', + type: 'keyword', + }, + 'dns.op_code': { + category: 'dns', + description: + 'The DNS operation code that specifies the kind of query in the message. This value is set by the originator of a query and copied into the response.', + example: 'QUERY', + name: 'dns.op_code', + type: 'keyword', + }, + 'dns.question.class': { + category: 'dns', + description: 'The class of records being queried.', + example: 'IN', + name: 'dns.question.class', + type: 'keyword', + }, + 'dns.question.name': { + category: 'dns', + description: + 'The name being queried. If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \\t, \\r, and \\n respectively.', + example: 'www.google.com', + name: 'dns.question.name', + type: 'keyword', + }, + 'dns.question.registered_domain': { + category: 'dns', + description: + 'The highest registered domain, stripped of the subdomain. For example, the registered domain for "foo.google.com" is "google.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk".', + example: 'google.com', + name: 'dns.question.registered_domain', + type: 'keyword', + }, + 'dns.question.subdomain': { + category: 'dns', + description: + 'The subdomain is all of the labels under the registered_domain. If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", the subdomain field should contain "sub2.sub1", with no trailing period.', + example: 'www', + name: 'dns.question.subdomain', + type: 'keyword', + }, + 'dns.question.top_level_domain': { + category: 'dns', + description: + 'The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for google.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk".', + example: 'co.uk', + name: 'dns.question.top_level_domain', + type: 'keyword', + }, + 'dns.question.type': { + category: 'dns', + description: 'The type of record being queried.', + example: 'AAAA', + name: 'dns.question.type', + type: 'keyword', + }, + 'dns.resolved_ip': { + category: 'dns', + description: + 'Array containing all IPs seen in `answers.data`. The `answers` array can be difficult to use, because of the variety of data formats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip` makes it possible to index them as IP addresses, and makes them easier to visualize and query for.', + example: '["10.10.10.10","10.10.10.11"]', + name: 'dns.resolved_ip', + type: 'ip', + }, + 'dns.response_code': { + category: 'dns', + description: 'The DNS response code.', + example: 'NOERROR', + name: 'dns.response_code', + type: 'keyword', + }, + 'dns.type': { + category: 'dns', + description: + 'The type of DNS event captured, query or answer. If your source of DNS events only gives you DNS queries, you should only create dns events of type `dns.type:query`. If your source of DNS events gives you answers as well, you should create one event per query (optionally as soon as the query is seen). And a second event containing all query details as well as an array of answers.', + example: 'answer', + name: 'dns.type', + type: 'keyword', + }, + 'ecs.version': { + category: 'ecs', + description: + 'ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events.', + example: '1.0.0', + name: 'ecs.version', + type: 'keyword', + }, + 'error.code': { + category: 'error', + description: 'Error code describing the error.', + name: 'error.code', + type: 'keyword', + }, + 'error.id': { + category: 'error', + description: 'Unique identifier for the error.', + name: 'error.id', + type: 'keyword', + }, + 'error.message': { + category: 'error', + description: 'Error message.', + name: 'error.message', + type: 'text', + }, + 'error.stack_trace': { + category: 'error', + description: 'The stack trace of this error in plain text.', + name: 'error.stack_trace', + type: 'keyword', + }, + 'error.type': { + category: 'error', + description: 'The type of the error, for example the class name of the exception.', + example: 'java.lang.NullPointerException', + name: 'error.type', + type: 'keyword', + }, + 'event.action': { + category: 'event', + description: + 'The action captured by the event. This describes the information in the event. It is more specific than `event.category`. Examples are `group-add`, `process-started`, `file-created`. The value is normally defined by the implementer.', + example: 'user-password-change', + name: 'event.action', + type: 'keyword', + }, + 'event.category': { + category: 'event', + description: + 'This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories.', + example: 'authentication', + name: 'event.category', + type: 'keyword', + }, + 'event.code': { + category: 'event', + description: + 'Identification code for this event, if one exists. Some event sources use event codes to identify messages unambiguously, regardless of message language or wording adjustments over time. An example of this is the Windows Event ID.', + example: 4648, + name: 'event.code', + type: 'keyword', + }, + 'event.created': { + category: 'event', + description: + "event.created contains the date/time when the event was first read by an agent, or by your pipeline. This field is distinct from @timestamp in that @timestamp typically contain the time extracted from the original event. In most situations, these two timestamps will be slightly different. The difference can be used to calculate the delay between your source generating an event, and the time when your agent first processed it. This can be used to monitor your agent's or pipeline's ability to keep up with your event source. In case the two timestamps are identical, @timestamp should be used.", + example: '2016-05-23T08:05:34.857Z', + name: 'event.created', + type: 'date', + }, + 'event.dataset': { + category: 'event', + description: + "Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name.", + example: 'apache.access', + name: 'event.dataset', + type: 'keyword', + }, + 'event.duration': { + category: 'event', + description: + 'Duration of the event in nanoseconds. If event.start and event.end are known this value should be the difference between the end and start time.', + name: 'event.duration', + type: 'long', + format: 'duration', + }, + 'event.end': { + category: 'event', + description: + 'event.end contains the date when the event ended or when the activity was last observed.', + name: 'event.end', + type: 'date', + }, + 'event.hash': { + category: 'event', + description: + 'Hash (perhaps logstash fingerprint) of raw field to be able to demonstrate log integrity.', + example: '123456789012345678901234567890ABCD', + name: 'event.hash', + type: 'keyword', + }, + 'event.id': { + category: 'event', + description: 'Unique ID to describe the event.', + example: '8a4f500d', + name: 'event.id', + type: 'keyword', + }, + 'event.ingested': { + category: 'event', + description: + "Timestamp when an event arrived in the central data store. This is different from `@timestamp`, which is when the event originally occurred. It's also different from `event.created`, which is meant to capture the first time an agent saw the event. In normal conditions, assuming no tampering, the timestamps should chronologically look like this: `@timestamp` < `event.created` < `event.ingested`.", + example: '2016-05-23T08:05:35.101Z', + name: 'event.ingested', + type: 'date', + }, + 'event.kind': { + category: 'event', + description: + 'This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data coming in at a regular interval or not.', + example: 'alert', + name: 'event.kind', + type: 'keyword', + }, + 'event.module': { + category: 'event', + description: + 'Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module.', + example: 'apache', + name: 'event.module', + type: 'keyword', + }, + 'event.original': { + category: 'event', + description: + 'Raw text message of entire event. Used to demonstrate log integrity. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`.', + example: + 'Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100| worm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232', + name: 'event.original', + type: 'keyword', + }, + 'event.outcome': { + category: 'event', + description: + 'This is one of four ECS Categorization Fields, and indicates the lowest level in the ECS category hierarchy. `event.outcome` simply denotes whether the event represents a success or a failure from the perspective of the entity that produced the event. Note that when a single transaction is described in multiple events, each event may populate different values of `event.outcome`, according to their perspective. Also note that in the case of a compound event (a single event that contains multiple logical events), this field should be populated with the value that best captures the overall success or failure from the perspective of the event producer. Further note that not all events will have an associated outcome. For example, this field is generally not populated for metric events, events with `event.type:info`, or any events for which an outcome does not make logical sense.', + example: 'success', + name: 'event.outcome', + type: 'keyword', + }, + 'event.provider': { + category: 'event', + description: + 'Source of the event. Event transports such as Syslog or the Windows Event Log typically mention the source of an event. It can be the name of the software that generated the event (e.g. Sysmon, httpd), or of a subsystem of the operating system (kernel, Microsoft-Windows-Security-Auditing).', + example: 'kernel', + name: 'event.provider', + type: 'keyword', + }, + 'event.reference': { + category: 'event', + description: + 'Reference URL linking to additional information about this event. This URL links to a static definition of the this event. Alert events, indicated by `event.kind:alert`, are a common use case for this field.', + example: 'https://system.vendor.com/event/#0001234', + name: 'event.reference', + type: 'keyword', + }, + 'event.risk_score': { + category: 'event', + description: + "Risk score or priority of the event (e.g. security solutions). Use your system's original value here.", + name: 'event.risk_score', + type: 'float', + }, + 'event.risk_score_norm': { + category: 'event', + description: + 'Normalized risk score or priority of the event, on a scale of 0 to 100. This is mainly useful if you use more than one system that assigns risk scores, and you want to see a normalized value across all systems.', + name: 'event.risk_score_norm', + type: 'float', + }, + 'event.sequence': { + category: 'event', + description: + 'Sequence number of the event. The sequence number is a value published by some event sources, to make the exact ordering of events unambiguous, regardless of the timestamp precision.', + name: 'event.sequence', + type: 'long', + format: 'string', + }, + 'event.severity': { + category: 'event', + description: + "The numeric severity of the event according to your event source. What the different severity values mean can be different between sources and use cases. It's up to the implementer to make sure severities are consistent across events from the same source. The Syslog severity belongs in `log.syslog.severity.code`. `event.severity` is meant to represent the severity according to the event source (e.g. firewall, IDS). If the event source does not publish its own severity, you may optionally copy the `log.syslog.severity.code` to `event.severity`.", + example: 7, + name: 'event.severity', + type: 'long', + format: 'string', + }, + 'event.start': { + category: 'event', + description: + 'event.start contains the date when the event started or when the activity was first observed.', + name: 'event.start', + type: 'date', + }, + 'event.timezone': { + category: 'event', + description: + 'This field should be populated when the event\'s timestamp does not include timezone information already (e.g. default Syslog timestamps). It\'s optional otherwise. Acceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"), abbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").', + name: 'event.timezone', + type: 'keyword', + }, + 'event.type': { + category: 'event', + description: + 'This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types.', + name: 'event.type', + type: 'keyword', + }, + 'event.url': { + category: 'event', + description: + 'URL linking to an external system to continue investigation of this event. This URL links to another system where in-depth investigation of the specific occurence of this event can take place. Alert events, indicated by `event.kind:alert`, are a common use case for this field.', + example: 'https://mysystem.mydomain.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe', + name: 'event.url', + type: 'keyword', + }, + 'file.accessed': { + category: 'file', + description: + 'Last time the file was accessed. Note that not all filesystems keep track of access time.', + name: 'file.accessed', + type: 'date', + }, + 'file.attributes': { + category: 'file', + description: + "Array of file attributes. Attributes names will vary by platform. Here's a non-exhaustive list of values that are expected in this field: archive, compressed, directory, encrypted, execute, hidden, read, readonly, system, write.", + example: '["readonly", "system"]', + name: 'file.attributes', + type: 'keyword', + }, + 'file.code_signature.exists': { + category: 'file', + description: 'Boolean to capture if a signature is present.', + example: 'true', + name: 'file.code_signature.exists', + type: 'boolean', + }, + 'file.code_signature.status': { + category: 'file', + description: + 'Additional information about the certificate status. This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked.', + example: 'ERROR_UNTRUSTED_ROOT', + name: 'file.code_signature.status', + type: 'keyword', + }, + 'file.code_signature.subject_name': { + category: 'file', + description: 'Subject name of the code signer', + example: 'Microsoft Corporation', + name: 'file.code_signature.subject_name', + type: 'keyword', + }, + 'file.code_signature.trusted': { + category: 'file', + description: + 'Stores the trust status of the certificate chain. Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status.', + example: 'true', + name: 'file.code_signature.trusted', + type: 'boolean', + }, + 'file.code_signature.valid': { + category: 'file', + description: + 'Boolean to capture if the digital signature is verified against the binary content. Leave unpopulated if a certificate was unchecked.', + example: 'true', + name: 'file.code_signature.valid', + type: 'boolean', + }, + 'file.created': { + category: 'file', + description: 'File creation time. Note that not all filesystems store the creation time.', + name: 'file.created', + type: 'date', + }, + 'file.ctime': { + category: 'file', + description: + 'Last time the file attributes or metadata changed. Note that changes to the file content will update `mtime`. This implies `ctime` will be adjusted at the same time, since `mtime` is an attribute of the file.', + name: 'file.ctime', + type: 'date', + }, + 'file.device': { + category: 'file', + description: 'Device that is the source of the file.', + example: 'sda', + name: 'file.device', + type: 'keyword', + }, + 'file.directory': { + category: 'file', + description: + 'Directory where the file is located. It should include the drive letter, when appropriate.', + example: '/home/alice', + name: 'file.directory', + type: 'keyword', + }, + 'file.drive_letter': { + category: 'file', + description: + 'Drive letter where the file is located. This field is only relevant on Windows. The value should be uppercase, and not include the colon.', + example: 'C', + name: 'file.drive_letter', + type: 'keyword', + }, + 'file.extension': { + category: 'file', + description: 'File extension.', + example: 'png', + name: 'file.extension', + type: 'keyword', + }, + 'file.gid': { + category: 'file', + description: 'Primary group ID (GID) of the file.', + example: '1001', + name: 'file.gid', + type: 'keyword', + }, + 'file.group': { + category: 'file', + description: 'Primary group name of the file.', + example: 'alice', + name: 'file.group', + type: 'keyword', + }, + 'file.hash.md5': { + category: 'file', + description: 'MD5 hash.', + name: 'file.hash.md5', + type: 'keyword', + }, + 'file.hash.sha1': { + category: 'file', + description: 'SHA1 hash.', + name: 'file.hash.sha1', + type: 'keyword', + }, + 'file.hash.sha256': { + category: 'file', + description: 'SHA256 hash.', + name: 'file.hash.sha256', + type: 'keyword', + }, + 'file.hash.sha512': { + category: 'file', + description: 'SHA512 hash.', + name: 'file.hash.sha512', + type: 'keyword', + }, + 'file.inode': { + category: 'file', + description: 'Inode representing the file in the filesystem.', + example: '256383', + name: 'file.inode', + type: 'keyword', + }, + 'file.mime_type': { + category: 'file', + description: + 'MIME type should identify the format of the file or stream of bytes using https://www.iana.org/assignments/media-types/media-types.xhtml[IANA official types], where possible. When more than one type is applicable, the most specific type should be used.', + name: 'file.mime_type', + type: 'keyword', + }, + 'file.mode': { + category: 'file', + description: 'Mode of the file in octal representation.', + example: '0640', + name: 'file.mode', + type: 'keyword', + }, + 'file.mtime': { + category: 'file', + description: 'Last time the file content was modified.', + name: 'file.mtime', + type: 'date', + }, + 'file.name': { + category: 'file', + description: 'Name of the file including the extension, without the directory.', + example: 'example.png', + name: 'file.name', + type: 'keyword', + }, + 'file.owner': { + category: 'file', + description: "File owner's username.", + example: 'alice', + name: 'file.owner', + type: 'keyword', + }, + 'file.path': { + category: 'file', + description: + 'Full path to the file, including the file name. It should include the drive letter, when appropriate.', + example: '/home/alice/example.png', + name: 'file.path', + type: 'keyword', + }, + 'file.pe.company': { + category: 'file', + description: 'Internal company name of the file, provided at compile-time.', + example: 'Microsoft Corporation', + name: 'file.pe.company', + type: 'keyword', + }, + 'file.pe.description': { + category: 'file', + description: 'Internal description of the file, provided at compile-time.', + example: 'Paint', + name: 'file.pe.description', + type: 'keyword', + }, + 'file.pe.file_version': { + category: 'file', + description: 'Internal version of the file, provided at compile-time.', + example: '6.3.9600.17415', + name: 'file.pe.file_version', + type: 'keyword', + }, + 'file.pe.original_file_name': { + category: 'file', + description: 'Internal name of the file, provided at compile-time.', + example: 'MSPAINT.EXE', + name: 'file.pe.original_file_name', + type: 'keyword', + }, + 'file.pe.product': { + category: 'file', + description: 'Internal product name of the file, provided at compile-time.', + example: 'Microsoft® Windows® Operating System', + name: 'file.pe.product', + type: 'keyword', + }, + 'file.size': { + category: 'file', + description: 'File size in bytes. Only relevant when `file.type` is "file".', + example: 16384, + name: 'file.size', + type: 'long', + }, + 'file.target_path': { + category: 'file', + description: 'Target path for symlinks.', + name: 'file.target_path', + type: 'keyword', + }, + 'file.type': { + category: 'file', + description: 'File type (file, dir, or symlink).', + example: 'file', + name: 'file.type', + type: 'keyword', + }, + 'file.uid': { + category: 'file', + description: 'The user ID (UID) or security identifier (SID) of the file owner.', + example: '1001', + name: 'file.uid', + type: 'keyword', + }, + 'geo.city_name': { + category: 'geo', + description: 'City name.', + example: 'Montreal', + name: 'geo.city_name', + type: 'keyword', + }, + 'geo.continent_name': { + category: 'geo', + description: 'Name of the continent.', + example: 'North America', + name: 'geo.continent_name', + type: 'keyword', + }, + 'geo.country_iso_code': { + category: 'geo', + description: 'Country ISO code.', + example: 'CA', + name: 'geo.country_iso_code', + type: 'keyword', + }, + 'geo.country_name': { + category: 'geo', + description: 'Country name.', + example: 'Canada', + name: 'geo.country_name', + type: 'keyword', + }, + 'geo.location': { + category: 'geo', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'geo.location', + type: 'geo_point', + }, + 'geo.name': { + category: 'geo', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'geo.name', + type: 'keyword', + }, + 'geo.region_iso_code': { + category: 'geo', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'geo.region_iso_code', + type: 'keyword', + }, + 'geo.region_name': { + category: 'geo', + description: 'Region name.', + example: 'Quebec', + name: 'geo.region_name', + type: 'keyword', + }, + 'group.domain': { + category: 'group', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'group.domain', + type: 'keyword', + }, + 'group.id': { + category: 'group', + description: 'Unique identifier for the group on the system/platform.', + name: 'group.id', + type: 'keyword', + }, + 'group.name': { + category: 'group', + description: 'Name of the group.', + name: 'group.name', + type: 'keyword', + }, + 'hash.md5': { + category: 'hash', + description: 'MD5 hash.', + name: 'hash.md5', + type: 'keyword', + }, + 'hash.sha1': { + category: 'hash', + description: 'SHA1 hash.', + name: 'hash.sha1', + type: 'keyword', + }, + 'hash.sha256': { + category: 'hash', + description: 'SHA256 hash.', + name: 'hash.sha256', + type: 'keyword', + }, + 'hash.sha512': { + category: 'hash', + description: 'SHA512 hash.', + name: 'hash.sha512', + type: 'keyword', + }, + 'host.architecture': { + category: 'host', + description: 'Operating system architecture.', + example: 'x86_64', + name: 'host.architecture', + type: 'keyword', + }, + 'host.domain': { + category: 'host', + description: + "Name of the domain of which the host is a member. For example, on Windows this could be the host's Active Directory domain or NetBIOS domain name. For Linux this could be the domain of the host's LDAP provider.", + example: 'CONTOSO', + name: 'host.domain', + type: 'keyword', + }, + 'host.geo.city_name': { + category: 'host', + description: 'City name.', + example: 'Montreal', + name: 'host.geo.city_name', + type: 'keyword', + }, + 'host.geo.continent_name': { + category: 'host', + description: 'Name of the continent.', + example: 'North America', + name: 'host.geo.continent_name', + type: 'keyword', + }, + 'host.geo.country_iso_code': { + category: 'host', + description: 'Country ISO code.', + example: 'CA', + name: 'host.geo.country_iso_code', + type: 'keyword', + }, + 'host.geo.country_name': { + category: 'host', + description: 'Country name.', + example: 'Canada', + name: 'host.geo.country_name', + type: 'keyword', + }, + 'host.geo.location': { + category: 'host', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'host.geo.location', + type: 'geo_point', + }, + 'host.geo.name': { + category: 'host', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'host.geo.name', + type: 'keyword', + }, + 'host.geo.region_iso_code': { + category: 'host', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'host.geo.region_iso_code', + type: 'keyword', + }, + 'host.geo.region_name': { + category: 'host', + description: 'Region name.', + example: 'Quebec', + name: 'host.geo.region_name', + type: 'keyword', + }, + 'host.hostname': { + category: 'host', + description: + 'Hostname of the host. It normally contains what the `hostname` command returns on the host machine.', + name: 'host.hostname', + type: 'keyword', + }, + 'host.id': { + category: 'host', + description: + 'Unique host id. As hostname is not always unique, use values that are meaningful in your environment. Example: The current usage of `beat.name`.', + name: 'host.id', + type: 'keyword', + }, + 'host.ip': { + category: 'host', + description: 'Host ip addresses.', + name: 'host.ip', + type: 'ip', + }, + 'host.mac': { + category: 'host', + description: 'Host mac addresses.', + name: 'host.mac', + type: 'keyword', + }, + 'host.name': { + category: 'host', + description: + 'Name of the host. It can contain what `hostname` returns on Unix systems, the fully qualified domain name, or a name specified by the user. The sender decides which value to use.', + name: 'host.name', + type: 'keyword', + }, + 'host.os.family': { + category: 'host', + description: 'OS family (such as redhat, debian, freebsd, windows).', + example: 'debian', + name: 'host.os.family', + type: 'keyword', + }, + 'host.os.full': { + category: 'host', + description: 'Operating system name, including the version or code name.', + example: 'Mac OS Mojave', + name: 'host.os.full', + type: 'keyword', + }, + 'host.os.kernel': { + category: 'host', + description: 'Operating system kernel version as a raw string.', + example: '4.4.0-112-generic', + name: 'host.os.kernel', + type: 'keyword', + }, + 'host.os.name': { + category: 'host', + description: 'Operating system name, without the version.', + example: 'Mac OS X', + name: 'host.os.name', + type: 'keyword', + }, + 'host.os.platform': { + category: 'host', + description: 'Operating system platform (such centos, ubuntu, windows).', + example: 'darwin', + name: 'host.os.platform', + type: 'keyword', + }, + 'host.os.version': { + category: 'host', + description: 'Operating system version as a raw string.', + example: '10.14.1', + name: 'host.os.version', + type: 'keyword', + }, + 'host.type': { + category: 'host', + description: + 'Type of host. For Cloud providers this can be the machine type like `t2.medium`. If vm, this could be the container, for example, or other information meaningful in your environment.', + name: 'host.type', + type: 'keyword', + }, + 'host.uptime': { + category: 'host', + description: 'Seconds the host has been up.', + example: 1325, + name: 'host.uptime', + type: 'long', + }, + 'host.user.domain': { + category: 'host', + description: + 'Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name.', + name: 'host.user.domain', + type: 'keyword', + }, + 'host.user.email': { + category: 'host', + description: 'User email address.', + name: 'host.user.email', + type: 'keyword', + }, + 'host.user.full_name': { + category: 'host', + description: "User's full name, if available.", + example: 'Albert Einstein', + name: 'host.user.full_name', + type: 'keyword', + }, + 'host.user.group.domain': { + category: 'host', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'host.user.group.domain', + type: 'keyword', + }, + 'host.user.group.id': { + category: 'host', + description: 'Unique identifier for the group on the system/platform.', + name: 'host.user.group.id', + type: 'keyword', + }, + 'host.user.group.name': { + category: 'host', + description: 'Name of the group.', + name: 'host.user.group.name', + type: 'keyword', + }, + 'host.user.hash': { + category: 'host', + description: + 'Unique user hash to correlate information for a user in anonymized form. Useful if `user.id` or `user.name` contain confidential information and cannot be used.', + name: 'host.user.hash', + type: 'keyword', + }, + 'host.user.id': { + category: 'host', + description: 'Unique identifiers of the user.', + name: 'host.user.id', + type: 'keyword', + }, + 'host.user.name': { + category: 'host', + description: 'Short name or login of the user.', + example: 'albert', + name: 'host.user.name', + type: 'keyword', + }, + 'http.request.body.bytes': { + category: 'http', + description: 'Size in bytes of the request body.', + example: 887, + name: 'http.request.body.bytes', + type: 'long', + format: 'bytes', + }, + 'http.request.body.content': { + category: 'http', + description: 'The full HTTP request body.', + example: 'Hello world', + name: 'http.request.body.content', + type: 'keyword', + }, + 'http.request.bytes': { + category: 'http', + description: 'Total size in bytes of the request (body and headers).', + example: 1437, + name: 'http.request.bytes', + type: 'long', + format: 'bytes', + }, + 'http.request.method': { + category: 'http', + description: + 'HTTP request method. The field value must be normalized to lowercase for querying. See the documentation section "Implementing ECS".', + example: 'get, post, put', + name: 'http.request.method', + type: 'keyword', + }, + 'http.request.referrer': { + category: 'http', + description: 'Referrer for this HTTP request.', + example: 'https://blog.example.com/', + name: 'http.request.referrer', + type: 'keyword', + }, + 'http.response.body.bytes': { + category: 'http', + description: 'Size in bytes of the response body.', + example: 887, + name: 'http.response.body.bytes', + type: 'long', + format: 'bytes', + }, + 'http.response.body.content': { + category: 'http', + description: 'The full HTTP response body.', + example: 'Hello world', + name: 'http.response.body.content', + type: 'keyword', + }, + 'http.response.bytes': { + category: 'http', + description: 'Total size in bytes of the response (body and headers).', + example: 1437, + name: 'http.response.bytes', + type: 'long', + format: 'bytes', + }, + 'http.response.status_code': { + category: 'http', + description: 'HTTP response status code.', + example: 404, + name: 'http.response.status_code', + type: 'long', + format: 'string', + }, + 'http.version': { + category: 'http', + description: 'HTTP version.', + example: 1.1, + name: 'http.version', + type: 'keyword', + }, + 'interface.alias': { + category: 'interface', + description: + 'Interface alias as reported by the system, typically used in firewall implementations for e.g. inside, outside, or dmz logical interface naming.', + example: 'outside', + name: 'interface.alias', + type: 'keyword', + }, + 'interface.id': { + category: 'interface', + description: 'Interface ID as reported by an observer (typically SNMP interface ID).', + example: 10, + name: 'interface.id', + type: 'keyword', + }, + 'interface.name': { + category: 'interface', + description: 'Interface name as reported by the system.', + example: 'eth0', + name: 'interface.name', + type: 'keyword', + }, + 'log.level': { + category: 'log', + description: + "Original log level of the log event. If the source of the event provides a log level or textual severity, this is the one that goes in `log.level`. If your source doesn't specify one, you may put your event transport's severity here (e.g. Syslog severity). Some examples are `warn`, `err`, `i`, `informational`.", + example: 'error', + name: 'log.level', + type: 'keyword', + }, + 'log.logger': { + category: 'log', + description: + 'The name of the logger inside an application. This is usually the name of the class which initialized the logger, or can be a custom name.', + example: 'org.elasticsearch.bootstrap.Bootstrap', + name: 'log.logger', + type: 'keyword', + }, + 'log.origin.file.line': { + category: 'log', + description: + 'The line number of the file containing the source code which originated the log event.', + example: 42, + name: 'log.origin.file.line', + type: 'integer', + }, + 'log.origin.file.name': { + category: 'log', + description: + 'The name of the file containing the source code which originated the log event. Note that this is not the name of the log file.', + example: 'Bootstrap.java', + name: 'log.origin.file.name', + type: 'keyword', + }, + 'log.origin.function': { + category: 'log', + description: 'The name of the function or method which originated the log event.', + example: 'init', + name: 'log.origin.function', + type: 'keyword', + }, + 'log.original': { + category: 'log', + description: + "This is the original log message and contains the full log message before splitting it up in multiple parts. In contrast to the `message` field which can contain an extracted part of the log message, this field contains the original, full log message. It can have already some modifications applied like encoding or new lines removed to clean up the log message. This field is not indexed and doc_values are disabled so it can't be queried but the value can be retrieved from `_source`.", + example: 'Sep 19 08:26:10 localhost My log', + name: 'log.original', + type: 'keyword', + }, + 'log.syslog': { + category: 'log', + description: + 'The Syslog metadata of the event, if the event was transmitted via Syslog. Please see RFCs 5424 or 3164.', + name: 'log.syslog', + type: 'object', + }, + 'log.syslog.facility.code': { + category: 'log', + description: + 'The Syslog numeric facility of the log event, if available. According to RFCs 5424 and 3164, this value should be an integer between 0 and 23.', + example: 23, + name: 'log.syslog.facility.code', + type: 'long', + format: 'string', + }, + 'log.syslog.facility.name': { + category: 'log', + description: 'The Syslog text-based facility of the log event, if available.', + example: 'local7', + name: 'log.syslog.facility.name', + type: 'keyword', + }, + 'log.syslog.priority': { + category: 'log', + description: + 'Syslog numeric priority of the event, if available. According to RFCs 5424 and 3164, the priority is 8 * facility + severity. This number is therefore expected to contain a value between 0 and 191.', + example: 135, + name: 'log.syslog.priority', + type: 'long', + format: 'string', + }, + 'log.syslog.severity.code': { + category: 'log', + description: + "The Syslog numeric severity of the log event, if available. If the event source publishing via Syslog provides a different numeric severity value (e.g. firewall, IDS), your source's numeric severity should go to `event.severity`. If the event source does not specify a distinct severity, you can optionally copy the Syslog severity to `event.severity`.", + example: 3, + name: 'log.syslog.severity.code', + type: 'long', + }, + 'log.syslog.severity.name': { + category: 'log', + description: + "The Syslog numeric severity of the log event, if available. If the event source publishing via Syslog provides a different severity value (e.g. firewall, IDS), your source's text severity should go to `log.level`. If the event source does not specify a distinct severity, you can optionally copy the Syslog severity to `log.level`.", + example: 'Error', + name: 'log.syslog.severity.name', + type: 'keyword', + }, + 'network.application': { + category: 'network', + description: + 'A name given to an application level protocol. This can be arbitrarily assigned for things like microservices, but also apply to things like skype, icq, facebook, twitter. This would be used in situations where the vendor or service can be decoded such as from the source/dest IP owners, ports, or wire format. The field value must be normalized to lowercase for querying. See the documentation section "Implementing ECS".', + example: 'aim', + name: 'network.application', + type: 'keyword', + }, + 'network.bytes': { + category: 'network', + description: + 'Total bytes transferred in both directions. If `source.bytes` and `destination.bytes` are known, `network.bytes` is their sum.', + example: 368, + name: 'network.bytes', + type: 'long', + format: 'bytes', + }, + 'network.community_id': { + category: 'network', + description: + 'A hash of source and destination IPs and ports, as well as the protocol used in a communication. This is a tool-agnostic standard to identify flows. Learn more at https://github.com/corelight/community-id-spec.', + example: '1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=', + name: 'network.community_id', + type: 'keyword', + }, + 'network.direction': { + category: 'network', + description: + "Direction of the network traffic. Recommended values are: * inbound * outbound * internal * external * unknown When mapping events from a host-based monitoring context, populate this field from the host's point of view. When mapping events from a network or perimeter-based monitoring context, populate this field from the point of view of your network perimeter.", + example: 'inbound', + name: 'network.direction', + type: 'keyword', + }, + 'network.forwarded_ip': { + category: 'network', + description: 'Host IP address when the source IP address is the proxy.', + example: '192.1.1.2', + name: 'network.forwarded_ip', + type: 'ip', + }, + 'network.iana_number': { + category: 'network', + description: + 'IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml). Standardized list of protocols. This aligns well with NetFlow and sFlow related logs which use the IANA Protocol Number.', + example: 6, + name: 'network.iana_number', + type: 'keyword', + }, + 'network.inner': { + category: 'network', + description: + 'Network.inner fields are added in addition to network.vlan fields to describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed fields include vlan.id and vlan.name. Inner vlan fields are typically used when sending traffic with multiple 802.1q encapsulations to a network sensor (e.g. Zeek, Wireshark.)', + name: 'network.inner', + type: 'object', + }, + 'network.inner.vlan.id': { + category: 'network', + description: 'VLAN ID as reported by the observer.', + example: 10, + name: 'network.inner.vlan.id', + type: 'keyword', + }, + 'network.inner.vlan.name': { + category: 'network', + description: 'Optional VLAN name as reported by the observer.', + example: 'outside', + name: 'network.inner.vlan.name', + type: 'keyword', + }, + 'network.name': { + category: 'network', + description: 'Name given by operators to sections of their network.', + example: 'Guest Wifi', + name: 'network.name', + type: 'keyword', + }, + 'network.packets': { + category: 'network', + description: + 'Total packets transferred in both directions. If `source.packets` and `destination.packets` are known, `network.packets` is their sum.', + example: 24, + name: 'network.packets', + type: 'long', + }, + 'network.protocol': { + category: 'network', + description: + 'L7 Network protocol name. ex. http, lumberjack, transport protocol. The field value must be normalized to lowercase for querying. See the documentation section "Implementing ECS".', + example: 'http', + name: 'network.protocol', + type: 'keyword', + }, + 'network.transport': { + category: 'network', + description: + 'Same as network.iana_number, but instead using the Keyword name of the transport layer (udp, tcp, ipv6-icmp, etc.) The field value must be normalized to lowercase for querying. See the documentation section "Implementing ECS".', + example: 'tcp', + name: 'network.transport', + type: 'keyword', + }, + 'network.type': { + category: 'network', + description: + 'In the OSI Model this would be the Network Layer. ipv4, ipv6, ipsec, pim, etc The field value must be normalized to lowercase for querying. See the documentation section "Implementing ECS".', + example: 'ipv4', + name: 'network.type', + type: 'keyword', + }, + 'network.vlan.id': { + category: 'network', + description: 'VLAN ID as reported by the observer.', + example: 10, + name: 'network.vlan.id', + type: 'keyword', + }, + 'network.vlan.name': { + category: 'network', + description: 'Optional VLAN name as reported by the observer.', + example: 'outside', + name: 'network.vlan.name', + type: 'keyword', + }, + 'observer.egress': { + category: 'observer', + description: + 'Observer.egress holds information like interface number and name, vlan, and zone information to classify egress traffic. Single armed monitoring such as a network sensor on a span port should only use observer.ingress to categorize traffic.', + name: 'observer.egress', + type: 'object', + }, + 'observer.egress.interface.alias': { + category: 'observer', + description: + 'Interface alias as reported by the system, typically used in firewall implementations for e.g. inside, outside, or dmz logical interface naming.', + example: 'outside', + name: 'observer.egress.interface.alias', + type: 'keyword', + }, + 'observer.egress.interface.id': { + category: 'observer', + description: 'Interface ID as reported by an observer (typically SNMP interface ID).', + example: 10, + name: 'observer.egress.interface.id', + type: 'keyword', + }, + 'observer.egress.interface.name': { + category: 'observer', + description: 'Interface name as reported by the system.', + example: 'eth0', + name: 'observer.egress.interface.name', + type: 'keyword', + }, + 'observer.egress.vlan.id': { + category: 'observer', + description: 'VLAN ID as reported by the observer.', + example: 10, + name: 'observer.egress.vlan.id', + type: 'keyword', + }, + 'observer.egress.vlan.name': { + category: 'observer', + description: 'Optional VLAN name as reported by the observer.', + example: 'outside', + name: 'observer.egress.vlan.name', + type: 'keyword', + }, + 'observer.egress.zone': { + category: 'observer', + description: + 'Network zone of outbound traffic as reported by the observer to categorize the destination area of egress traffic, e.g. Internal, External, DMZ, HR, Legal, etc.', + example: 'Public_Internet', + name: 'observer.egress.zone', + type: 'keyword', + }, + 'observer.geo.city_name': { + category: 'observer', + description: 'City name.', + example: 'Montreal', + name: 'observer.geo.city_name', + type: 'keyword', + }, + 'observer.geo.continent_name': { + category: 'observer', + description: 'Name of the continent.', + example: 'North America', + name: 'observer.geo.continent_name', + type: 'keyword', + }, + 'observer.geo.country_iso_code': { + category: 'observer', + description: 'Country ISO code.', + example: 'CA', + name: 'observer.geo.country_iso_code', + type: 'keyword', + }, + 'observer.geo.country_name': { + category: 'observer', + description: 'Country name.', + example: 'Canada', + name: 'observer.geo.country_name', + type: 'keyword', + }, + 'observer.geo.location': { + category: 'observer', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'observer.geo.location', + type: 'geo_point', + }, + 'observer.geo.name': { + category: 'observer', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'observer.geo.name', + type: 'keyword', + }, + 'observer.geo.region_iso_code': { + category: 'observer', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'observer.geo.region_iso_code', + type: 'keyword', + }, + 'observer.geo.region_name': { + category: 'observer', + description: 'Region name.', + example: 'Quebec', + name: 'observer.geo.region_name', + type: 'keyword', + }, + 'observer.hostname': { + category: 'observer', + description: 'Hostname of the observer.', + name: 'observer.hostname', + type: 'keyword', + }, + 'observer.ingress': { + category: 'observer', + description: + 'Observer.ingress holds information like interface number and name, vlan, and zone information to classify ingress traffic. Single armed monitoring such as a network sensor on a span port should only use observer.ingress to categorize traffic.', + name: 'observer.ingress', + type: 'object', + }, + 'observer.ingress.interface.alias': { + category: 'observer', + description: + 'Interface alias as reported by the system, typically used in firewall implementations for e.g. inside, outside, or dmz logical interface naming.', + example: 'outside', + name: 'observer.ingress.interface.alias', + type: 'keyword', + }, + 'observer.ingress.interface.id': { + category: 'observer', + description: 'Interface ID as reported by an observer (typically SNMP interface ID).', + example: 10, + name: 'observer.ingress.interface.id', + type: 'keyword', + }, + 'observer.ingress.interface.name': { + category: 'observer', + description: 'Interface name as reported by the system.', + example: 'eth0', + name: 'observer.ingress.interface.name', + type: 'keyword', + }, + 'observer.ingress.vlan.id': { + category: 'observer', + description: 'VLAN ID as reported by the observer.', + example: 10, + name: 'observer.ingress.vlan.id', + type: 'keyword', + }, + 'observer.ingress.vlan.name': { + category: 'observer', + description: 'Optional VLAN name as reported by the observer.', + example: 'outside', + name: 'observer.ingress.vlan.name', + type: 'keyword', + }, + 'observer.ingress.zone': { + category: 'observer', + description: + 'Network zone of incoming traffic as reported by the observer to categorize the source area of ingress traffic. e.g. internal, External, DMZ, HR, Legal, etc.', + example: 'DMZ', + name: 'observer.ingress.zone', + type: 'keyword', + }, + 'observer.ip': { + category: 'observer', + description: 'IP addresses of the observer.', + name: 'observer.ip', + type: 'ip', + }, + 'observer.mac': { + category: 'observer', + description: 'MAC addresses of the observer', + name: 'observer.mac', + type: 'keyword', + }, + 'observer.name': { + category: 'observer', + description: + 'Custom name of the observer. This is a name that can be given to an observer. This can be helpful for example if multiple firewalls of the same model are used in an organization. If no custom name is needed, the field can be left empty.', + example: '1_proxySG', + name: 'observer.name', + type: 'keyword', + }, + 'observer.os.family': { + category: 'observer', + description: 'OS family (such as redhat, debian, freebsd, windows).', + example: 'debian', + name: 'observer.os.family', + type: 'keyword', + }, + 'observer.os.full': { + category: 'observer', + description: 'Operating system name, including the version or code name.', + example: 'Mac OS Mojave', + name: 'observer.os.full', + type: 'keyword', + }, + 'observer.os.kernel': { + category: 'observer', + description: 'Operating system kernel version as a raw string.', + example: '4.4.0-112-generic', + name: 'observer.os.kernel', + type: 'keyword', + }, + 'observer.os.name': { + category: 'observer', + description: 'Operating system name, without the version.', + example: 'Mac OS X', + name: 'observer.os.name', + type: 'keyword', + }, + 'observer.os.platform': { + category: 'observer', + description: 'Operating system platform (such centos, ubuntu, windows).', + example: 'darwin', + name: 'observer.os.platform', + type: 'keyword', + }, + 'observer.os.version': { + category: 'observer', + description: 'Operating system version as a raw string.', + example: '10.14.1', + name: 'observer.os.version', + type: 'keyword', + }, + 'observer.product': { + category: 'observer', + description: 'The product name of the observer.', + example: 's200', + name: 'observer.product', + type: 'keyword', + }, + 'observer.serial_number': { + category: 'observer', + description: 'Observer serial number.', + name: 'observer.serial_number', + type: 'keyword', + }, + 'observer.type': { + category: 'observer', + description: + 'The type of the observer the data is coming from. There is no predefined list of observer types. Some examples are `forwarder`, `firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.', + example: 'firewall', + name: 'observer.type', + type: 'keyword', + }, + 'observer.vendor': { + category: 'observer', + description: 'Vendor name of the observer.', + example: 'Symantec', + name: 'observer.vendor', + type: 'keyword', + }, + 'observer.version': { + category: 'observer', + description: 'Observer version.', + name: 'observer.version', + type: 'keyword', + }, + 'organization.id': { + category: 'organization', + description: 'Unique identifier for the organization.', + name: 'organization.id', + type: 'keyword', + }, + 'organization.name': { + category: 'organization', + description: 'Organization name.', + name: 'organization.name', + type: 'keyword', + }, + 'os.family': { + category: 'os', + description: 'OS family (such as redhat, debian, freebsd, windows).', + example: 'debian', + name: 'os.family', + type: 'keyword', + }, + 'os.full': { + category: 'os', + description: 'Operating system name, including the version or code name.', + example: 'Mac OS Mojave', + name: 'os.full', + type: 'keyword', + }, + 'os.kernel': { + category: 'os', + description: 'Operating system kernel version as a raw string.', + example: '4.4.0-112-generic', + name: 'os.kernel', + type: 'keyword', + }, + 'os.name': { + category: 'os', + description: 'Operating system name, without the version.', + example: 'Mac OS X', + name: 'os.name', + type: 'keyword', + }, + 'os.platform': { + category: 'os', + description: 'Operating system platform (such centos, ubuntu, windows).', + example: 'darwin', + name: 'os.platform', + type: 'keyword', + }, + 'os.version': { + category: 'os', + description: 'Operating system version as a raw string.', + example: '10.14.1', + name: 'os.version', + type: 'keyword', + }, + 'package.architecture': { + category: 'package', + description: 'Package architecture.', + example: 'x86_64', + name: 'package.architecture', + type: 'keyword', + }, + 'package.build_version': { + category: 'package', + description: + 'Additional information about the build version of the installed package. For example use the commit SHA of a non-released package.', + example: '36f4f7e89dd61b0988b12ee000b98966867710cd', + name: 'package.build_version', + type: 'keyword', + }, + 'package.checksum': { + category: 'package', + description: 'Checksum of the installed package for verification.', + example: '68b329da9893e34099c7d8ad5cb9c940', + name: 'package.checksum', + type: 'keyword', + }, + 'package.description': { + category: 'package', + description: 'Description of the package.', + example: 'Open source programming language to build simple/reliable/efficient software.', + name: 'package.description', + type: 'keyword', + }, + 'package.install_scope': { + category: 'package', + description: 'Indicating how the package was installed, e.g. user-local, global.', + example: 'global', + name: 'package.install_scope', + type: 'keyword', + }, + 'package.installed': { + category: 'package', + description: 'Time when package was installed.', + name: 'package.installed', + type: 'date', + }, + 'package.license': { + category: 'package', + description: + 'License under which the package was released. Use a short name, e.g. the license identifier from SPDX License List where possible (https://spdx.org/licenses/).', + example: 'Apache License 2.0', + name: 'package.license', + type: 'keyword', + }, + 'package.name': { + category: 'package', + description: 'Package name', + example: 'go', + name: 'package.name', + type: 'keyword', + }, + 'package.path': { + category: 'package', + description: 'Path where the package is installed.', + example: '/usr/local/Cellar/go/1.12.9/', + name: 'package.path', + type: 'keyword', + }, + 'package.reference': { + category: 'package', + description: 'Home page or reference URL of the software in this package, if available.', + example: 'https://golang.org', + name: 'package.reference', + type: 'keyword', + }, + 'package.size': { + category: 'package', + description: 'Package size in bytes.', + example: 62231, + name: 'package.size', + type: 'long', + format: 'string', + }, + 'package.type': { + category: 'package', + description: + 'Type of package. This should contain the package file type, rather than the package manager name. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar.', + example: 'rpm', + name: 'package.type', + type: 'keyword', + }, + 'package.version': { + category: 'package', + description: 'Package version', + example: '1.12.9', + name: 'package.version', + type: 'keyword', + }, + 'pe.company': { + category: 'pe', + description: 'Internal company name of the file, provided at compile-time.', + example: 'Microsoft Corporation', + name: 'pe.company', + type: 'keyword', + }, + 'pe.description': { + category: 'pe', + description: 'Internal description of the file, provided at compile-time.', + example: 'Paint', + name: 'pe.description', + type: 'keyword', + }, + 'pe.file_version': { + category: 'pe', + description: 'Internal version of the file, provided at compile-time.', + example: '6.3.9600.17415', + name: 'pe.file_version', + type: 'keyword', + }, + 'pe.original_file_name': { + category: 'pe', + description: 'Internal name of the file, provided at compile-time.', + example: 'MSPAINT.EXE', + name: 'pe.original_file_name', + type: 'keyword', + }, + 'pe.product': { + category: 'pe', + description: 'Internal product name of the file, provided at compile-time.', + example: 'Microsoft® Windows® Operating System', + name: 'pe.product', + type: 'keyword', + }, + 'process.args': { + category: 'process', + description: + 'Array of process arguments, starting with the absolute path to the executable. May be filtered to protect sensitive information.', + example: '["/usr/bin/ssh","-l","user","10.0.0.16"]', + name: 'process.args', + type: 'keyword', + }, + 'process.args_count': { + category: 'process', + description: + 'Length of the process.args array. This field can be useful for querying or performing bucket analysis on how many arguments were provided to start a process. More arguments may be an indication of suspicious activity.', + example: 4, + name: 'process.args_count', + type: 'long', + }, + 'process.code_signature.exists': { + category: 'process', + description: 'Boolean to capture if a signature is present.', + example: 'true', + name: 'process.code_signature.exists', + type: 'boolean', + }, + 'process.code_signature.status': { + category: 'process', + description: + 'Additional information about the certificate status. This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked.', + example: 'ERROR_UNTRUSTED_ROOT', + name: 'process.code_signature.status', + type: 'keyword', + }, + 'process.code_signature.subject_name': { + category: 'process', + description: 'Subject name of the code signer', + example: 'Microsoft Corporation', + name: 'process.code_signature.subject_name', + type: 'keyword', + }, + 'process.code_signature.trusted': { + category: 'process', + description: + 'Stores the trust status of the certificate chain. Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status.', + example: 'true', + name: 'process.code_signature.trusted', + type: 'boolean', + }, + 'process.code_signature.valid': { + category: 'process', + description: + 'Boolean to capture if the digital signature is verified against the binary content. Leave unpopulated if a certificate was unchecked.', + example: 'true', + name: 'process.code_signature.valid', + type: 'boolean', + }, + 'process.command_line': { + category: 'process', + description: + 'Full command line that started the process, including the absolute path to the executable, and all arguments. Some arguments may be filtered to protect sensitive information.', + example: '/usr/bin/ssh -l user 10.0.0.16', + name: 'process.command_line', + type: 'keyword', + }, + 'process.entity_id': { + category: 'process', + description: + 'Unique identifier for the process. The implementation of this is specified by the data source, but some examples of what could be used here are a process-generated UUID, Sysmon Process GUIDs, or a hash of some uniquely identifying components of a process. Constructing a globally unique identifier is a common practice to mitigate PID reuse as well as to identify a specific process over time, across multiple monitored hosts.', + example: 'c2c455d9f99375d', + name: 'process.entity_id', + type: 'keyword', + }, + 'process.executable': { + category: 'process', + description: 'Absolute path to the process executable.', + example: '/usr/bin/ssh', + name: 'process.executable', + type: 'keyword', + }, + 'process.exit_code': { + category: 'process', + description: + 'The exit code of the process, if this is a termination event. The field should be absent if there is no exit code for the event (e.g. process start).', + example: 137, + name: 'process.exit_code', + type: 'long', + }, + 'process.hash.md5': { + category: 'process', + description: 'MD5 hash.', + name: 'process.hash.md5', + type: 'keyword', + }, + 'process.hash.sha1': { + category: 'process', + description: 'SHA1 hash.', + name: 'process.hash.sha1', + type: 'keyword', + }, + 'process.hash.sha256': { + category: 'process', + description: 'SHA256 hash.', + name: 'process.hash.sha256', + type: 'keyword', + }, + 'process.hash.sha512': { + category: 'process', + description: 'SHA512 hash.', + name: 'process.hash.sha512', + type: 'keyword', + }, + 'process.name': { + category: 'process', + description: 'Process name. Sometimes called program name or similar.', + example: 'ssh', + name: 'process.name', + type: 'keyword', + }, + 'process.parent.args': { + category: 'process', + description: 'Array of process arguments. May be filtered to protect sensitive information.', + example: '["ssh","-l","user","10.0.0.16"]', + name: 'process.parent.args', + type: 'keyword', + }, + 'process.parent.args_count': { + category: 'process', + description: + 'Length of the process.args array. This field can be useful for querying or performing bucket analysis on how many arguments were provided to start a process. More arguments may be an indication of suspicious activity.', + example: 4, + name: 'process.parent.args_count', + type: 'long', + }, + 'process.parent.code_signature.exists': { + category: 'process', + description: 'Boolean to capture if a signature is present.', + example: 'true', + name: 'process.parent.code_signature.exists', + type: 'boolean', + }, + 'process.parent.code_signature.status': { + category: 'process', + description: + 'Additional information about the certificate status. This is useful for logging cryptographic errors with the certificate validity or trust status. Leave unpopulated if the validity or trust of the certificate was unchecked.', + example: 'ERROR_UNTRUSTED_ROOT', + name: 'process.parent.code_signature.status', + type: 'keyword', + }, + 'process.parent.code_signature.subject_name': { + category: 'process', + description: 'Subject name of the code signer', + example: 'Microsoft Corporation', + name: 'process.parent.code_signature.subject_name', + type: 'keyword', + }, + 'process.parent.code_signature.trusted': { + category: 'process', + description: + 'Stores the trust status of the certificate chain. Validating the trust of the certificate chain may be complicated, and this field should only be populated by tools that actively check the status.', + example: 'true', + name: 'process.parent.code_signature.trusted', + type: 'boolean', + }, + 'process.parent.code_signature.valid': { + category: 'process', + description: + 'Boolean to capture if the digital signature is verified against the binary content. Leave unpopulated if a certificate was unchecked.', + example: 'true', + name: 'process.parent.code_signature.valid', + type: 'boolean', + }, + 'process.parent.command_line': { + category: 'process', + description: + 'Full command line that started the process, including the absolute path to the executable, and all arguments. Some arguments may be filtered to protect sensitive information.', + example: '/usr/bin/ssh -l user 10.0.0.16', + name: 'process.parent.command_line', + type: 'keyword', + }, + 'process.parent.entity_id': { + category: 'process', + description: + 'Unique identifier for the process. The implementation of this is specified by the data source, but some examples of what could be used here are a process-generated UUID, Sysmon Process GUIDs, or a hash of some uniquely identifying components of a process. Constructing a globally unique identifier is a common practice to mitigate PID reuse as well as to identify a specific process over time, across multiple monitored hosts.', + example: 'c2c455d9f99375d', + name: 'process.parent.entity_id', + type: 'keyword', + }, + 'process.parent.executable': { + category: 'process', + description: 'Absolute path to the process executable.', + example: '/usr/bin/ssh', + name: 'process.parent.executable', + type: 'keyword', + }, + 'process.parent.exit_code': { + category: 'process', + description: + 'The exit code of the process, if this is a termination event. The field should be absent if there is no exit code for the event (e.g. process start).', + example: 137, + name: 'process.parent.exit_code', + type: 'long', + }, + 'process.parent.hash.md5': { + category: 'process', + description: 'MD5 hash.', + name: 'process.parent.hash.md5', + type: 'keyword', + }, + 'process.parent.hash.sha1': { + category: 'process', + description: 'SHA1 hash.', + name: 'process.parent.hash.sha1', + type: 'keyword', + }, + 'process.parent.hash.sha256': { + category: 'process', + description: 'SHA256 hash.', + name: 'process.parent.hash.sha256', + type: 'keyword', + }, + 'process.parent.hash.sha512': { + category: 'process', + description: 'SHA512 hash.', + name: 'process.parent.hash.sha512', + type: 'keyword', + }, + 'process.parent.name': { + category: 'process', + description: 'Process name. Sometimes called program name or similar.', + example: 'ssh', + name: 'process.parent.name', + type: 'keyword', + }, + 'process.parent.pgid': { + category: 'process', + description: 'Identifier of the group of processes the process belongs to.', + name: 'process.parent.pgid', + type: 'long', + format: 'string', + }, + 'process.parent.pid': { + category: 'process', + description: 'Process id.', + example: 4242, + name: 'process.parent.pid', + type: 'long', + format: 'string', + }, + 'process.parent.ppid': { + category: 'process', + description: "Parent process' pid.", + example: 4241, + name: 'process.parent.ppid', + type: 'long', + format: 'string', + }, + 'process.parent.start': { + category: 'process', + description: 'The time the process started.', + example: '2016-05-23T08:05:34.853Z', + name: 'process.parent.start', + type: 'date', + }, + 'process.parent.thread.id': { + category: 'process', + description: 'Thread ID.', + example: 4242, + name: 'process.parent.thread.id', + type: 'long', + format: 'string', + }, + 'process.parent.thread.name': { + category: 'process', + description: 'Thread name.', + example: 'thread-0', + name: 'process.parent.thread.name', + type: 'keyword', + }, + 'process.parent.title': { + category: 'process', + description: + 'Process title. The proctitle, some times the same as process name. Can also be different: for example a browser setting its title to the web page currently opened.', + name: 'process.parent.title', + type: 'keyword', + }, + 'process.parent.uptime': { + category: 'process', + description: 'Seconds the process has been up.', + example: 1325, + name: 'process.parent.uptime', + type: 'long', + }, + 'process.parent.working_directory': { + category: 'process', + description: 'The working directory of the process.', + example: '/home/alice', + name: 'process.parent.working_directory', + type: 'keyword', + }, + 'process.pe.company': { + category: 'process', + description: 'Internal company name of the file, provided at compile-time.', + example: 'Microsoft Corporation', + name: 'process.pe.company', + type: 'keyword', + }, + 'process.pe.description': { + category: 'process', + description: 'Internal description of the file, provided at compile-time.', + example: 'Paint', + name: 'process.pe.description', + type: 'keyword', + }, + 'process.pe.file_version': { + category: 'process', + description: 'Internal version of the file, provided at compile-time.', + example: '6.3.9600.17415', + name: 'process.pe.file_version', + type: 'keyword', + }, + 'process.pe.original_file_name': { + category: 'process', + description: 'Internal name of the file, provided at compile-time.', + example: 'MSPAINT.EXE', + name: 'process.pe.original_file_name', + type: 'keyword', + }, + 'process.pe.product': { + category: 'process', + description: 'Internal product name of the file, provided at compile-time.', + example: 'Microsoft® Windows® Operating System', + name: 'process.pe.product', + type: 'keyword', + }, + 'process.pgid': { + category: 'process', + description: 'Identifier of the group of processes the process belongs to.', + name: 'process.pgid', + type: 'long', + format: 'string', + }, + 'process.pid': { + category: 'process', + description: 'Process id.', + example: 4242, + name: 'process.pid', + type: 'long', + format: 'string', + }, + 'process.ppid': { + category: 'process', + description: "Parent process' pid.", + example: 4241, + name: 'process.ppid', + type: 'long', + format: 'string', + }, + 'process.start': { + category: 'process', + description: 'The time the process started.', + example: '2016-05-23T08:05:34.853Z', + name: 'process.start', + type: 'date', + }, + 'process.thread.id': { + category: 'process', + description: 'Thread ID.', + example: 4242, + name: 'process.thread.id', + type: 'long', + format: 'string', + }, + 'process.thread.name': { + category: 'process', + description: 'Thread name.', + example: 'thread-0', + name: 'process.thread.name', + type: 'keyword', + }, + 'process.title': { + category: 'process', + description: + 'Process title. The proctitle, some times the same as process name. Can also be different: for example a browser setting its title to the web page currently opened.', + name: 'process.title', + type: 'keyword', + }, + 'process.uptime': { + category: 'process', + description: 'Seconds the process has been up.', + example: 1325, + name: 'process.uptime', + type: 'long', + }, + 'process.working_directory': { + category: 'process', + description: 'The working directory of the process.', + example: '/home/alice', + name: 'process.working_directory', + type: 'keyword', + }, + 'registry.data.bytes': { + category: 'registry', + description: + 'Original bytes written with base64 encoding. For Windows registry operations, such as SetValueEx and RegQueryValueEx, this corresponds to the data pointed by `lp_data`. This is optional but provides better recoverability and should be populated for REG_BINARY encoded values.', + example: 'ZQBuAC0AVQBTAAAAZQBuAAAAAAA=', + name: 'registry.data.bytes', + type: 'keyword', + }, + 'registry.data.strings': { + category: 'registry', + description: + 'Content when writing string types. Populated as an array when writing string data to the registry. For single string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with one string. For sequences of string with REG_MULTI_SZ, this array will be variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should be populated with the decimal representation (e.g `"1"`).', + example: '["C:\\rta\\red_ttp\\bin\\myapp.exe"]', + name: 'registry.data.strings', + type: 'keyword', + }, + 'registry.data.type': { + category: 'registry', + description: 'Standard registry type for encoding contents', + example: 'REG_SZ', + name: 'registry.data.type', + type: 'keyword', + }, + 'registry.hive': { + category: 'registry', + description: 'Abbreviated name for the hive.', + example: 'HKLM', + name: 'registry.hive', + type: 'keyword', + }, + 'registry.key': { + category: 'registry', + description: 'Hive-relative path of keys.', + example: + 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe', + name: 'registry.key', + type: 'keyword', + }, + 'registry.path': { + category: 'registry', + description: 'Full path, including hive, key and value', + example: + 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe\\Debugger', + name: 'registry.path', + type: 'keyword', + }, + 'registry.value': { + category: 'registry', + description: 'Name of the value written.', + example: 'Debugger', + name: 'registry.value', + type: 'keyword', + }, + 'related.hash': { + category: 'related', + description: + "All the hashes seen on your event. Populating this field, then using it to search for hashes can help in situations where you're unsure what the hash algorithm is (and therefore which key name to search).", + name: 'related.hash', + type: 'keyword', + }, + 'related.ip': { + category: 'related', + description: 'All of the IPs seen on your event.', + name: 'related.ip', + type: 'ip', + }, + 'related.user': { + category: 'related', + description: 'All the user names seen on your event.', + name: 'related.user', + type: 'keyword', + }, + 'rule.author': { + category: 'rule', + description: + 'Name, organization, or pseudonym of the author or authors who created the rule used to generate this event.', + example: '["Star-Lord"]', + name: 'rule.author', + type: 'keyword', + }, + 'rule.category': { + category: 'rule', + description: + 'A categorization value keyword used by the entity using the rule for detection of this event.', + example: 'Attempted Information Leak', + name: 'rule.category', + type: 'keyword', + }, + 'rule.description': { + category: 'rule', + description: 'The description of the rule generating the event.', + example: 'Block requests to public DNS over HTTPS / TLS protocols', + name: 'rule.description', + type: 'keyword', + }, + 'rule.id': { + category: 'rule', + description: + 'A rule ID that is unique within the scope of an agent, observer, or other entity using the rule for detection of this event.', + example: 101, + name: 'rule.id', + type: 'keyword', + }, + 'rule.license': { + category: 'rule', + description: + 'Name of the license under which the rule used to generate this event is made available.', + example: 'Apache 2.0', + name: 'rule.license', + type: 'keyword', + }, + 'rule.name': { + category: 'rule', + description: 'The name of the rule or signature generating the event.', + example: 'BLOCK_DNS_over_TLS', + name: 'rule.name', + type: 'keyword', + }, + 'rule.reference': { + category: 'rule', + description: + "Reference URL to additional information about the rule used to generate this event. The URL can point to the vendor's documentation about the rule. If that's not available, it can also be a link to a more general page describing this type of alert.", + example: 'https://en.wikipedia.org/wiki/DNS_over_TLS', + name: 'rule.reference', + type: 'keyword', + }, + 'rule.ruleset': { + category: 'rule', + description: + 'Name of the ruleset, policy, group, or parent category in which the rule used to generate this event is a member.', + example: 'Standard_Protocol_Filters', + name: 'rule.ruleset', + type: 'keyword', + }, + 'rule.uuid': { + category: 'rule', + description: + 'A rule ID that is unique within the scope of a set or group of agents, observers, or other entities using the rule for detection of this event.', + example: 1100110011, + name: 'rule.uuid', + type: 'keyword', + }, + 'rule.version': { + category: 'rule', + description: 'The version / revision of the rule being used for analysis.', + example: 1.1, + name: 'rule.version', + type: 'keyword', + }, + 'server.address': { + category: 'server', + description: + 'Some event server addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', + name: 'server.address', + type: 'keyword', + }, + 'server.as.number': { + category: 'server', + description: + 'Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet.', + example: 15169, + name: 'server.as.number', + type: 'long', + }, + 'server.as.organization.name': { + category: 'server', + description: 'Organization name.', + example: 'Google LLC', + name: 'server.as.organization.name', + type: 'keyword', + }, + 'server.bytes': { + category: 'server', + description: 'Bytes sent from the server to the client.', + example: 184, + name: 'server.bytes', + type: 'long', + format: 'bytes', + }, + 'server.domain': { + category: 'server', + description: 'Server domain.', + name: 'server.domain', + type: 'keyword', + }, + 'server.geo.city_name': { + category: 'server', + description: 'City name.', + example: 'Montreal', + name: 'server.geo.city_name', + type: 'keyword', + }, + 'server.geo.continent_name': { + category: 'server', + description: 'Name of the continent.', + example: 'North America', + name: 'server.geo.continent_name', + type: 'keyword', + }, + 'server.geo.country_iso_code': { + category: 'server', + description: 'Country ISO code.', + example: 'CA', + name: 'server.geo.country_iso_code', + type: 'keyword', + }, + 'server.geo.country_name': { + category: 'server', + description: 'Country name.', + example: 'Canada', + name: 'server.geo.country_name', + type: 'keyword', + }, + 'server.geo.location': { + category: 'server', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'server.geo.location', + type: 'geo_point', + }, + 'server.geo.name': { + category: 'server', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'server.geo.name', + type: 'keyword', + }, + 'server.geo.region_iso_code': { + category: 'server', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'server.geo.region_iso_code', + type: 'keyword', + }, + 'server.geo.region_name': { + category: 'server', + description: 'Region name.', + example: 'Quebec', + name: 'server.geo.region_name', + type: 'keyword', + }, + 'server.ip': { + category: 'server', + description: 'IP address of the server. Can be one or multiple IPv4 or IPv6 addresses.', + name: 'server.ip', + type: 'ip', + }, + 'server.mac': { + category: 'server', + description: 'MAC address of the server.', + name: 'server.mac', + type: 'keyword', + }, + 'server.nat.ip': { + category: 'server', + description: + 'Translated ip of destination based NAT sessions (e.g. internet to private DMZ) Typically used with load balancers, firewalls, or routers.', + name: 'server.nat.ip', + type: 'ip', + }, + 'server.nat.port': { + category: 'server', + description: + 'Translated port of destination based NAT sessions (e.g. internet to private DMZ) Typically used with load balancers, firewalls, or routers.', + name: 'server.nat.port', + type: 'long', + format: 'string', + }, + 'server.packets': { + category: 'server', + description: 'Packets sent from the server to the client.', + example: 12, + name: 'server.packets', + type: 'long', + }, + 'server.port': { + category: 'server', + description: 'Port of the server.', + name: 'server.port', + type: 'long', + format: 'string', + }, + 'server.registered_domain': { + category: 'server', + description: + 'The highest registered server domain, stripped of the subdomain. For example, the registered domain for "foo.google.com" is "google.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk".', + example: 'google.com', + name: 'server.registered_domain', + type: 'keyword', + }, + 'server.top_level_domain': { + category: 'server', + description: + 'The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for google.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk".', + example: 'co.uk', + name: 'server.top_level_domain', + type: 'keyword', + }, + 'server.user.domain': { + category: 'server', + description: + 'Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name.', + name: 'server.user.domain', + type: 'keyword', + }, + 'server.user.email': { + category: 'server', + description: 'User email address.', + name: 'server.user.email', + type: 'keyword', + }, + 'server.user.full_name': { + category: 'server', + description: "User's full name, if available.", + example: 'Albert Einstein', + name: 'server.user.full_name', + type: 'keyword', + }, + 'server.user.group.domain': { + category: 'server', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'server.user.group.domain', + type: 'keyword', + }, + 'server.user.group.id': { + category: 'server', + description: 'Unique identifier for the group on the system/platform.', + name: 'server.user.group.id', + type: 'keyword', + }, + 'server.user.group.name': { + category: 'server', + description: 'Name of the group.', + name: 'server.user.group.name', + type: 'keyword', + }, + 'server.user.hash': { + category: 'server', + description: + 'Unique user hash to correlate information for a user in anonymized form. Useful if `user.id` or `user.name` contain confidential information and cannot be used.', + name: 'server.user.hash', + type: 'keyword', + }, + 'server.user.id': { + category: 'server', + description: 'Unique identifiers of the user.', + name: 'server.user.id', + type: 'keyword', + }, + 'server.user.name': { + category: 'server', + description: 'Short name or login of the user.', + example: 'albert', + name: 'server.user.name', + type: 'keyword', + }, + 'service.ephemeral_id': { + category: 'service', + description: + 'Ephemeral identifier of this service (if one exists). This id normally changes across restarts, but `service.id` does not.', + example: '8a4f500f', + name: 'service.ephemeral_id', + type: 'keyword', + }, + 'service.id': { + category: 'service', + description: + 'Unique identifier of the running service. If the service is comprised of many nodes, the `service.id` should be the same for all nodes. This id should uniquely identify the service. This makes it possible to correlate logs and metrics for one specific service, no matter which particular node emitted the event. Note that if you need to see the events from one specific host of the service, you should filter on that `host.name` or `host.id` instead.', + example: 'd37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6', + name: 'service.id', + type: 'keyword', + }, + 'service.name': { + category: 'service', + description: + 'Name of the service data is collected from. The name of the service is normally user given. This allows for distributed services that run on multiple hosts to correlate the related instances based on the name. In the case of Elasticsearch the `service.name` could contain the cluster name. For Beats the `service.name` is by default a copy of the `service.type` field if no name is specified.', + example: 'elasticsearch-metrics', + name: 'service.name', + type: 'keyword', + }, + 'service.node.name': { + category: 'service', + description: + "Name of a service node. This allows for two nodes of the same service running on the same host to be differentiated. Therefore, `service.node.name` should typically be unique across nodes of a given service. In the case of Elasticsearch, the `service.node.name` could contain the unique node name within the Elasticsearch cluster. In cases where the service doesn't have the concept of a node name, the host name or container name can be used to distinguish running instances that make up this service. If those do not provide uniqueness (e.g. multiple instances of the service running on the same host) - the node name can be manually set.", + example: 'instance-0000000016', + name: 'service.node.name', + type: 'keyword', + }, + 'service.state': { + category: 'service', + description: 'Current state of the service.', + name: 'service.state', + type: 'keyword', + }, + 'service.type': { + category: 'service', + description: + 'The type of the service data is collected from. The type can be used to group and correlate logs and metrics from one service type. Example: If logs or metrics are collected from Elasticsearch, `service.type` would be `elasticsearch`.', + example: 'elasticsearch', + name: 'service.type', + type: 'keyword', + }, + 'service.version': { + category: 'service', + description: + 'Version of the service the data was collected from. This allows to look at a data set only for a specific version of a service.', + example: '3.2.4', + name: 'service.version', + type: 'keyword', + }, + 'source.address': { + category: 'source', + description: + 'Some event source addresses are defined ambiguously. The event will sometimes list an IP, a domain or a unix socket. You should always store the raw address in the `.address` field. Then it should be duplicated to `.ip` or `.domain`, depending on which one it is.', + name: 'source.address', + type: 'keyword', + }, + 'source.as.number': { + category: 'source', + description: + 'Unique number allocated to the autonomous system. The autonomous system number (ASN) uniquely identifies each network on the Internet.', + example: 15169, + name: 'source.as.number', + type: 'long', + }, + 'source.as.organization.name': { + category: 'source', + description: 'Organization name.', + example: 'Google LLC', + name: 'source.as.organization.name', + type: 'keyword', + }, + 'source.bytes': { + category: 'source', + description: 'Bytes sent from the source to the destination.', + example: 184, + name: 'source.bytes', + type: 'long', + format: 'bytes', + }, + 'source.domain': { + category: 'source', + description: 'Source domain.', + name: 'source.domain', + type: 'keyword', + }, + 'source.geo.city_name': { + category: 'source', + description: 'City name.', + example: 'Montreal', + name: 'source.geo.city_name', + type: 'keyword', + }, + 'source.geo.continent_name': { + category: 'source', + description: 'Name of the continent.', + example: 'North America', + name: 'source.geo.continent_name', + type: 'keyword', + }, + 'source.geo.country_iso_code': { + category: 'source', + description: 'Country ISO code.', + example: 'CA', + name: 'source.geo.country_iso_code', + type: 'keyword', + }, + 'source.geo.country_name': { + category: 'source', + description: 'Country name.', + example: 'Canada', + name: 'source.geo.country_name', + type: 'keyword', + }, + 'source.geo.location': { + category: 'source', + description: 'Longitude and latitude.', + example: '{ "lon": -73.614830, "lat": 45.505918 }', + name: 'source.geo.location', + type: 'geo_point', + }, + 'source.geo.name': { + category: 'source', + description: + 'User-defined description of a location, at the level of granularity they care about. Could be the name of their data centers, the floor number, if this describes a local physical entity, city names. Not typically used in automated geolocation.', + example: 'boston-dc', + name: 'source.geo.name', + type: 'keyword', + }, + 'source.geo.region_iso_code': { + category: 'source', + description: 'Region ISO code.', + example: 'CA-QC', + name: 'source.geo.region_iso_code', + type: 'keyword', + }, + 'source.geo.region_name': { + category: 'source', + description: 'Region name.', + example: 'Quebec', + name: 'source.geo.region_name', + type: 'keyword', + }, + 'source.ip': { + category: 'source', + description: 'IP address of the source. Can be one or multiple IPv4 or IPv6 addresses.', + name: 'source.ip', + type: 'ip', + }, + 'source.mac': { + category: 'source', + description: 'MAC address of the source.', + name: 'source.mac', + type: 'keyword', + }, + 'source.nat.ip': { + category: 'source', + description: + 'Translated ip of source based NAT sessions (e.g. internal client to internet) Typically connections traversing load balancers, firewalls, or routers.', + name: 'source.nat.ip', + type: 'ip', + }, + 'source.nat.port': { + category: 'source', + description: + 'Translated port of source based NAT sessions. (e.g. internal client to internet) Typically used with load balancers, firewalls, or routers.', + name: 'source.nat.port', + type: 'long', + format: 'string', + }, + 'source.packets': { + category: 'source', + description: 'Packets sent from the source to the destination.', + example: 12, + name: 'source.packets', + type: 'long', + }, + 'source.port': { + category: 'source', + description: 'Port of the source.', + name: 'source.port', + type: 'long', + format: 'string', + }, + 'source.registered_domain': { + category: 'source', + description: + 'The highest registered source domain, stripped of the subdomain. For example, the registered domain for "foo.google.com" is "google.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk".', + example: 'google.com', + name: 'source.registered_domain', + type: 'keyword', + }, + 'source.top_level_domain': { + category: 'source', + description: + 'The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for google.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk".', + example: 'co.uk', + name: 'source.top_level_domain', + type: 'keyword', + }, + 'source.user.domain': { + category: 'source', + description: + 'Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name.', + name: 'source.user.domain', + type: 'keyword', + }, + 'source.user.email': { + category: 'source', + description: 'User email address.', + name: 'source.user.email', + type: 'keyword', + }, + 'source.user.full_name': { + category: 'source', + description: "User's full name, if available.", + example: 'Albert Einstein', + name: 'source.user.full_name', + type: 'keyword', + }, + 'source.user.group.domain': { + category: 'source', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'source.user.group.domain', + type: 'keyword', + }, + 'source.user.group.id': { + category: 'source', + description: 'Unique identifier for the group on the system/platform.', + name: 'source.user.group.id', + type: 'keyword', + }, + 'source.user.group.name': { + category: 'source', + description: 'Name of the group.', + name: 'source.user.group.name', + type: 'keyword', + }, + 'source.user.hash': { + category: 'source', + description: + 'Unique user hash to correlate information for a user in anonymized form. Useful if `user.id` or `user.name` contain confidential information and cannot be used.', + name: 'source.user.hash', + type: 'keyword', + }, + 'source.user.id': { + category: 'source', + description: 'Unique identifiers of the user.', + name: 'source.user.id', + type: 'keyword', + }, + 'source.user.name': { + category: 'source', + description: 'Short name or login of the user.', + example: 'albert', + name: 'source.user.name', + type: 'keyword', + }, + 'threat.framework': { + category: 'threat', + description: + 'Name of the threat framework used to further categorize and classify the tactic and technique of the reported threat. Framework classification can be provided by detecting systems, evaluated at ingest time, or retrospectively tagged to events.', + example: 'MITRE ATT&CK', + name: 'threat.framework', + type: 'keyword', + }, + 'threat.tactic.id': { + category: 'threat', + description: + 'The id of tactic used by this threat. You can use the Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/ )', + example: 'TA0040', + name: 'threat.tactic.id', + type: 'keyword', + }, + 'threat.tactic.name': { + category: 'threat', + description: + 'Name of the type of tactic used by this threat. You can use the Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/ )', + example: 'impact', + name: 'threat.tactic.name', + type: 'keyword', + }, + 'threat.tactic.reference': { + category: 'threat', + description: + 'The reference url of tactic used by this threat. You can use the Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/tactics/TA0040/ )', + example: 'https://attack.mitre.org/tactics/TA0040/', + name: 'threat.tactic.reference', + type: 'keyword', + }, + 'threat.technique.id': { + category: 'threat', + description: + 'The id of technique used by this tactic. You can use the Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/ )', + example: 'T1499', + name: 'threat.technique.id', + type: 'keyword', + }, + 'threat.technique.name': { + category: 'threat', + description: + 'The name of technique used by this tactic. You can use the Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/ )', + example: 'endpoint denial of service', + name: 'threat.technique.name', + type: 'keyword', + }, + 'threat.technique.reference': { + category: 'threat', + description: + 'The reference url of technique used by this tactic. You can use the Mitre ATT&CK Matrix Tactic categorization, for example. (ex. https://attack.mitre.org/techniques/T1499/ )', + example: 'https://attack.mitre.org/techniques/T1499/', + name: 'threat.technique.reference', + type: 'keyword', + }, + 'tls.cipher': { + category: 'tls', + description: 'String indicating the cipher used during the current connection.', + example: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', + name: 'tls.cipher', + type: 'keyword', + }, + 'tls.client.certificate': { + category: 'tls', + description: + 'PEM-encoded stand-alone certificate offered by the client. This is usually mutually-exclusive of `client.certificate_chain` since this value also exists in that list.', + example: 'MII...', + name: 'tls.client.certificate', + type: 'keyword', + }, + 'tls.client.certificate_chain': { + category: 'tls', + description: + 'Array of PEM-encoded certificates that make up the certificate chain offered by the client. This is usually mutually-exclusive of `client.certificate` since that value should be the first certificate in the chain.', + example: '["MII...","MII..."]', + name: 'tls.client.certificate_chain', + type: 'keyword', + }, + 'tls.client.hash.md5': { + category: 'tls', + description: + 'Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the client. For consistency with other hash values, this value should be formatted as an uppercase hash.', + example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', + name: 'tls.client.hash.md5', + type: 'keyword', + }, + 'tls.client.hash.sha1': { + category: 'tls', + description: + 'Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the client. For consistency with other hash values, this value should be formatted as an uppercase hash.', + example: '9E393D93138888D288266C2D915214D1D1CCEB2A', + name: 'tls.client.hash.sha1', + type: 'keyword', + }, + 'tls.client.hash.sha256': { + category: 'tls', + description: + 'Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the client. For consistency with other hash values, this value should be formatted as an uppercase hash.', + example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', + name: 'tls.client.hash.sha256', + type: 'keyword', + }, + 'tls.client.issuer': { + category: 'tls', + description: + 'Distinguished name of subject of the issuer of the x.509 certificate presented by the client.', + example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', + name: 'tls.client.issuer', + type: 'keyword', + }, + 'tls.client.ja3': { + category: 'tls', + description: 'A hash that identifies clients based on how they perform an SSL/TLS handshake.', + example: 'd4e5b18d6b55c71272893221c96ba240', + name: 'tls.client.ja3', + type: 'keyword', + }, + 'tls.client.not_after': { + category: 'tls', + description: 'Date/Time indicating when client certificate is no longer considered valid.', + example: '2021-01-01T00:00:00.000Z', + name: 'tls.client.not_after', + type: 'date', + }, + 'tls.client.not_before': { + category: 'tls', + description: 'Date/Time indicating when client certificate is first considered valid.', + example: '1970-01-01T00:00:00.000Z', + name: 'tls.client.not_before', + type: 'date', + }, + 'tls.client.server_name': { + category: 'tls', + description: + 'Also called an SNI, this tells the server which hostname to which the client is attempting to connect. When this value is available, it should get copied to `destination.domain`.', + example: 'www.elastic.co', + name: 'tls.client.server_name', + type: 'keyword', + }, + 'tls.client.subject': { + category: 'tls', + description: 'Distinguished name of subject of the x.509 certificate presented by the client.', + example: 'CN=myclient, OU=Documentation Team, DC=mydomain, DC=com', + name: 'tls.client.subject', + type: 'keyword', + }, + 'tls.client.supported_ciphers': { + category: 'tls', + description: 'Array of ciphers offered by the client during the client hello.', + example: + '["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","..."]', + name: 'tls.client.supported_ciphers', + type: 'keyword', + }, + 'tls.curve': { + category: 'tls', + description: 'String indicating the curve used for the given cipher, when applicable.', + example: 'secp256r1', + name: 'tls.curve', + type: 'keyword', + }, + 'tls.established': { + category: 'tls', + description: + 'Boolean flag indicating if the TLS negotiation was successful and transitioned to an encrypted tunnel.', + name: 'tls.established', + type: 'boolean', + }, + 'tls.next_protocol': { + category: 'tls', + description: + 'String indicating the protocol being tunneled. Per the values in the IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), this string should be lower case.', + example: 'http/1.1', + name: 'tls.next_protocol', + type: 'keyword', + }, + 'tls.resumed': { + category: 'tls', + description: + 'Boolean flag indicating if this TLS connection was resumed from an existing TLS negotiation.', + name: 'tls.resumed', + type: 'boolean', + }, + 'tls.server.certificate': { + category: 'tls', + description: + 'PEM-encoded stand-alone certificate offered by the server. This is usually mutually-exclusive of `server.certificate_chain` since this value also exists in that list.', + example: 'MII...', + name: 'tls.server.certificate', + type: 'keyword', + }, + 'tls.server.certificate_chain': { + category: 'tls', + description: + 'Array of PEM-encoded certificates that make up the certificate chain offered by the server. This is usually mutually-exclusive of `server.certificate` since that value should be the first certificate in the chain.', + example: '["MII...","MII..."]', + name: 'tls.server.certificate_chain', + type: 'keyword', + }, + 'tls.server.hash.md5': { + category: 'tls', + description: + 'Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the server. For consistency with other hash values, this value should be formatted as an uppercase hash.', + example: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC', + name: 'tls.server.hash.md5', + type: 'keyword', + }, + 'tls.server.hash.sha1': { + category: 'tls', + description: + 'Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the server. For consistency with other hash values, this value should be formatted as an uppercase hash.', + example: '9E393D93138888D288266C2D915214D1D1CCEB2A', + name: 'tls.server.hash.sha1', + type: 'keyword', + }, + 'tls.server.hash.sha256': { + category: 'tls', + description: + 'Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the server. For consistency with other hash values, this value should be formatted as an uppercase hash.', + example: '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0', + name: 'tls.server.hash.sha256', + type: 'keyword', + }, + 'tls.server.issuer': { + category: 'tls', + description: 'Subject of the issuer of the x.509 certificate presented by the server.', + example: 'CN=MyDomain Root CA, OU=Infrastructure Team, DC=mydomain, DC=com', + name: 'tls.server.issuer', + type: 'keyword', + }, + 'tls.server.ja3s': { + category: 'tls', + description: 'A hash that identifies servers based on how they perform an SSL/TLS handshake.', + example: '394441ab65754e2207b1e1b457b3641d', + name: 'tls.server.ja3s', + type: 'keyword', + }, + 'tls.server.not_after': { + category: 'tls', + description: 'Timestamp indicating when server certificate is no longer considered valid.', + example: '2021-01-01T00:00:00.000Z', + name: 'tls.server.not_after', + type: 'date', + }, + 'tls.server.not_before': { + category: 'tls', + description: 'Timestamp indicating when server certificate is first considered valid.', + example: '1970-01-01T00:00:00.000Z', + name: 'tls.server.not_before', + type: 'date', + }, + 'tls.server.subject': { + category: 'tls', + description: 'Subject of the x.509 certificate presented by the server.', + example: 'CN=www.mydomain.com, OU=Infrastructure Team, DC=mydomain, DC=com', + name: 'tls.server.subject', + type: 'keyword', + }, + 'tls.version': { + category: 'tls', + description: 'Numeric part of the version parsed from the original string.', + example: '1.2', + name: 'tls.version', + type: 'keyword', + }, + 'tls.version_protocol': { + category: 'tls', + description: 'Normalized lowercase protocol name parsed from original string.', + example: 'tls', + name: 'tls.version_protocol', + type: 'keyword', + }, + 'tracing.trace.id': { + category: 'tracing', + description: + 'Unique identifier of the trace. A trace groups multiple events like transactions that belong together. For example, a user request handled by multiple inter-connected services.', + example: '4bf92f3577b34da6a3ce929d0e0e4736', + name: 'tracing.trace.id', + type: 'keyword', + }, + 'tracing.transaction.id': { + category: 'tracing', + description: + 'Unique identifier of the transaction. A transaction is the highest level of work measured within a service, such as a request to a server.', + example: '00f067aa0ba902b7', + name: 'tracing.transaction.id', + type: 'keyword', + }, + 'url.domain': { + category: 'url', + description: + 'Domain of the url, such as "www.elastic.co". In some cases a URL may refer to an IP and/or port directly, without a domain name. In this case, the IP address would go to the `domain` field.', + example: 'www.elastic.co', + name: 'url.domain', + type: 'keyword', + }, + 'url.extension': { + category: 'url', + description: + 'The field contains the file extension from the original request url. The file extension is only set if it exists, as not every url has a file extension. The leading period must not be included. For example, the value must be "png", not ".png".', + example: 'png', + name: 'url.extension', + type: 'keyword', + }, + 'url.fragment': { + category: 'url', + description: + 'Portion of the url after the `#`, such as "top". The `#` is not part of the fragment.', + name: 'url.fragment', + type: 'keyword', + }, + 'url.full': { + category: 'url', + description: + 'If full URLs are important to your use case, they should be stored in `url.full`, whether this field is reconstructed or present in the event source.', + example: 'https://www.elastic.co:443/search?q=elasticsearch#top', + name: 'url.full', + type: 'keyword', + }, + 'url.original': { + category: 'url', + description: + 'Unmodified original url as seen in the event source. Note that in network monitoring, the observed URL may be a full URL, whereas in access logs, the URL is often just represented as a path. This field is meant to represent the URL as it was observed, complete or not.', + example: 'https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch', + name: 'url.original', + type: 'keyword', + }, + 'url.password': { + category: 'url', + description: 'Password of the request.', + name: 'url.password', + type: 'keyword', + }, + 'url.path': { + category: 'url', + description: 'Path of the request, such as "/search".', + name: 'url.path', + type: 'keyword', + }, + 'url.port': { + category: 'url', + description: 'Port of the request, such as 443.', + example: 443, + name: 'url.port', + type: 'long', + format: 'string', + }, + 'url.query': { + category: 'url', + description: + 'The query field describes the query string of the request, such as "q=elasticsearch". The `?` is excluded from the query string. If a URL contains no `?`, there is no query field. If there is a `?` but no query, the query field exists with an empty string. The `exists` query can be used to differentiate between the two cases.', + name: 'url.query', + type: 'keyword', + }, + 'url.registered_domain': { + category: 'url', + description: + 'The highest registered url domain, stripped of the subdomain. For example, the registered domain for "foo.google.com" is "google.com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last two labels will not work well for TLDs such as "co.uk".', + example: 'google.com', + name: 'url.registered_domain', + type: 'keyword', + }, + 'url.scheme': { + category: 'url', + description: 'Scheme of the request, such as "https". Note: The `:` is not part of the scheme.', + example: 'https', + name: 'url.scheme', + type: 'keyword', + }, + 'url.top_level_domain': { + category: 'url', + description: + 'The effective top level domain (eTLD), also known as the domain suffix, is the last part of the domain name. For example, the top level domain for google.com is "com". This value can be determined precisely with a list like the public suffix list (http://publicsuffix.org). Trying to approximate this by simply taking the last label will not work well for effective TLDs such as "co.uk".', + example: 'co.uk', + name: 'url.top_level_domain', + type: 'keyword', + }, + 'url.username': { + category: 'url', + description: 'Username of the request.', + name: 'url.username', + type: 'keyword', + }, + 'user.domain': { + category: 'user', + description: + 'Name of the directory the user is a member of. For example, an LDAP or Active Directory domain name.', + name: 'user.domain', + type: 'keyword', + }, + 'user.email': { + category: 'user', + description: 'User email address.', + name: 'user.email', + type: 'keyword', + }, + 'user.full_name': { + category: 'user', + description: "User's full name, if available.", + example: 'Albert Einstein', + name: 'user.full_name', + type: 'keyword', + }, + 'user.group.domain': { + category: 'user', + description: + 'Name of the directory the group is a member of. For example, an LDAP or Active Directory domain name.', + name: 'user.group.domain', + type: 'keyword', + }, + 'user.group.id': { + category: 'user', + description: 'Unique identifier for the group on the system/platform.', + name: 'user.group.id', + type: 'keyword', + }, + 'user.group.name': { + category: 'user', + description: 'Name of the group.', + name: 'user.group.name', + type: 'keyword', + }, + 'user.hash': { + category: 'user', + description: + 'Unique user hash to correlate information for a user in anonymized form. Useful if `user.id` or `user.name` contain confidential information and cannot be used.', + name: 'user.hash', + type: 'keyword', + }, + 'user.id': { + category: 'user', + description: 'Unique identifiers of the user.', + name: 'user.id', + type: 'keyword', + }, + 'user.name': { + category: 'user', + description: 'Short name or login of the user.', + example: 'albert', + name: 'user.name', + type: 'keyword', + }, + 'user_agent.device.name': { + category: 'user_agent', + description: 'Name of the device.', + example: 'iPhone', + name: 'user_agent.device.name', + type: 'keyword', + }, + 'user_agent.name': { + category: 'user_agent', + description: 'Name of the user agent.', + example: 'Safari', + name: 'user_agent.name', + type: 'keyword', + }, + 'user_agent.original': { + category: 'user_agent', + description: 'Unparsed user_agent string.', + example: + 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', + name: 'user_agent.original', + type: 'keyword', + }, + 'user_agent.os.family': { + category: 'user_agent', + description: 'OS family (such as redhat, debian, freebsd, windows).', + example: 'debian', + name: 'user_agent.os.family', + type: 'keyword', + }, + 'user_agent.os.full': { + category: 'user_agent', + description: 'Operating system name, including the version or code name.', + example: 'Mac OS Mojave', + name: 'user_agent.os.full', + type: 'keyword', + }, + 'user_agent.os.kernel': { + category: 'user_agent', + description: 'Operating system kernel version as a raw string.', + example: '4.4.0-112-generic', + name: 'user_agent.os.kernel', + type: 'keyword', + }, + 'user_agent.os.name': { + category: 'user_agent', + description: 'Operating system name, without the version.', + example: 'Mac OS X', + name: 'user_agent.os.name', + type: 'keyword', + }, + 'user_agent.os.platform': { + category: 'user_agent', + description: 'Operating system platform (such centos, ubuntu, windows).', + example: 'darwin', + name: 'user_agent.os.platform', + type: 'keyword', + }, + 'user_agent.os.version': { + category: 'user_agent', + description: 'Operating system version as a raw string.', + example: '10.14.1', + name: 'user_agent.os.version', + type: 'keyword', + }, + 'user_agent.version': { + category: 'user_agent', + description: 'Version of the user agent.', + example: 12, + name: 'user_agent.version', + type: 'keyword', + }, + 'vlan.id': { + category: 'vlan', + description: 'VLAN ID as reported by the observer.', + example: 10, + name: 'vlan.id', + type: 'keyword', + }, + 'vlan.name': { + category: 'vlan', + description: 'Optional VLAN name as reported by the observer.', + example: 'outside', + name: 'vlan.name', + type: 'keyword', + }, + 'vulnerability.category': { + category: 'vulnerability', + description: + 'The type of system or architecture that the vulnerability affects. These may be platform-specific (for example, Debian or SUSE) or general (for example, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys vulnerability categories]) This field must be an array.', + example: '["Firewall"]', + name: 'vulnerability.category', + type: 'keyword', + }, + 'vulnerability.classification': { + category: 'vulnerability', + description: + 'The classification of the vulnerability scoring system. For example (https://www.first.org/cvss/)', + example: 'CVSS', + name: 'vulnerability.classification', + type: 'keyword', + }, + 'vulnerability.description': { + category: 'vulnerability', + description: + 'The description of the vulnerability that provides additional context of the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common Vulnerabilities and Exposure CVE description])', + example: 'In macOS before 2.12.6, there is a vulnerability in the RPC...', + name: 'vulnerability.description', + type: 'keyword', + }, + 'vulnerability.enumeration': { + category: 'vulnerability', + description: + 'The type of identifier used for this vulnerability. For example (https://cve.mitre.org/about/)', + example: 'CVE', + name: 'vulnerability.enumeration', + type: 'keyword', + }, + 'vulnerability.id': { + category: 'vulnerability', + description: + 'The identification (ID) is the number portion of a vulnerability entry. It includes a unique identification number for the vulnerability. For example (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities and Exposure CVE ID]', + example: 'CVE-2019-00001', + name: 'vulnerability.id', + type: 'keyword', + }, + 'vulnerability.reference': { + category: 'vulnerability', + description: + 'A resource that provides additional information, context, and mitigations for the identified vulnerability.', + example: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111', + name: 'vulnerability.reference', + type: 'keyword', + }, + 'vulnerability.report_id': { + category: 'vulnerability', + description: 'The report or scan identification number.', + example: 20191018.0001, + name: 'vulnerability.report_id', + type: 'keyword', + }, + 'vulnerability.scanner.vendor': { + category: 'vulnerability', + description: 'The name of the vulnerability scanner vendor.', + example: 'Tenable', + name: 'vulnerability.scanner.vendor', + type: 'keyword', + }, + 'vulnerability.score.base': { + category: 'vulnerability', + description: + 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe. Base scores cover an assessment for exploitability metrics (attack vector, complexity, privileges, and user interaction), impact metrics (confidentiality, integrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document)', + example: 5.5, + name: 'vulnerability.score.base', + type: 'float', + }, + 'vulnerability.score.environmental': { + category: 'vulnerability', + description: + 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe. Environmental scores cover an assessment for any modified Base metrics, confidentiality, integrity, and availability requirements. For example (https://www.first.org/cvss/specification-document)', + example: 5.5, + name: 'vulnerability.score.environmental', + type: 'float', + }, + 'vulnerability.score.temporal': { + category: 'vulnerability', + description: + 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe. Temporal scores cover an assessment for code maturity, remediation level, and confidence. For example (https://www.first.org/cvss/specification-document)', + name: 'vulnerability.score.temporal', + type: 'float', + }, + 'vulnerability.score.version': { + category: 'vulnerability', + description: + 'The National Vulnerability Database (NVD) provides qualitative severity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score ranges in addition to the severity ratings for CVSS v3.0 as they are defined in the CVSS v3.0 specification. CVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit organization, whose mission is to help computer security incident response teams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss)', + example: 2, + name: 'vulnerability.score.version', + type: 'keyword', + }, + 'vulnerability.severity': { + category: 'vulnerability', + description: + 'The severity of the vulnerability can help with metrics and internal prioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss)', + example: 'Critical', + name: 'vulnerability.severity', + type: 'keyword', + }, + 'agent.hostname': { + category: 'agent', + description: + 'Deprecated - use agent.name or agent.id to identify an agent. Hostname of the agent. ', + name: 'agent.hostname', + type: 'keyword', + }, + 'beat.timezone': { + category: 'beat', + name: 'beat.timezone', + type: 'alias', + }, + fields: { + category: 'base', + description: 'Contains user configurable fields. ', + name: 'fields', + type: 'object', + }, + 'beat.name': { + category: 'beat', + name: 'beat.name', + type: 'alias', + }, + 'beat.hostname': { + category: 'beat', + name: 'beat.hostname', + type: 'alias', + }, + 'timeseries.instance': { + category: 'timeseries', + description: 'Time series instance id', + name: 'timeseries.instance', + type: 'keyword', + }, + 'cloud.project.id': { + category: 'cloud', + description: 'Name of the project in Google Cloud. ', + example: 'project-x', + name: 'cloud.project.id', + }, + 'cloud.image.id': { + category: 'cloud', + description: 'Image ID for the cloud instance. ', + example: 'ami-abcd1234', + name: 'cloud.image.id', + }, + 'meta.cloud.provider': { + category: 'meta', + name: 'meta.cloud.provider', + type: 'alias', + }, + 'meta.cloud.instance_id': { + category: 'meta', + name: 'meta.cloud.instance_id', + type: 'alias', + }, + 'meta.cloud.instance_name': { + category: 'meta', + name: 'meta.cloud.instance_name', + type: 'alias', + }, + 'meta.cloud.machine_type': { + category: 'meta', + name: 'meta.cloud.machine_type', + type: 'alias', + }, + 'meta.cloud.availability_zone': { + category: 'meta', + name: 'meta.cloud.availability_zone', + type: 'alias', + }, + 'meta.cloud.project_id': { + category: 'meta', + name: 'meta.cloud.project_id', + type: 'alias', + }, + 'meta.cloud.region': { + category: 'meta', + name: 'meta.cloud.region', + type: 'alias', + }, + 'docker.container.id': { + category: 'docker', + name: 'docker.container.id', + type: 'alias', + }, + 'docker.container.image': { + category: 'docker', + name: 'docker.container.image', + type: 'alias', + }, + 'docker.container.name': { + category: 'docker', + name: 'docker.container.name', + type: 'alias', + }, + 'docker.container.labels': { + category: 'docker', + description: 'Image labels. ', + name: 'docker.container.labels', + type: 'object', + }, + 'host.containerized': { + category: 'host', + description: 'If the host is a container. ', + name: 'host.containerized', + type: 'boolean', + }, + 'host.os.build': { + category: 'host', + description: 'OS build information. ', + example: '18D109', + name: 'host.os.build', + type: 'keyword', + }, + 'host.os.codename': { + category: 'host', + description: 'OS codename, if any. ', + example: 'stretch', + name: 'host.os.codename', + type: 'keyword', + }, + 'kubernetes.pod.name': { + category: 'kubernetes', + description: 'Kubernetes pod name ', + name: 'kubernetes.pod.name', + type: 'keyword', + }, + 'kubernetes.pod.uid': { + category: 'kubernetes', + description: 'Kubernetes Pod UID ', + name: 'kubernetes.pod.uid', + type: 'keyword', + }, + 'kubernetes.namespace': { + category: 'kubernetes', + description: 'Kubernetes namespace ', + name: 'kubernetes.namespace', + type: 'keyword', + }, + 'kubernetes.node.name': { + category: 'kubernetes', + description: 'Kubernetes node name ', + name: 'kubernetes.node.name', + type: 'keyword', + }, + 'kubernetes.labels.*': { + category: 'kubernetes', + description: 'Kubernetes labels map ', + name: 'kubernetes.labels.*', + type: 'object', + }, + 'kubernetes.annotations.*': { + category: 'kubernetes', + description: 'Kubernetes annotations map ', + name: 'kubernetes.annotations.*', + type: 'object', + }, + 'kubernetes.replicaset.name': { + category: 'kubernetes', + description: 'Kubernetes replicaset name ', + name: 'kubernetes.replicaset.name', + type: 'keyword', + }, + 'kubernetes.deployment.name': { + category: 'kubernetes', + description: 'Kubernetes deployment name ', + name: 'kubernetes.deployment.name', + type: 'keyword', + }, + 'kubernetes.statefulset.name': { + category: 'kubernetes', + description: 'Kubernetes statefulset name ', + name: 'kubernetes.statefulset.name', + type: 'keyword', + }, + 'kubernetes.container.name': { + category: 'kubernetes', + description: 'Kubernetes container name ', + name: 'kubernetes.container.name', + type: 'keyword', + }, + 'kubernetes.container.image': { + category: 'kubernetes', + description: 'Kubernetes container image ', + name: 'kubernetes.container.image', + type: 'keyword', + }, + 'process.exe': { + category: 'process', + name: 'process.exe', + type: 'alias', + }, + 'jolokia.agent.version': { + category: 'jolokia', + description: 'Version number of jolokia agent. ', + name: 'jolokia.agent.version', + type: 'keyword', + }, + 'jolokia.agent.id': { + category: 'jolokia', + description: + 'Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type. ', + name: 'jolokia.agent.id', + type: 'keyword', + }, + 'jolokia.server.product': { + category: 'jolokia', + description: 'The container product if detected. ', + name: 'jolokia.server.product', + type: 'keyword', + }, + 'jolokia.server.version': { + category: 'jolokia', + description: "The container's version (if detected). ", + name: 'jolokia.server.version', + type: 'keyword', + }, + 'jolokia.server.vendor': { + category: 'jolokia', + description: 'The vendor of the container the agent is running in. ', + name: 'jolokia.server.vendor', + type: 'keyword', + }, + 'jolokia.url': { + category: 'jolokia', + description: 'The URL how this agent can be contacted. ', + name: 'jolokia.url', + type: 'keyword', + }, + 'jolokia.secured': { + category: 'jolokia', + description: 'Whether the agent was configured for authentication or not. ', + name: 'jolokia.secured', + type: 'boolean', + }, + 'file.setuid': { + category: 'file', + description: 'Set if the file has the `setuid` bit set. Omitted otherwise.', + example: 'true', + name: 'file.setuid', + type: 'boolean', + }, + 'file.setgid': { + category: 'file', + description: 'Set if the file has the `setgid` bit set. Omitted otherwise.', + example: 'true', + name: 'file.setgid', + type: 'boolean', + }, + 'file.origin': { + category: 'file', + description: + 'An array of strings describing a possible external origin for this file. For example, the URL it was downloaded from. Only supported in macOS, via the kMDItemWhereFroms attribute. Omitted if origin information is not available. ', + name: 'file.origin', + type: 'keyword', + }, + 'file.selinux.user': { + category: 'file', + description: 'The owner of the object.', + name: 'file.selinux.user', + type: 'keyword', + }, + 'file.selinux.role': { + category: 'file', + description: "The object's SELinux role.", + name: 'file.selinux.role', + type: 'keyword', + }, + 'file.selinux.domain': { + category: 'file', + description: "The object's SELinux domain or type.", + name: 'file.selinux.domain', + type: 'keyword', + }, + 'file.selinux.level': { + category: 'file', + description: "The object's SELinux level.", + example: 's0', + name: 'file.selinux.level', + type: 'keyword', + }, + 'user.audit.id': { + category: 'user', + description: 'Audit user ID.', + name: 'user.audit.id', + type: 'keyword', + }, + 'user.audit.name': { + category: 'user', + description: 'Audit user name.', + name: 'user.audit.name', + type: 'keyword', + }, + 'user.effective.id': { + category: 'user', + description: 'Effective user ID.', + name: 'user.effective.id', + type: 'keyword', + }, + 'user.effective.name': { + category: 'user', + description: 'Effective user name.', + name: 'user.effective.name', + type: 'keyword', + }, + 'user.effective.group.id': { + category: 'user', + description: 'Effective group ID.', + name: 'user.effective.group.id', + type: 'keyword', + }, + 'user.effective.group.name': { + category: 'user', + description: 'Effective group name.', + name: 'user.effective.group.name', + type: 'keyword', + }, + 'user.filesystem.id': { + category: 'user', + description: 'Filesystem user ID.', + name: 'user.filesystem.id', + type: 'keyword', + }, + 'user.filesystem.name': { + category: 'user', + description: 'Filesystem user name.', + name: 'user.filesystem.name', + type: 'keyword', + }, + 'user.filesystem.group.id': { + category: 'user', + description: 'Filesystem group ID.', + name: 'user.filesystem.group.id', + type: 'keyword', + }, + 'user.filesystem.group.name': { + category: 'user', + description: 'Filesystem group name.', + name: 'user.filesystem.group.name', + type: 'keyword', + }, + 'user.saved.id': { + category: 'user', + description: 'Saved user ID.', + name: 'user.saved.id', + type: 'keyword', + }, + 'user.saved.name': { + category: 'user', + description: 'Saved user name.', + name: 'user.saved.name', + type: 'keyword', + }, + 'user.saved.group.id': { + category: 'user', + description: 'Saved group ID.', + name: 'user.saved.group.id', + type: 'keyword', + }, + 'user.saved.group.name': { + category: 'user', + description: 'Saved group name.', + name: 'user.saved.group.name', + type: 'keyword', + }, + 'user.auid': { + category: 'user', + name: 'user.auid', + type: 'alias', + }, + 'user.uid': { + category: 'user', + name: 'user.uid', + type: 'alias', + }, + 'user.euid': { + category: 'user', + name: 'user.euid', + type: 'alias', + }, + 'user.fsuid': { + category: 'user', + name: 'user.fsuid', + type: 'alias', + }, + 'user.suid': { + category: 'user', + name: 'user.suid', + type: 'alias', + }, + 'user.gid': { + category: 'user', + name: 'user.gid', + type: 'alias', + }, + 'user.egid': { + category: 'user', + name: 'user.egid', + type: 'alias', + }, + 'user.sgid': { + category: 'user', + name: 'user.sgid', + type: 'alias', + }, + 'user.fsgid': { + category: 'user', + name: 'user.fsgid', + type: 'alias', + }, + 'user.name_map.auid': { + category: 'user', + name: 'user.name_map.auid', + type: 'alias', + }, + 'user.name_map.uid': { + category: 'user', + name: 'user.name_map.uid', + type: 'alias', + }, + 'user.name_map.euid': { + category: 'user', + name: 'user.name_map.euid', + type: 'alias', + }, + 'user.name_map.fsuid': { + category: 'user', + name: 'user.name_map.fsuid', + type: 'alias', + }, + 'user.name_map.suid': { + category: 'user', + name: 'user.name_map.suid', + type: 'alias', + }, + 'user.name_map.gid': { + category: 'user', + name: 'user.name_map.gid', + type: 'alias', + }, + 'user.name_map.egid': { + category: 'user', + name: 'user.name_map.egid', + type: 'alias', + }, + 'user.name_map.sgid': { + category: 'user', + name: 'user.name_map.sgid', + type: 'alias', + }, + 'user.name_map.fsgid': { + category: 'user', + name: 'user.name_map.fsgid', + type: 'alias', + }, + 'user.selinux.user': { + category: 'user', + description: 'account submitted for authentication', + name: 'user.selinux.user', + type: 'keyword', + }, + 'user.selinux.role': { + category: 'user', + description: "user's SELinux role", + name: 'user.selinux.role', + type: 'keyword', + }, + 'user.selinux.domain': { + category: 'user', + description: "The actor's SELinux domain or type.", + name: 'user.selinux.domain', + type: 'keyword', + }, + 'user.selinux.level': { + category: 'user', + description: "The actor's SELinux level.", + example: 's0', + name: 'user.selinux.level', + type: 'keyword', + }, + 'user.selinux.category': { + category: 'user', + description: "The actor's SELinux category or compartments.", + name: 'user.selinux.category', + type: 'keyword', + }, + 'process.cwd': { + category: 'process', + description: 'The current working directory.', + name: 'process.cwd', + type: 'alias', + }, + 'source.path': { + category: 'source', + description: 'This is the path associated with a unix socket.', + name: 'source.path', + type: 'keyword', + }, + 'destination.path': { + category: 'destination', + description: 'This is the path associated with a unix socket.', + name: 'destination.path', + type: 'keyword', + }, + 'auditd.message_type': { + category: 'auditd', + description: 'The audit message type (e.g. syscall or apparmor_denied). ', + example: 'syscall', + name: 'auditd.message_type', + type: 'keyword', + }, + 'auditd.sequence': { + category: 'auditd', + description: + 'The sequence number of the event as assigned by the kernel. Sequence numbers are stored as a uint32 in the kernel and can rollover. ', + name: 'auditd.sequence', + type: 'long', + }, + 'auditd.session': { + category: 'auditd', + description: + 'The session ID assigned to a login. All events related to a login session will have the same value. ', + name: 'auditd.session', + type: 'keyword', + }, + 'auditd.result': { + category: 'auditd', + description: 'The result of the audited operation (success/fail).', + example: 'success or fail', + name: 'auditd.result', + type: 'keyword', + }, + 'auditd.summary.actor.primary': { + category: 'auditd', + description: + "The primary identity of the actor. This is the actor's original login ID. It will not change even if the user changes to another account. ", + name: 'auditd.summary.actor.primary', + type: 'keyword', + }, + 'auditd.summary.actor.secondary': { + category: 'auditd', + description: + 'The secondary identity of the actor. This is typically the same as the primary, except for when the user has used `su`.', + name: 'auditd.summary.actor.secondary', + type: 'keyword', + }, + 'auditd.summary.object.type': { + category: 'auditd', + description: 'A description of the what the "thing" is (e.g. file, socket, user-session). ', + name: 'auditd.summary.object.type', + type: 'keyword', + }, + 'auditd.summary.object.primary': { + category: 'auditd', + description: '', + name: 'auditd.summary.object.primary', + type: 'keyword', + }, + 'auditd.summary.object.secondary': { + category: 'auditd', + description: '', + name: 'auditd.summary.object.secondary', + type: 'keyword', + }, + 'auditd.summary.how': { + category: 'auditd', + description: + 'This describes how the action was performed. Usually this is the exe or command that was being executed that triggered the event. ', + name: 'auditd.summary.how', + type: 'keyword', + }, + 'auditd.paths.inode': { + category: 'auditd', + description: 'inode number', + name: 'auditd.paths.inode', + type: 'keyword', + }, + 'auditd.paths.dev': { + category: 'auditd', + description: 'device name as found in /dev', + name: 'auditd.paths.dev', + type: 'keyword', + }, + 'auditd.paths.obj_user': { + category: 'auditd', + description: '', + name: 'auditd.paths.obj_user', + type: 'keyword', + }, + 'auditd.paths.obj_role': { + category: 'auditd', + description: '', + name: 'auditd.paths.obj_role', + type: 'keyword', + }, + 'auditd.paths.obj_domain': { + category: 'auditd', + description: '', + name: 'auditd.paths.obj_domain', + type: 'keyword', + }, + 'auditd.paths.obj_level': { + category: 'auditd', + description: '', + name: 'auditd.paths.obj_level', + type: 'keyword', + }, + 'auditd.paths.objtype': { + category: 'auditd', + description: '', + name: 'auditd.paths.objtype', + type: 'keyword', + }, + 'auditd.paths.ouid': { + category: 'auditd', + description: 'file owner user ID', + name: 'auditd.paths.ouid', + type: 'keyword', + }, + 'auditd.paths.rdev': { + category: 'auditd', + description: 'the device identifier (special files only)', + name: 'auditd.paths.rdev', + type: 'keyword', + }, + 'auditd.paths.nametype': { + category: 'auditd', + description: 'kind of file operation being referenced', + name: 'auditd.paths.nametype', + type: 'keyword', + }, + 'auditd.paths.ogid': { + category: 'auditd', + description: 'file owner group ID', + name: 'auditd.paths.ogid', + type: 'keyword', + }, + 'auditd.paths.item': { + category: 'auditd', + description: 'which item is being recorded', + name: 'auditd.paths.item', + type: 'keyword', + }, + 'auditd.paths.mode': { + category: 'auditd', + description: 'mode flags on a file', + name: 'auditd.paths.mode', + type: 'keyword', + }, + 'auditd.paths.name': { + category: 'auditd', + description: 'file name in avcs', + name: 'auditd.paths.name', + type: 'keyword', + }, + 'auditd.data.action': { + category: 'auditd', + description: 'netfilter packet disposition', + name: 'auditd.data.action', + type: 'keyword', + }, + 'auditd.data.minor': { + category: 'auditd', + description: 'device minor number', + name: 'auditd.data.minor', + type: 'keyword', + }, + 'auditd.data.acct': { + category: 'auditd', + description: "a user's account name", + name: 'auditd.data.acct', + type: 'keyword', + }, + 'auditd.data.addr': { + category: 'auditd', + description: 'the remote address that the user is connecting from', + name: 'auditd.data.addr', + type: 'keyword', + }, + 'auditd.data.cipher': { + category: 'auditd', + description: 'name of crypto cipher selected', + name: 'auditd.data.cipher', + type: 'keyword', + }, + 'auditd.data.id': { + category: 'auditd', + description: 'during account changes', + name: 'auditd.data.id', + type: 'keyword', + }, + 'auditd.data.entries': { + category: 'auditd', + description: 'number of entries in the netfilter table', + name: 'auditd.data.entries', + type: 'keyword', + }, + 'auditd.data.kind': { + category: 'auditd', + description: 'server or client in crypto operation', + name: 'auditd.data.kind', + type: 'keyword', + }, + 'auditd.data.ksize': { + category: 'auditd', + description: 'key size for crypto operation', + name: 'auditd.data.ksize', + type: 'keyword', + }, + 'auditd.data.spid': { + category: 'auditd', + description: 'sent process ID', + name: 'auditd.data.spid', + type: 'keyword', + }, + 'auditd.data.arch': { + category: 'auditd', + description: 'the elf architecture flags', + name: 'auditd.data.arch', + type: 'keyword', + }, + 'auditd.data.argc': { + category: 'auditd', + description: 'the number of arguments to an execve syscall', + name: 'auditd.data.argc', + type: 'keyword', + }, + 'auditd.data.major': { + category: 'auditd', + description: 'device major number', + name: 'auditd.data.major', + type: 'keyword', + }, + 'auditd.data.unit': { + category: 'auditd', + description: 'systemd unit', + name: 'auditd.data.unit', + type: 'keyword', + }, + 'auditd.data.table': { + category: 'auditd', + description: 'netfilter table name', + name: 'auditd.data.table', + type: 'keyword', + }, + 'auditd.data.terminal': { + category: 'auditd', + description: 'terminal name the user is running programs on', + name: 'auditd.data.terminal', + type: 'keyword', + }, + 'auditd.data.grantors': { + category: 'auditd', + description: 'pam modules approving the action', + name: 'auditd.data.grantors', + type: 'keyword', + }, + 'auditd.data.direction': { + category: 'auditd', + description: 'direction of crypto operation', + name: 'auditd.data.direction', + type: 'keyword', + }, + 'auditd.data.op': { + category: 'auditd', + description: 'the operation being performed that is audited', + name: 'auditd.data.op', + type: 'keyword', + }, + 'auditd.data.tty': { + category: 'auditd', + description: 'tty udevice the user is running programs on', + name: 'auditd.data.tty', + type: 'keyword', + }, + 'auditd.data.syscall': { + category: 'auditd', + description: 'syscall number in effect when the event occurred', + name: 'auditd.data.syscall', + type: 'keyword', + }, + 'auditd.data.data': { + category: 'auditd', + description: 'TTY text', + name: 'auditd.data.data', + type: 'keyword', + }, + 'auditd.data.family': { + category: 'auditd', + description: 'netfilter protocol', + name: 'auditd.data.family', + type: 'keyword', + }, + 'auditd.data.mac': { + category: 'auditd', + description: 'crypto MAC algorithm selected', + name: 'auditd.data.mac', + type: 'keyword', + }, + 'auditd.data.pfs': { + category: 'auditd', + description: 'perfect forward secrecy method', + name: 'auditd.data.pfs', + type: 'keyword', + }, + 'auditd.data.items': { + category: 'auditd', + description: 'the number of path records in the event', + name: 'auditd.data.items', + type: 'keyword', + }, + 'auditd.data.a0': { + category: 'auditd', + description: '', + name: 'auditd.data.a0', + type: 'keyword', + }, + 'auditd.data.a1': { + category: 'auditd', + description: '', + name: 'auditd.data.a1', + type: 'keyword', + }, + 'auditd.data.a2': { + category: 'auditd', + description: '', + name: 'auditd.data.a2', + type: 'keyword', + }, + 'auditd.data.a3': { + category: 'auditd', + description: '', + name: 'auditd.data.a3', + type: 'keyword', + }, + 'auditd.data.hostname': { + category: 'auditd', + description: 'the hostname that the user is connecting from', + name: 'auditd.data.hostname', + type: 'keyword', + }, + 'auditd.data.lport': { + category: 'auditd', + description: 'local network port', + name: 'auditd.data.lport', + type: 'keyword', + }, + 'auditd.data.rport': { + category: 'auditd', + description: 'remote port number', + name: 'auditd.data.rport', + type: 'keyword', + }, + 'auditd.data.exit': { + category: 'auditd', + description: 'syscall exit code', + name: 'auditd.data.exit', + type: 'keyword', + }, + 'auditd.data.fp': { + category: 'auditd', + description: 'crypto key finger print', + name: 'auditd.data.fp', + type: 'keyword', + }, + 'auditd.data.laddr': { + category: 'auditd', + description: 'local network address', + name: 'auditd.data.laddr', + type: 'keyword', + }, + 'auditd.data.sport': { + category: 'auditd', + description: 'local port number', + name: 'auditd.data.sport', + type: 'keyword', + }, + 'auditd.data.capability': { + category: 'auditd', + description: 'posix capabilities', + name: 'auditd.data.capability', + type: 'keyword', + }, + 'auditd.data.nargs': { + category: 'auditd', + description: 'the number of arguments to a socket call', + name: 'auditd.data.nargs', + type: 'keyword', + }, + 'auditd.data.new-enabled': { + category: 'auditd', + description: 'new TTY audit enabled setting', + name: 'auditd.data.new-enabled', + type: 'keyword', + }, + 'auditd.data.audit_backlog_limit': { + category: 'auditd', + description: "audit system's backlog queue size", + name: 'auditd.data.audit_backlog_limit', + type: 'keyword', + }, + 'auditd.data.dir': { + category: 'auditd', + description: 'directory name', + name: 'auditd.data.dir', + type: 'keyword', + }, + 'auditd.data.cap_pe': { + category: 'auditd', + description: 'process effective capability map', + name: 'auditd.data.cap_pe', + type: 'keyword', + }, + 'auditd.data.model': { + category: 'auditd', + description: 'security model being used for virt', + name: 'auditd.data.model', + type: 'keyword', + }, + 'auditd.data.new_pp': { + category: 'auditd', + description: 'new process permitted capability map', + name: 'auditd.data.new_pp', + type: 'keyword', + }, + 'auditd.data.old-enabled': { + category: 'auditd', + description: 'present TTY audit enabled setting', + name: 'auditd.data.old-enabled', + type: 'keyword', + }, + 'auditd.data.oauid': { + category: 'auditd', + description: "object's login user ID", + name: 'auditd.data.oauid', + type: 'keyword', + }, + 'auditd.data.old': { + category: 'auditd', + description: 'old value', + name: 'auditd.data.old', + type: 'keyword', + }, + 'auditd.data.banners': { + category: 'auditd', + description: 'banners used on printed page', + name: 'auditd.data.banners', + type: 'keyword', + }, + 'auditd.data.feature': { + category: 'auditd', + description: 'kernel feature being changed', + name: 'auditd.data.feature', + type: 'keyword', + }, + 'auditd.data.vm-ctx': { + category: 'auditd', + description: "the vm's context string", + name: 'auditd.data.vm-ctx', + type: 'keyword', + }, + 'auditd.data.opid': { + category: 'auditd', + description: "object's process ID", + name: 'auditd.data.opid', + type: 'keyword', + }, + 'auditd.data.seperms': { + category: 'auditd', + description: 'SELinux permissions being used', + name: 'auditd.data.seperms', + type: 'keyword', + }, + 'auditd.data.seresult': { + category: 'auditd', + description: 'SELinux AVC decision granted/denied', + name: 'auditd.data.seresult', + type: 'keyword', + }, + 'auditd.data.new-rng': { + category: 'auditd', + description: 'device name of rng being added from a vm', + name: 'auditd.data.new-rng', + type: 'keyword', + }, + 'auditd.data.old-net': { + category: 'auditd', + description: 'present MAC address assigned to vm', + name: 'auditd.data.old-net', + type: 'keyword', + }, + 'auditd.data.sigev_signo': { + category: 'auditd', + description: 'signal number', + name: 'auditd.data.sigev_signo', + type: 'keyword', + }, + 'auditd.data.ino': { + category: 'auditd', + description: 'inode number', + name: 'auditd.data.ino', + type: 'keyword', + }, + 'auditd.data.old_enforcing': { + category: 'auditd', + description: 'old MAC enforcement status', + name: 'auditd.data.old_enforcing', + type: 'keyword', + }, + 'auditd.data.old-vcpu': { + category: 'auditd', + description: 'present number of CPU cores', + name: 'auditd.data.old-vcpu', + type: 'keyword', + }, + 'auditd.data.range': { + category: 'auditd', + description: "user's SE Linux range", + name: 'auditd.data.range', + type: 'keyword', + }, + 'auditd.data.res': { + category: 'auditd', + description: 'result of the audited operation(success/fail)', + name: 'auditd.data.res', + type: 'keyword', + }, + 'auditd.data.added': { + category: 'auditd', + description: 'number of new files detected', + name: 'auditd.data.added', + type: 'keyword', + }, + 'auditd.data.fam': { + category: 'auditd', + description: 'socket address family', + name: 'auditd.data.fam', + type: 'keyword', + }, + 'auditd.data.nlnk-pid': { + category: 'auditd', + description: 'pid of netlink packet sender', + name: 'auditd.data.nlnk-pid', + type: 'keyword', + }, + 'auditd.data.subj': { + category: 'auditd', + description: "lspp subject's context string", + name: 'auditd.data.subj', + type: 'keyword', + }, + 'auditd.data.a[0-3]': { + category: 'auditd', + description: 'the arguments to a syscall', + name: 'auditd.data.a[0-3]', + type: 'keyword', + }, + 'auditd.data.cgroup': { + category: 'auditd', + description: 'path to cgroup in sysfs', + name: 'auditd.data.cgroup', + type: 'keyword', + }, + 'auditd.data.kernel': { + category: 'auditd', + description: "kernel's version number", + name: 'auditd.data.kernel', + type: 'keyword', + }, + 'auditd.data.ocomm': { + category: 'auditd', + description: "object's command line name", + name: 'auditd.data.ocomm', + type: 'keyword', + }, + 'auditd.data.new-net': { + category: 'auditd', + description: 'MAC address being assigned to vm', + name: 'auditd.data.new-net', + type: 'keyword', + }, + 'auditd.data.permissive': { + category: 'auditd', + description: 'SELinux is in permissive mode', + name: 'auditd.data.permissive', + type: 'keyword', + }, + 'auditd.data.class': { + category: 'auditd', + description: 'resource class assigned to vm', + name: 'auditd.data.class', + type: 'keyword', + }, + 'auditd.data.compat': { + category: 'auditd', + description: 'is_compat_task result', + name: 'auditd.data.compat', + type: 'keyword', + }, + 'auditd.data.fi': { + category: 'auditd', + description: 'file assigned inherited capability map', + name: 'auditd.data.fi', + type: 'keyword', + }, + 'auditd.data.changed': { + category: 'auditd', + description: 'number of changed files', + name: 'auditd.data.changed', + type: 'keyword', + }, + 'auditd.data.msg': { + category: 'auditd', + description: 'the payload of the audit record', + name: 'auditd.data.msg', + type: 'keyword', + }, + 'auditd.data.dport': { + category: 'auditd', + description: 'remote port number', + name: 'auditd.data.dport', + type: 'keyword', + }, + 'auditd.data.new-seuser': { + category: 'auditd', + description: 'new SELinux user', + name: 'auditd.data.new-seuser', + type: 'keyword', + }, + 'auditd.data.invalid_context': { + category: 'auditd', + description: 'SELinux context', + name: 'auditd.data.invalid_context', + type: 'keyword', + }, + 'auditd.data.dmac': { + category: 'auditd', + description: 'remote MAC address', + name: 'auditd.data.dmac', + type: 'keyword', + }, + 'auditd.data.ipx-net': { + category: 'auditd', + description: 'IPX network number', + name: 'auditd.data.ipx-net', + type: 'keyword', + }, + 'auditd.data.iuid': { + category: 'auditd', + description: "ipc object's user ID", + name: 'auditd.data.iuid', + type: 'keyword', + }, + 'auditd.data.macproto': { + category: 'auditd', + description: 'ethernet packet type ID field', + name: 'auditd.data.macproto', + type: 'keyword', + }, + 'auditd.data.obj': { + category: 'auditd', + description: 'lspp object context string', + name: 'auditd.data.obj', + type: 'keyword', + }, + 'auditd.data.ipid': { + category: 'auditd', + description: 'IP datagram fragment identifier', + name: 'auditd.data.ipid', + type: 'keyword', + }, + 'auditd.data.new-fs': { + category: 'auditd', + description: 'file system being added to vm', + name: 'auditd.data.new-fs', + type: 'keyword', + }, + 'auditd.data.vm-pid': { + category: 'auditd', + description: "vm's process ID", + name: 'auditd.data.vm-pid', + type: 'keyword', + }, + 'auditd.data.cap_pi': { + category: 'auditd', + description: 'process inherited capability map', + name: 'auditd.data.cap_pi', + type: 'keyword', + }, + 'auditd.data.old-auid': { + category: 'auditd', + description: 'previous auid value', + name: 'auditd.data.old-auid', + type: 'keyword', + }, + 'auditd.data.oses': { + category: 'auditd', + description: "object's session ID", + name: 'auditd.data.oses', + type: 'keyword', + }, + 'auditd.data.fd': { + category: 'auditd', + description: 'file descriptor number', + name: 'auditd.data.fd', + type: 'keyword', + }, + 'auditd.data.igid': { + category: 'auditd', + description: "ipc object's group ID", + name: 'auditd.data.igid', + type: 'keyword', + }, + 'auditd.data.new-disk': { + category: 'auditd', + description: 'disk being added to vm', + name: 'auditd.data.new-disk', + type: 'keyword', + }, + 'auditd.data.parent': { + category: 'auditd', + description: 'the inode number of the parent file', + name: 'auditd.data.parent', + type: 'keyword', + }, + 'auditd.data.len': { + category: 'auditd', + description: 'length', + name: 'auditd.data.len', + type: 'keyword', + }, + 'auditd.data.oflag': { + category: 'auditd', + description: 'open syscall flags', + name: 'auditd.data.oflag', + type: 'keyword', + }, + 'auditd.data.uuid': { + category: 'auditd', + description: 'a UUID', + name: 'auditd.data.uuid', + type: 'keyword', + }, + 'auditd.data.code': { + category: 'auditd', + description: 'seccomp action code', + name: 'auditd.data.code', + type: 'keyword', + }, + 'auditd.data.nlnk-grp': { + category: 'auditd', + description: 'netlink group number', + name: 'auditd.data.nlnk-grp', + type: 'keyword', + }, + 'auditd.data.cap_fp': { + category: 'auditd', + description: 'file permitted capability map', + name: 'auditd.data.cap_fp', + type: 'keyword', + }, + 'auditd.data.new-mem': { + category: 'auditd', + description: 'new amount of memory in KB', + name: 'auditd.data.new-mem', + type: 'keyword', + }, + 'auditd.data.seperm': { + category: 'auditd', + description: 'SELinux permission being decided on', + name: 'auditd.data.seperm', + type: 'keyword', + }, + 'auditd.data.enforcing': { + category: 'auditd', + description: 'new MAC enforcement status', + name: 'auditd.data.enforcing', + type: 'keyword', + }, + 'auditd.data.new-chardev': { + category: 'auditd', + description: 'new character device being assigned to vm', + name: 'auditd.data.new-chardev', + type: 'keyword', + }, + 'auditd.data.old-rng': { + category: 'auditd', + description: 'device name of rng being removed from a vm', + name: 'auditd.data.old-rng', + type: 'keyword', + }, + 'auditd.data.outif': { + category: 'auditd', + description: 'out interface number', + name: 'auditd.data.outif', + type: 'keyword', + }, + 'auditd.data.cmd': { + category: 'auditd', + description: 'command being executed', + name: 'auditd.data.cmd', + type: 'keyword', + }, + 'auditd.data.hook': { + category: 'auditd', + description: 'netfilter hook that packet came from', + name: 'auditd.data.hook', + type: 'keyword', + }, + 'auditd.data.new-level': { + category: 'auditd', + description: 'new run level', + name: 'auditd.data.new-level', + type: 'keyword', + }, + 'auditd.data.sauid': { + category: 'auditd', + description: 'sent login user ID', + name: 'auditd.data.sauid', + type: 'keyword', + }, + 'auditd.data.sig': { + category: 'auditd', + description: 'signal number', + name: 'auditd.data.sig', + type: 'keyword', + }, + 'auditd.data.audit_backlog_wait_time': { + category: 'auditd', + description: "audit system's backlog wait time", + name: 'auditd.data.audit_backlog_wait_time', + type: 'keyword', + }, + 'auditd.data.printer': { + category: 'auditd', + description: 'printer name', + name: 'auditd.data.printer', + type: 'keyword', + }, + 'auditd.data.old-mem': { + category: 'auditd', + description: 'present amount of memory in KB', + name: 'auditd.data.old-mem', + type: 'keyword', + }, + 'auditd.data.perm': { + category: 'auditd', + description: 'the file permission being used', + name: 'auditd.data.perm', + type: 'keyword', + }, + 'auditd.data.old_pi': { + category: 'auditd', + description: 'old process inherited capability map', + name: 'auditd.data.old_pi', + type: 'keyword', + }, + 'auditd.data.state': { + category: 'auditd', + description: 'audit daemon configuration resulting state', + name: 'auditd.data.state', + type: 'keyword', + }, + 'auditd.data.format': { + category: 'auditd', + description: "audit log's format", + name: 'auditd.data.format', + type: 'keyword', + }, + 'auditd.data.new_gid': { + category: 'auditd', + description: 'new group ID being assigned', + name: 'auditd.data.new_gid', + type: 'keyword', + }, + 'auditd.data.tcontext': { + category: 'auditd', + description: "the target's or object's context string", + name: 'auditd.data.tcontext', + type: 'keyword', + }, + 'auditd.data.maj': { + category: 'auditd', + description: 'device major number', + name: 'auditd.data.maj', + type: 'keyword', + }, + 'auditd.data.watch': { + category: 'auditd', + description: 'file name in a watch record', + name: 'auditd.data.watch', + type: 'keyword', + }, + 'auditd.data.device': { + category: 'auditd', + description: 'device name', + name: 'auditd.data.device', + type: 'keyword', + }, + 'auditd.data.grp': { + category: 'auditd', + description: 'group name', + name: 'auditd.data.grp', + type: 'keyword', + }, + 'auditd.data.bool': { + category: 'auditd', + description: 'name of SELinux boolean', + name: 'auditd.data.bool', + type: 'keyword', + }, + 'auditd.data.icmp_type': { + category: 'auditd', + description: 'type of icmp message', + name: 'auditd.data.icmp_type', + type: 'keyword', + }, + 'auditd.data.new_lock': { + category: 'auditd', + description: 'new value of feature lock', + name: 'auditd.data.new_lock', + type: 'keyword', + }, + 'auditd.data.old_prom': { + category: 'auditd', + description: 'network promiscuity flag', + name: 'auditd.data.old_prom', + type: 'keyword', + }, + 'auditd.data.acl': { + category: 'auditd', + description: 'access mode of resource assigned to vm', + name: 'auditd.data.acl', + type: 'keyword', + }, + 'auditd.data.ip': { + category: 'auditd', + description: 'network address of a printer', + name: 'auditd.data.ip', + type: 'keyword', + }, + 'auditd.data.new_pi': { + category: 'auditd', + description: 'new process inherited capability map', + name: 'auditd.data.new_pi', + type: 'keyword', + }, + 'auditd.data.default-context': { + category: 'auditd', + description: 'default MAC context', + name: 'auditd.data.default-context', + type: 'keyword', + }, + 'auditd.data.inode_gid': { + category: 'auditd', + description: "group ID of the inode's owner", + name: 'auditd.data.inode_gid', + type: 'keyword', + }, + 'auditd.data.new-log_passwd': { + category: 'auditd', + description: 'new value for TTY password logging', + name: 'auditd.data.new-log_passwd', + type: 'keyword', + }, + 'auditd.data.new_pe': { + category: 'auditd', + description: 'new process effective capability map', + name: 'auditd.data.new_pe', + type: 'keyword', + }, + 'auditd.data.selected-context': { + category: 'auditd', + description: 'new MAC context assigned to session', + name: 'auditd.data.selected-context', + type: 'keyword', + }, + 'auditd.data.cap_fver': { + category: 'auditd', + description: 'file system capabilities version number', + name: 'auditd.data.cap_fver', + type: 'keyword', + }, + 'auditd.data.file': { + category: 'auditd', + description: 'file name', + name: 'auditd.data.file', + type: 'keyword', + }, + 'auditd.data.net': { + category: 'auditd', + description: 'network MAC address', + name: 'auditd.data.net', + type: 'keyword', + }, + 'auditd.data.virt': { + category: 'auditd', + description: 'kind of virtualization being referenced', + name: 'auditd.data.virt', + type: 'keyword', + }, + 'auditd.data.cap_pp': { + category: 'auditd', + description: 'process permitted capability map', + name: 'auditd.data.cap_pp', + type: 'keyword', + }, + 'auditd.data.old-range': { + category: 'auditd', + description: 'present SELinux range', + name: 'auditd.data.old-range', + type: 'keyword', + }, + 'auditd.data.resrc': { + category: 'auditd', + description: 'resource being assigned', + name: 'auditd.data.resrc', + type: 'keyword', + }, + 'auditd.data.new-range': { + category: 'auditd', + description: 'new SELinux range', + name: 'auditd.data.new-range', + type: 'keyword', + }, + 'auditd.data.obj_gid': { + category: 'auditd', + description: 'group ID of object', + name: 'auditd.data.obj_gid', + type: 'keyword', + }, + 'auditd.data.proto': { + category: 'auditd', + description: 'network protocol', + name: 'auditd.data.proto', + type: 'keyword', + }, + 'auditd.data.old-disk': { + category: 'auditd', + description: 'disk being removed from vm', + name: 'auditd.data.old-disk', + type: 'keyword', + }, + 'auditd.data.audit_failure': { + category: 'auditd', + description: "audit system's failure mode", + name: 'auditd.data.audit_failure', + type: 'keyword', + }, + 'auditd.data.inif': { + category: 'auditd', + description: 'in interface number', + name: 'auditd.data.inif', + type: 'keyword', + }, + 'auditd.data.vm': { + category: 'auditd', + description: 'virtual machine name', + name: 'auditd.data.vm', + type: 'keyword', + }, + 'auditd.data.flags': { + category: 'auditd', + description: 'mmap syscall flags', + name: 'auditd.data.flags', + type: 'keyword', + }, + 'auditd.data.nlnk-fam': { + category: 'auditd', + description: 'netlink protocol number', + name: 'auditd.data.nlnk-fam', + type: 'keyword', + }, + 'auditd.data.old-fs': { + category: 'auditd', + description: 'file system being removed from vm', + name: 'auditd.data.old-fs', + type: 'keyword', + }, + 'auditd.data.old-ses': { + category: 'auditd', + description: 'previous ses value', + name: 'auditd.data.old-ses', + type: 'keyword', + }, + 'auditd.data.seqno': { + category: 'auditd', + description: 'sequence number', + name: 'auditd.data.seqno', + type: 'keyword', + }, + 'auditd.data.fver': { + category: 'auditd', + description: 'file system capabilities version number', + name: 'auditd.data.fver', + type: 'keyword', + }, + 'auditd.data.qbytes': { + category: 'auditd', + description: 'ipc objects quantity of bytes', + name: 'auditd.data.qbytes', + type: 'keyword', + }, + 'auditd.data.seuser': { + category: 'auditd', + description: "user's SE Linux user acct", + name: 'auditd.data.seuser', + type: 'keyword', + }, + 'auditd.data.cap_fe': { + category: 'auditd', + description: 'file assigned effective capability map', + name: 'auditd.data.cap_fe', + type: 'keyword', + }, + 'auditd.data.new-vcpu': { + category: 'auditd', + description: 'new number of CPU cores', + name: 'auditd.data.new-vcpu', + type: 'keyword', + }, + 'auditd.data.old-level': { + category: 'auditd', + description: 'old run level', + name: 'auditd.data.old-level', + type: 'keyword', + }, + 'auditd.data.old_pp': { + category: 'auditd', + description: 'old process permitted capability map', + name: 'auditd.data.old_pp', + type: 'keyword', + }, + 'auditd.data.daddr': { + category: 'auditd', + description: 'remote IP address', + name: 'auditd.data.daddr', + type: 'keyword', + }, + 'auditd.data.old-role': { + category: 'auditd', + description: 'present SELinux role', + name: 'auditd.data.old-role', + type: 'keyword', + }, + 'auditd.data.ioctlcmd': { + category: 'auditd', + description: 'The request argument to the ioctl syscall', + name: 'auditd.data.ioctlcmd', + type: 'keyword', + }, + 'auditd.data.smac': { + category: 'auditd', + description: 'local MAC address', + name: 'auditd.data.smac', + type: 'keyword', + }, + 'auditd.data.apparmor': { + category: 'auditd', + description: 'apparmor event information', + name: 'auditd.data.apparmor', + type: 'keyword', + }, + 'auditd.data.fe': { + category: 'auditd', + description: 'file assigned effective capability map', + name: 'auditd.data.fe', + type: 'keyword', + }, + 'auditd.data.perm_mask': { + category: 'auditd', + description: 'file permission mask that triggered a watch event', + name: 'auditd.data.perm_mask', + type: 'keyword', + }, + 'auditd.data.ses': { + category: 'auditd', + description: 'login session ID', + name: 'auditd.data.ses', + type: 'keyword', + }, + 'auditd.data.cap_fi': { + category: 'auditd', + description: 'file inherited capability map', + name: 'auditd.data.cap_fi', + type: 'keyword', + }, + 'auditd.data.obj_uid': { + category: 'auditd', + description: 'user ID of object', + name: 'auditd.data.obj_uid', + type: 'keyword', + }, + 'auditd.data.reason': { + category: 'auditd', + description: 'text string denoting a reason for the action', + name: 'auditd.data.reason', + type: 'keyword', + }, + 'auditd.data.list': { + category: 'auditd', + description: "the audit system's filter list number", + name: 'auditd.data.list', + type: 'keyword', + }, + 'auditd.data.old_lock': { + category: 'auditd', + description: 'present value of feature lock', + name: 'auditd.data.old_lock', + type: 'keyword', + }, + 'auditd.data.bus': { + category: 'auditd', + description: 'name of subsystem bus a vm resource belongs to', + name: 'auditd.data.bus', + type: 'keyword', + }, + 'auditd.data.old_pe': { + category: 'auditd', + description: 'old process effective capability map', + name: 'auditd.data.old_pe', + type: 'keyword', + }, + 'auditd.data.new-role': { + category: 'auditd', + description: 'new SELinux role', + name: 'auditd.data.new-role', + type: 'keyword', + }, + 'auditd.data.prom': { + category: 'auditd', + description: 'network promiscuity flag', + name: 'auditd.data.prom', + type: 'keyword', + }, + 'auditd.data.uri': { + category: 'auditd', + description: 'URI pointing to a printer', + name: 'auditd.data.uri', + type: 'keyword', + }, + 'auditd.data.audit_enabled': { + category: 'auditd', + description: "audit systems's enable/disable status", + name: 'auditd.data.audit_enabled', + type: 'keyword', + }, + 'auditd.data.old-log_passwd': { + category: 'auditd', + description: 'present value for TTY password logging', + name: 'auditd.data.old-log_passwd', + type: 'keyword', + }, + 'auditd.data.old-seuser': { + category: 'auditd', + description: 'present SELinux user', + name: 'auditd.data.old-seuser', + type: 'keyword', + }, + 'auditd.data.per': { + category: 'auditd', + description: 'linux personality', + name: 'auditd.data.per', + type: 'keyword', + }, + 'auditd.data.scontext': { + category: 'auditd', + description: "the subject's context string", + name: 'auditd.data.scontext', + type: 'keyword', + }, + 'auditd.data.tclass': { + category: 'auditd', + description: "target's object classification", + name: 'auditd.data.tclass', + type: 'keyword', + }, + 'auditd.data.ver': { + category: 'auditd', + description: "audit daemon's version number", + name: 'auditd.data.ver', + type: 'keyword', + }, + 'auditd.data.new': { + category: 'auditd', + description: 'value being set in feature', + name: 'auditd.data.new', + type: 'keyword', + }, + 'auditd.data.val': { + category: 'auditd', + description: 'generic value associated with the operation', + name: 'auditd.data.val', + type: 'keyword', + }, + 'auditd.data.img-ctx': { + category: 'auditd', + description: "the vm's disk image context string", + name: 'auditd.data.img-ctx', + type: 'keyword', + }, + 'auditd.data.old-chardev': { + category: 'auditd', + description: 'present character device assigned to vm', + name: 'auditd.data.old-chardev', + type: 'keyword', + }, + 'auditd.data.old_val': { + category: 'auditd', + description: 'current value of SELinux boolean', + name: 'auditd.data.old_val', + type: 'keyword', + }, + 'auditd.data.success': { + category: 'auditd', + description: 'whether the syscall was successful or not', + name: 'auditd.data.success', + type: 'keyword', + }, + 'auditd.data.inode_uid': { + category: 'auditd', + description: "user ID of the inode's owner", + name: 'auditd.data.inode_uid', + type: 'keyword', + }, + 'auditd.data.removed': { + category: 'auditd', + description: 'number of deleted files', + name: 'auditd.data.removed', + type: 'keyword', + }, + 'auditd.data.socket.port': { + category: 'auditd', + description: 'The port number.', + name: 'auditd.data.socket.port', + type: 'keyword', + }, + 'auditd.data.socket.saddr': { + category: 'auditd', + description: 'The raw socket address structure.', + name: 'auditd.data.socket.saddr', + type: 'keyword', + }, + 'auditd.data.socket.addr': { + category: 'auditd', + description: 'The remote address.', + name: 'auditd.data.socket.addr', + type: 'keyword', + }, + 'auditd.data.socket.family': { + category: 'auditd', + description: 'The socket family (unix, ipv4, ipv6, netlink).', + example: 'unix', + name: 'auditd.data.socket.family', + type: 'keyword', + }, + 'auditd.data.socket.path': { + category: 'auditd', + description: 'This is the path associated with a unix socket.', + name: 'auditd.data.socket.path', + type: 'keyword', + }, + 'auditd.messages': { + category: 'auditd', + description: + 'An ordered list of the raw messages received from the kernel that were used to construct this document. This field is present if an error occurred processing the data or if `include_raw_message` is set in the config. ', + name: 'auditd.messages', + type: 'alias', + }, + 'auditd.warnings': { + category: 'auditd', + description: + 'The warnings generated by the Beat during the construction of the event. These are disabled by default and are used for development and debug purposes only. ', + name: 'auditd.warnings', + type: 'alias', + }, + 'geoip.continent_name': { + category: 'geoip', + description: 'The name of the continent. ', + name: 'geoip.continent_name', + type: 'keyword', + }, + 'geoip.city_name': { + category: 'geoip', + description: 'The name of the city. ', + name: 'geoip.city_name', + type: 'keyword', + }, + 'geoip.region_name': { + category: 'geoip', + description: 'The name of the region. ', + name: 'geoip.region_name', + type: 'keyword', + }, + 'geoip.country_iso_code': { + category: 'geoip', + description: 'Country ISO code. ', + name: 'geoip.country_iso_code', + type: 'keyword', + }, + 'geoip.location': { + category: 'geoip', + description: 'The longitude and latitude. ', + name: 'geoip.location', + type: 'geo_point', + }, + 'hash.blake2b_256': { + category: 'hash', + description: 'BLAKE2b-256 hash of the file.', + name: 'hash.blake2b_256', + type: 'keyword', + }, + 'hash.blake2b_384': { + category: 'hash', + description: 'BLAKE2b-384 hash of the file.', + name: 'hash.blake2b_384', + type: 'keyword', + }, + 'hash.blake2b_512': { + category: 'hash', + description: 'BLAKE2b-512 hash of the file.', + name: 'hash.blake2b_512', + type: 'keyword', + }, + 'hash.sha224': { + category: 'hash', + description: 'SHA224 hash of the file.', + name: 'hash.sha224', + type: 'keyword', + }, + 'hash.sha384': { + category: 'hash', + description: 'SHA384 hash of the file.', + name: 'hash.sha384', + type: 'keyword', + }, + 'hash.sha3_224': { + category: 'hash', + description: 'SHA3_224 hash of the file.', + name: 'hash.sha3_224', + type: 'keyword', + }, + 'hash.sha3_256': { + category: 'hash', + description: 'SHA3_256 hash of the file.', + name: 'hash.sha3_256', + type: 'keyword', + }, + 'hash.sha3_384': { + category: 'hash', + description: 'SHA3_384 hash of the file.', + name: 'hash.sha3_384', + type: 'keyword', + }, + 'hash.sha3_512': { + category: 'hash', + description: 'SHA3_512 hash of the file.', + name: 'hash.sha3_512', + type: 'keyword', + }, + 'hash.sha512_224': { + category: 'hash', + description: 'SHA512/224 hash of the file.', + name: 'hash.sha512_224', + type: 'keyword', + }, + 'hash.sha512_256': { + category: 'hash', + description: 'SHA512/256 hash of the file.', + name: 'hash.sha512_256', + type: 'keyword', + }, + 'hash.xxh64': { + category: 'hash', + description: 'XX64 hash of the file.', + name: 'hash.xxh64', + type: 'keyword', + }, + 'event.origin': { + category: 'event', + description: + 'Origin of the event. This can be a file path (e.g. `/var/log/log.1`), or the name of the system component that supplied the data (e.g. `netlink`). ', + name: 'event.origin', + type: 'keyword', + }, + 'user.entity_id': { + category: 'user', + description: + 'ID uniquely identifying the user on a host. It is computed as a SHA-256 hash of the host ID, user ID, and user name. ', + name: 'user.entity_id', + type: 'keyword', + }, + 'user.terminal': { + category: 'user', + description: 'Terminal of the user. ', + name: 'user.terminal', + type: 'keyword', + }, + 'process.hash.blake2b_256': { + category: 'process', + description: 'BLAKE2b-256 hash of the executable.', + name: 'process.hash.blake2b_256', + type: 'keyword', + }, + 'process.hash.blake2b_384': { + category: 'process', + description: 'BLAKE2b-384 hash of the executable.', + name: 'process.hash.blake2b_384', + type: 'keyword', + }, + 'process.hash.blake2b_512': { + category: 'process', + description: 'BLAKE2b-512 hash of the executable.', + name: 'process.hash.blake2b_512', + type: 'keyword', + }, + 'process.hash.sha224': { + category: 'process', + description: 'SHA224 hash of the executable.', + name: 'process.hash.sha224', + type: 'keyword', + }, + 'process.hash.sha384': { + category: 'process', + description: 'SHA384 hash of the executable.', + name: 'process.hash.sha384', + type: 'keyword', + }, + 'process.hash.sha3_224': { + category: 'process', + description: 'SHA3_224 hash of the executable.', + name: 'process.hash.sha3_224', + type: 'keyword', + }, + 'process.hash.sha3_256': { + category: 'process', + description: 'SHA3_256 hash of the executable.', + name: 'process.hash.sha3_256', + type: 'keyword', + }, + 'process.hash.sha3_384': { + category: 'process', + description: 'SHA3_384 hash of the executable.', + name: 'process.hash.sha3_384', + type: 'keyword', + }, + 'process.hash.sha3_512': { + category: 'process', + description: 'SHA3_512 hash of the executable.', + name: 'process.hash.sha3_512', + type: 'keyword', + }, + 'process.hash.sha512_224': { + category: 'process', + description: 'SHA512/224 hash of the executable.', + name: 'process.hash.sha512_224', + type: 'keyword', + }, + 'process.hash.sha512_256': { + category: 'process', + description: 'SHA512/256 hash of the executable.', + name: 'process.hash.sha512_256', + type: 'keyword', + }, + 'process.hash.xxh64': { + category: 'process', + description: 'XX64 hash of the executable.', + name: 'process.hash.xxh64', + type: 'keyword', + }, + 'socket.entity_id': { + category: 'socket', + description: + 'ID uniquely identifying the socket. It is computed as a SHA-256 hash of the host ID, socket inode, local IP, local port, remote IP, and remote port. ', + name: 'socket.entity_id', + type: 'keyword', + }, + 'system.audit.host.uptime': { + category: 'system', + description: 'Uptime in nanoseconds. ', + name: 'system.audit.host.uptime', + type: 'long', + format: 'duration', + }, + 'system.audit.host.boottime': { + category: 'system', + description: 'Boot time. ', + name: 'system.audit.host.boottime', + type: 'date', + }, + 'system.audit.host.containerized': { + category: 'system', + description: 'Set if host is a container. ', + name: 'system.audit.host.containerized', + type: 'boolean', + }, + 'system.audit.host.timezone.name': { + category: 'system', + description: 'Name of the timezone of the host, e.g. BST. ', + name: 'system.audit.host.timezone.name', + type: 'keyword', + }, + 'system.audit.host.timezone.offset.sec': { + category: 'system', + description: 'Timezone offset in seconds. ', + name: 'system.audit.host.timezone.offset.sec', + type: 'long', + }, + 'system.audit.host.hostname': { + category: 'system', + description: 'Hostname. ', + name: 'system.audit.host.hostname', + type: 'keyword', + }, + 'system.audit.host.id': { + category: 'system', + description: 'Host ID. ', + name: 'system.audit.host.id', + type: 'keyword', + }, + 'system.audit.host.architecture': { + category: 'system', + description: 'Host architecture (e.g. x86_64). ', + name: 'system.audit.host.architecture', + type: 'keyword', + }, + 'system.audit.host.mac': { + category: 'system', + description: 'MAC addresses. ', + name: 'system.audit.host.mac', + type: 'keyword', + }, + 'system.audit.host.ip': { + category: 'system', + description: 'IP addresses. ', + name: 'system.audit.host.ip', + type: 'ip', + }, + 'system.audit.host.os.codename': { + category: 'system', + description: 'OS codename, if any (e.g. stretch). ', + name: 'system.audit.host.os.codename', + type: 'keyword', + }, + 'system.audit.host.os.platform': { + category: 'system', + description: 'OS platform (e.g. centos, ubuntu, windows). ', + name: 'system.audit.host.os.platform', + type: 'keyword', + }, + 'system.audit.host.os.name': { + category: 'system', + description: 'OS name (e.g. Mac OS X). ', + name: 'system.audit.host.os.name', + type: 'keyword', + }, + 'system.audit.host.os.family': { + category: 'system', + description: 'OS family (e.g. redhat, debian, freebsd, windows). ', + name: 'system.audit.host.os.family', + type: 'keyword', + }, + 'system.audit.host.os.version': { + category: 'system', + description: 'OS version. ', + name: 'system.audit.host.os.version', + type: 'keyword', + }, + 'system.audit.host.os.kernel': { + category: 'system', + description: "The operating system's kernel version. ", + name: 'system.audit.host.os.kernel', + type: 'keyword', + }, + 'system.audit.package.entity_id': { + category: 'system', + description: + 'ID uniquely identifying the package. It is computed as a SHA-256 hash of the host ID, package name, and package version. ', + name: 'system.audit.package.entity_id', + type: 'keyword', + }, + 'system.audit.package.name': { + category: 'system', + description: 'Package name. ', + name: 'system.audit.package.name', + type: 'keyword', + }, + 'system.audit.package.version': { + category: 'system', + description: 'Package version. ', + name: 'system.audit.package.version', + type: 'keyword', + }, + 'system.audit.package.release': { + category: 'system', + description: 'Package release. ', + name: 'system.audit.package.release', + type: 'keyword', + }, + 'system.audit.package.arch': { + category: 'system', + description: 'Package architecture. ', + name: 'system.audit.package.arch', + type: 'keyword', + }, + 'system.audit.package.license': { + category: 'system', + description: 'Package license. ', + name: 'system.audit.package.license', + type: 'keyword', + }, + 'system.audit.package.installtime': { + category: 'system', + description: 'Package install time. ', + name: 'system.audit.package.installtime', + type: 'date', + }, + 'system.audit.package.size': { + category: 'system', + description: 'Package size. ', + name: 'system.audit.package.size', + type: 'long', + }, + 'system.audit.package.summary': { + category: 'system', + description: 'Package summary. ', + name: 'system.audit.package.summary', + }, + 'system.audit.package.url': { + category: 'system', + description: 'Package URL. ', + name: 'system.audit.package.url', + type: 'keyword', + }, + 'system.audit.user.name': { + category: 'system', + description: 'User name. ', + name: 'system.audit.user.name', + type: 'keyword', + }, + 'system.audit.user.uid': { + category: 'system', + description: 'User ID. ', + name: 'system.audit.user.uid', + type: 'keyword', + }, + 'system.audit.user.gid': { + category: 'system', + description: 'Group ID. ', + name: 'system.audit.user.gid', + type: 'keyword', + }, + 'system.audit.user.dir': { + category: 'system', + description: "User's home directory. ", + name: 'system.audit.user.dir', + type: 'keyword', + }, + 'system.audit.user.shell': { + category: 'system', + description: 'Program to run at login. ', + name: 'system.audit.user.shell', + type: 'keyword', + }, + 'system.audit.user.user_information': { + category: 'system', + description: 'General user information. On Linux, this is the gecos field. ', + name: 'system.audit.user.user_information', + type: 'keyword', + }, + 'system.audit.user.group.name': { + category: 'system', + description: 'Group name. ', + name: 'system.audit.user.group.name', + type: 'keyword', + }, + 'system.audit.user.group.gid': { + category: 'system', + description: 'Group ID. ', + name: 'system.audit.user.group.gid', + type: 'integer', + }, + 'system.audit.user.password.type': { + category: 'system', + description: + "A user's password type. Possible values are `shadow_password` (the password hash is in the shadow file), `password_disabled`, `no_password` (this is dangerous as anyone can log in), and `crypt_password` (when the password field in /etc/passwd seems to contain an encrypted password). ", + name: 'system.audit.user.password.type', + type: 'keyword', + }, + 'system.audit.user.password.last_changed': { + category: 'system', + description: "The day the user's password was last changed. ", + name: 'system.audit.user.password.last_changed', + type: 'date', + }, + 'log.file.path': { + category: 'log', + description: + 'The file from which the line was read. This field contains the absolute path to the file. For example: `/var/log/system.log`. ', + name: 'log.file.path', + type: 'keyword', + }, + 'log.source.address': { + category: 'log', + description: 'Source address from which the log event was read / sent from. ', + name: 'log.source.address', + type: 'keyword', + }, + 'log.offset': { + category: 'log', + description: 'The file offset the reported line starts at. ', + name: 'log.offset', + type: 'long', + }, + stream: { + category: 'base', + description: "Log stream when reading container logs, can be 'stdout' or 'stderr' ", + name: 'stream', + type: 'keyword', + }, + 'input.type': { + category: 'input', + description: + 'The input type from which the event was generated. This field is set to the value specified for the `type` option in the input section of the Filebeat config file. ', + name: 'input.type', + }, + 'syslog.facility': { + category: 'syslog', + description: 'The facility extracted from the priority. ', + name: 'syslog.facility', + type: 'long', + }, + 'syslog.priority': { + category: 'syslog', + description: 'The priority of the syslog event. ', + name: 'syslog.priority', + type: 'long', + }, + 'syslog.severity_label': { + category: 'syslog', + description: 'The human readable severity. ', + name: 'syslog.severity_label', + type: 'keyword', + }, + 'syslog.facility_label': { + category: 'syslog', + description: 'The human readable facility. ', + name: 'syslog.facility_label', + type: 'keyword', + }, + 'process.program': { + category: 'process', + description: 'The name of the program. ', + name: 'process.program', + type: 'keyword', + }, + 'log.flags': { + category: 'log', + description: 'This field contains the flags of the event. ', + name: 'log.flags', + }, + 'http.response.content_length': { + category: 'http', + name: 'http.response.content_length', + type: 'alias', + }, + 'user_agent.os.full_name': { + category: 'user_agent', + name: 'user_agent.os.full_name', + type: 'keyword', + }, + 'fileset.name': { + category: 'fileset', + description: 'The Filebeat fileset that generated this event. ', + name: 'fileset.name', + type: 'keyword', + }, + 'fileset.module': { + category: 'fileset', + name: 'fileset.module', + type: 'alias', + }, + read_timestamp: { + category: 'base', + name: 'read_timestamp', + type: 'alias', + }, + 'docker.attrs': { + category: 'docker', + description: + "docker.attrs contains labels and environment variables written by docker's JSON File logging driver. These fields are only available when they are configured in the logging driver options. ", + name: 'docker.attrs', + type: 'object', + }, + 'icmp.code': { + category: 'icmp', + description: 'ICMP code. ', + name: 'icmp.code', + type: 'keyword', + }, + 'icmp.type': { + category: 'icmp', + description: 'ICMP type. ', + name: 'icmp.type', + type: 'keyword', + }, + 'igmp.type': { + category: 'igmp', + description: 'IGMP type. ', + name: 'igmp.type', + type: 'keyword', + }, + 'azure.eventhub': { + category: 'azure', + description: 'Name of the eventhub. ', + name: 'azure.eventhub', + type: 'keyword', + }, + 'azure.offset': { + category: 'azure', + description: 'The offset. ', + name: 'azure.offset', + type: 'long', + }, + 'azure.enqueued_time': { + category: 'azure', + description: 'The enqueued time. ', + name: 'azure.enqueued_time', + type: 'date', + }, + 'azure.partition_id': { + category: 'azure', + description: 'The partition id. ', + name: 'azure.partition_id', + type: 'long', + }, + 'azure.consumer_group': { + category: 'azure', + description: 'The consumer group. ', + name: 'azure.consumer_group', + type: 'keyword', + }, + 'azure.sequence_number': { + category: 'azure', + description: 'The sequence number. ', + name: 'azure.sequence_number', + type: 'long', + }, + 'kafka.topic': { + category: 'kafka', + description: 'Kafka topic ', + name: 'kafka.topic', + type: 'keyword', + }, + 'kafka.partition': { + category: 'kafka', + description: 'Kafka partition number ', + name: 'kafka.partition', + type: 'long', + }, + 'kafka.offset': { + category: 'kafka', + description: 'Kafka offset of this message ', + name: 'kafka.offset', + type: 'long', + }, + 'kafka.key': { + category: 'kafka', + description: 'Kafka key, corresponding to the Kafka value stored in the message ', + name: 'kafka.key', + type: 'keyword', + }, + 'kafka.block_timestamp': { + category: 'kafka', + description: 'Kafka outer (compressed) block timestamp ', + name: 'kafka.block_timestamp', + type: 'date', + }, + 'kafka.headers': { + category: 'kafka', + description: + 'An array of Kafka header strings for this message, in the form ": ". ', + name: 'kafka.headers', + type: 'array', + }, + 'apache2.access.remote_ip': { + category: 'apache2', + name: 'apache2.access.remote_ip', + type: 'alias', + }, + 'apache2.access.ssl.protocol': { + category: 'apache2', + name: 'apache2.access.ssl.protocol', + type: 'alias', + }, + 'apache2.access.ssl.cipher': { + category: 'apache2', + name: 'apache2.access.ssl.cipher', + type: 'alias', + }, + 'apache2.access.body_sent.bytes': { + category: 'apache2', + name: 'apache2.access.body_sent.bytes', + type: 'alias', + }, + 'apache2.access.user_name': { + category: 'apache2', + name: 'apache2.access.user_name', + type: 'alias', + }, + 'apache2.access.method': { + category: 'apache2', + name: 'apache2.access.method', + type: 'alias', + }, + 'apache2.access.url': { + category: 'apache2', + name: 'apache2.access.url', + type: 'alias', + }, + 'apache2.access.http_version': { + category: 'apache2', + name: 'apache2.access.http_version', + type: 'alias', + }, + 'apache2.access.response_code': { + category: 'apache2', + name: 'apache2.access.response_code', + type: 'alias', + }, + 'apache2.access.referrer': { + category: 'apache2', + name: 'apache2.access.referrer', + type: 'alias', + }, + 'apache2.access.agent': { + category: 'apache2', + name: 'apache2.access.agent', + type: 'alias', + }, + 'apache2.access.user_agent.device': { + category: 'apache2', + name: 'apache2.access.user_agent.device', + type: 'alias', + }, + 'apache2.access.user_agent.name': { + category: 'apache2', + name: 'apache2.access.user_agent.name', + type: 'alias', + }, + 'apache2.access.user_agent.os': { + category: 'apache2', + name: 'apache2.access.user_agent.os', + type: 'alias', + }, + 'apache2.access.user_agent.os_name': { + category: 'apache2', + name: 'apache2.access.user_agent.os_name', + type: 'alias', + }, + 'apache2.access.user_agent.original': { + category: 'apache2', + name: 'apache2.access.user_agent.original', + type: 'alias', + }, + 'apache2.access.geoip.continent_name': { + category: 'apache2', + name: 'apache2.access.geoip.continent_name', + type: 'alias', + }, + 'apache2.access.geoip.country_iso_code': { + category: 'apache2', + name: 'apache2.access.geoip.country_iso_code', + type: 'alias', + }, + 'apache2.access.geoip.location': { + category: 'apache2', + name: 'apache2.access.geoip.location', + type: 'alias', + }, + 'apache2.access.geoip.region_name': { + category: 'apache2', + name: 'apache2.access.geoip.region_name', + type: 'alias', + }, + 'apache2.access.geoip.city_name': { + category: 'apache2', + name: 'apache2.access.geoip.city_name', + type: 'alias', + }, + 'apache2.access.geoip.region_iso_code': { + category: 'apache2', + name: 'apache2.access.geoip.region_iso_code', + type: 'alias', + }, + 'apache2.error.level': { + category: 'apache2', + name: 'apache2.error.level', + type: 'alias', + }, + 'apache2.error.message': { + category: 'apache2', + name: 'apache2.error.message', + type: 'alias', + }, + 'apache2.error.pid': { + category: 'apache2', + name: 'apache2.error.pid', + type: 'alias', + }, + 'apache2.error.tid': { + category: 'apache2', + name: 'apache2.error.tid', + type: 'alias', + }, + 'apache2.error.module': { + category: 'apache2', + name: 'apache2.error.module', + type: 'alias', + }, + 'apache.access.ssl.protocol': { + category: 'apache', + description: 'SSL protocol version. ', + name: 'apache.access.ssl.protocol', + type: 'keyword', + }, + 'apache.access.ssl.cipher': { + category: 'apache', + description: 'SSL cipher name. ', + name: 'apache.access.ssl.cipher', + type: 'keyword', + }, + 'apache.error.module': { + category: 'apache', + description: 'The module producing the logged message. ', + name: 'apache.error.module', + type: 'keyword', + }, + 'user.audit.group.id': { + category: 'user', + description: 'Unique identifier for the group on the system/platform. ', + name: 'user.audit.group.id', + type: 'keyword', + }, + 'user.audit.group.name': { + category: 'user', + description: 'Name of the group. ', + name: 'user.audit.group.name', + type: 'keyword', + }, + 'user.owner.id': { + category: 'user', + description: 'One or multiple unique identifiers of the user. ', + name: 'user.owner.id', + type: 'keyword', + }, + 'user.owner.name': { + category: 'user', + description: 'Short name or login of the user. ', + example: 'albert', + name: 'user.owner.name', + type: 'keyword', + }, + 'user.owner.group.id': { + category: 'user', + description: 'Unique identifier for the group on the system/platform. ', + name: 'user.owner.group.id', + type: 'keyword', + }, + 'user.owner.group.name': { + category: 'user', + description: 'Name of the group. ', + name: 'user.owner.group.name', + type: 'keyword', + }, + 'auditd.log.old_auid': { + category: 'auditd', + description: + 'For login events this is the old audit ID used for the user prior to this login. ', + name: 'auditd.log.old_auid', + }, + 'auditd.log.new_auid': { + category: 'auditd', + description: + 'For login events this is the new audit ID. The audit ID can be used to trace future events to the user even if their identity changes (like becoming root). ', + name: 'auditd.log.new_auid', + }, + 'auditd.log.old_ses': { + category: 'auditd', + description: + 'For login events this is the old session ID used for the user prior to this login. ', + name: 'auditd.log.old_ses', + }, + 'auditd.log.new_ses': { + category: 'auditd', + description: + 'For login events this is the new session ID. It can be used to tie a user to future events by session ID. ', + name: 'auditd.log.new_ses', + }, + 'auditd.log.sequence': { + category: 'auditd', + description: 'The audit event sequence number. ', + name: 'auditd.log.sequence', + type: 'long', + }, + 'auditd.log.items': { + category: 'auditd', + description: 'The number of items in an event. ', + name: 'auditd.log.items', + }, + 'auditd.log.item': { + category: 'auditd', + description: + 'The item field indicates which item out of the total number of items. This number is zero-based; a value of 0 means it is the first item. ', + name: 'auditd.log.item', + }, + 'auditd.log.tty': { + category: 'auditd', + name: 'auditd.log.tty', + type: 'keyword', + }, + 'auditd.log.a0': { + category: 'auditd', + description: 'The first argument to the system call. ', + name: 'auditd.log.a0', + }, + 'auditd.log.addr': { + category: 'auditd', + name: 'auditd.log.addr', + type: 'ip', + }, + 'auditd.log.rport': { + category: 'auditd', + name: 'auditd.log.rport', + type: 'long', + }, + 'auditd.log.laddr': { + category: 'auditd', + name: 'auditd.log.laddr', + type: 'ip', + }, + 'auditd.log.lport': { + category: 'auditd', + name: 'auditd.log.lport', + type: 'long', + }, + 'auditd.log.acct': { + category: 'auditd', + name: 'auditd.log.acct', + type: 'alias', + }, + 'auditd.log.pid': { + category: 'auditd', + name: 'auditd.log.pid', + type: 'alias', + }, + 'auditd.log.ppid': { + category: 'auditd', + name: 'auditd.log.ppid', + type: 'alias', + }, + 'auditd.log.res': { + category: 'auditd', + name: 'auditd.log.res', + type: 'alias', + }, + 'auditd.log.record_type': { + category: 'auditd', + name: 'auditd.log.record_type', + type: 'alias', + }, + 'auditd.log.geoip.continent_name': { + category: 'auditd', + name: 'auditd.log.geoip.continent_name', + type: 'alias', + }, + 'auditd.log.geoip.country_iso_code': { + category: 'auditd', + name: 'auditd.log.geoip.country_iso_code', + type: 'alias', + }, + 'auditd.log.geoip.location': { + category: 'auditd', + name: 'auditd.log.geoip.location', + type: 'alias', + }, + 'auditd.log.geoip.region_name': { + category: 'auditd', + name: 'auditd.log.geoip.region_name', + type: 'alias', + }, + 'auditd.log.geoip.city_name': { + category: 'auditd', + name: 'auditd.log.geoip.city_name', + type: 'alias', + }, + 'auditd.log.geoip.region_iso_code': { + category: 'auditd', + name: 'auditd.log.geoip.region_iso_code', + type: 'alias', + }, + 'auditd.log.arch': { + category: 'auditd', + name: 'auditd.log.arch', + type: 'alias', + }, + 'auditd.log.gid': { + category: 'auditd', + name: 'auditd.log.gid', + type: 'alias', + }, + 'auditd.log.uid': { + category: 'auditd', + name: 'auditd.log.uid', + type: 'alias', + }, + 'auditd.log.agid': { + category: 'auditd', + name: 'auditd.log.agid', + type: 'alias', + }, + 'auditd.log.auid': { + category: 'auditd', + name: 'auditd.log.auid', + type: 'alias', + }, + 'auditd.log.fsgid': { + category: 'auditd', + name: 'auditd.log.fsgid', + type: 'alias', + }, + 'auditd.log.fsuid': { + category: 'auditd', + name: 'auditd.log.fsuid', + type: 'alias', + }, + 'auditd.log.egid': { + category: 'auditd', + name: 'auditd.log.egid', + type: 'alias', + }, + 'auditd.log.euid': { + category: 'auditd', + name: 'auditd.log.euid', + type: 'alias', + }, + 'auditd.log.sgid': { + category: 'auditd', + name: 'auditd.log.sgid', + type: 'alias', + }, + 'auditd.log.suid': { + category: 'auditd', + name: 'auditd.log.suid', + type: 'alias', + }, + 'auditd.log.ogid': { + category: 'auditd', + name: 'auditd.log.ogid', + type: 'alias', + }, + 'auditd.log.ouid': { + category: 'auditd', + name: 'auditd.log.ouid', + type: 'alias', + }, + 'auditd.log.comm': { + category: 'auditd', + name: 'auditd.log.comm', + type: 'alias', + }, + 'auditd.log.exe': { + category: 'auditd', + name: 'auditd.log.exe', + type: 'alias', + }, + 'auditd.log.terminal': { + category: 'auditd', + name: 'auditd.log.terminal', + type: 'alias', + }, + 'auditd.log.msg': { + category: 'auditd', + name: 'auditd.log.msg', + type: 'alias', + }, + 'auditd.log.src': { + category: 'auditd', + name: 'auditd.log.src', + type: 'alias', + }, + 'auditd.log.dst': { + category: 'auditd', + name: 'auditd.log.dst', + type: 'alias', + }, + 'elasticsearch.component': { + category: 'elasticsearch', + description: 'Elasticsearch component from where the log event originated', + example: 'o.e.c.m.MetaDataCreateIndexService', + name: 'elasticsearch.component', + type: 'keyword', + }, + 'elasticsearch.cluster.uuid': { + category: 'elasticsearch', + description: 'UUID of the cluster', + example: 'GmvrbHlNTiSVYiPf8kxg9g', + name: 'elasticsearch.cluster.uuid', + type: 'keyword', + }, + 'elasticsearch.cluster.name': { + category: 'elasticsearch', + description: 'Name of the cluster', + example: 'docker-cluster', + name: 'elasticsearch.cluster.name', + type: 'keyword', + }, + 'elasticsearch.node.id': { + category: 'elasticsearch', + description: 'ID of the node', + example: 'DSiWcTyeThWtUXLB9J0BMw', + name: 'elasticsearch.node.id', + type: 'keyword', + }, + 'elasticsearch.node.name': { + category: 'elasticsearch', + description: 'Name of the node', + example: 'vWNJsZ3', + name: 'elasticsearch.node.name', + type: 'keyword', + }, + 'elasticsearch.index.name': { + category: 'elasticsearch', + description: 'Index name', + example: 'filebeat-test-input', + name: 'elasticsearch.index.name', + type: 'keyword', + }, + 'elasticsearch.index.id': { + category: 'elasticsearch', + description: 'Index id', + example: 'aOGgDwbURfCV57AScqbCgw', + name: 'elasticsearch.index.id', + type: 'keyword', + }, + 'elasticsearch.shard.id': { + category: 'elasticsearch', + description: 'Id of the shard', + example: '0', + name: 'elasticsearch.shard.id', + type: 'keyword', + }, + 'elasticsearch.audit.layer': { + category: 'elasticsearch', + description: 'The layer from which this event originated: rest, transport or ip_filter', + example: 'rest', + name: 'elasticsearch.audit.layer', + type: 'keyword', + }, + 'elasticsearch.audit.event_type': { + category: 'elasticsearch', + description: + 'The type of event that occurred: anonymous_access_denied, authentication_failed, access_denied, access_granted, connection_granted, connection_denied, tampered_request, run_as_granted, run_as_denied', + example: 'access_granted', + name: 'elasticsearch.audit.event_type', + type: 'keyword', + }, + 'elasticsearch.audit.origin.type': { + category: 'elasticsearch', + description: + 'Where the request originated: rest (request originated from a REST API request), transport (request was received on the transport channel), local_node (the local node issued the request)', + example: 'local_node', + name: 'elasticsearch.audit.origin.type', + type: 'keyword', + }, + 'elasticsearch.audit.realm': { + category: 'elasticsearch', + description: 'The authentication realm the authentication was validated against', + name: 'elasticsearch.audit.realm', + type: 'keyword', + }, + 'elasticsearch.audit.user.realm': { + category: 'elasticsearch', + description: "The user's authentication realm, if authenticated", + name: 'elasticsearch.audit.user.realm', + type: 'keyword', + }, + 'elasticsearch.audit.user.roles': { + category: 'elasticsearch', + description: 'Roles to which the principal belongs', + example: '["kibana_admin","beats_admin"]', + name: 'elasticsearch.audit.user.roles', + type: 'keyword', + }, + 'elasticsearch.audit.action': { + category: 'elasticsearch', + description: 'The name of the action that was executed', + example: 'cluster:monitor/main', + name: 'elasticsearch.audit.action', + type: 'keyword', + }, + 'elasticsearch.audit.url.params': { + category: 'elasticsearch', + description: 'REST URI parameters', + example: '{username=jacknich2}', + name: 'elasticsearch.audit.url.params', + }, + 'elasticsearch.audit.indices': { + category: 'elasticsearch', + description: 'Indices accessed by action', + example: '["foo-2019.01.04","foo-2019.01.03","foo-2019.01.06"]', + name: 'elasticsearch.audit.indices', + type: 'keyword', + }, + 'elasticsearch.audit.request.id': { + category: 'elasticsearch', + description: 'Unique ID of request', + example: 'WzL_kb6VSvOhAq0twPvHOQ', + name: 'elasticsearch.audit.request.id', + type: 'keyword', + }, + 'elasticsearch.audit.request.name': { + category: 'elasticsearch', + description: 'The type of request that was executed', + example: 'ClearScrollRequest', + name: 'elasticsearch.audit.request.name', + type: 'keyword', + }, + 'elasticsearch.audit.request_body': { + category: 'elasticsearch', + name: 'elasticsearch.audit.request_body', + type: 'alias', + }, + 'elasticsearch.audit.origin_address': { + category: 'elasticsearch', + name: 'elasticsearch.audit.origin_address', + type: 'alias', + }, + 'elasticsearch.audit.uri': { + category: 'elasticsearch', + name: 'elasticsearch.audit.uri', + type: 'alias', + }, + 'elasticsearch.audit.principal': { + category: 'elasticsearch', + name: 'elasticsearch.audit.principal', + type: 'alias', + }, + 'elasticsearch.audit.message': { + category: 'elasticsearch', + name: 'elasticsearch.audit.message', + type: 'text', + }, + 'elasticsearch.deprecation': { + category: 'elasticsearch', + description: '', + name: 'elasticsearch.deprecation', + type: 'group', + }, + 'elasticsearch.gc.phase.name': { + category: 'elasticsearch', + description: 'Name of the GC collection phase. ', + name: 'elasticsearch.gc.phase.name', + type: 'keyword', + }, + 'elasticsearch.gc.phase.duration_sec': { + category: 'elasticsearch', + description: 'Collection phase duration according to the Java virtual machine. ', + name: 'elasticsearch.gc.phase.duration_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.scrub_symbol_table_time_sec': { + category: 'elasticsearch', + description: 'Pause time in seconds cleaning up symbol tables. ', + name: 'elasticsearch.gc.phase.scrub_symbol_table_time_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.scrub_string_table_time_sec': { + category: 'elasticsearch', + description: 'Pause time in seconds cleaning up string tables. ', + name: 'elasticsearch.gc.phase.scrub_string_table_time_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.weak_refs_processing_time_sec': { + category: 'elasticsearch', + description: 'Time spent processing weak references in seconds. ', + name: 'elasticsearch.gc.phase.weak_refs_processing_time_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.parallel_rescan_time_sec': { + category: 'elasticsearch', + description: 'Time spent in seconds marking live objects while application is stopped. ', + name: 'elasticsearch.gc.phase.parallel_rescan_time_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.class_unload_time_sec': { + category: 'elasticsearch', + description: 'Time spent unloading unused classes in seconds. ', + name: 'elasticsearch.gc.phase.class_unload_time_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.cpu_time.user_sec': { + category: 'elasticsearch', + description: 'CPU time spent outside the kernel. ', + name: 'elasticsearch.gc.phase.cpu_time.user_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.cpu_time.sys_sec': { + category: 'elasticsearch', + description: 'CPU time spent inside the kernel. ', + name: 'elasticsearch.gc.phase.cpu_time.sys_sec', + type: 'float', + }, + 'elasticsearch.gc.phase.cpu_time.real_sec': { + category: 'elasticsearch', + description: 'Total elapsed CPU time spent to complete the collection from start to finish. ', + name: 'elasticsearch.gc.phase.cpu_time.real_sec', + type: 'float', + }, + 'elasticsearch.gc.jvm_runtime_sec': { + category: 'elasticsearch', + description: 'The time from JVM start up in seconds, as a floating point number. ', + name: 'elasticsearch.gc.jvm_runtime_sec', + type: 'float', + }, + 'elasticsearch.gc.threads_total_stop_time_sec': { + category: 'elasticsearch', + description: 'Garbage collection threads total stop time seconds. ', + name: 'elasticsearch.gc.threads_total_stop_time_sec', + type: 'float', + }, + 'elasticsearch.gc.stopping_threads_time_sec': { + category: 'elasticsearch', + description: 'Time took to stop threads seconds. ', + name: 'elasticsearch.gc.stopping_threads_time_sec', + type: 'float', + }, + 'elasticsearch.gc.tags': { + category: 'elasticsearch', + description: 'GC logging tags. ', + name: 'elasticsearch.gc.tags', + type: 'keyword', + }, + 'elasticsearch.gc.heap.size_kb': { + category: 'elasticsearch', + description: 'Total heap size in kilobytes. ', + name: 'elasticsearch.gc.heap.size_kb', + type: 'integer', + }, + 'elasticsearch.gc.heap.used_kb': { + category: 'elasticsearch', + description: 'Used heap in kilobytes. ', + name: 'elasticsearch.gc.heap.used_kb', + type: 'integer', + }, + 'elasticsearch.gc.old_gen.size_kb': { + category: 'elasticsearch', + description: 'Total size of old generation in kilobytes. ', + name: 'elasticsearch.gc.old_gen.size_kb', + type: 'integer', + }, + 'elasticsearch.gc.old_gen.used_kb': { + category: 'elasticsearch', + description: 'Old generation occupancy in kilobytes. ', + name: 'elasticsearch.gc.old_gen.used_kb', + type: 'integer', + }, + 'elasticsearch.gc.young_gen.size_kb': { + category: 'elasticsearch', + description: 'Total size of young generation in kilobytes. ', + name: 'elasticsearch.gc.young_gen.size_kb', + type: 'integer', + }, + 'elasticsearch.gc.young_gen.used_kb': { + category: 'elasticsearch', + description: 'Young generation occupancy in kilobytes. ', + name: 'elasticsearch.gc.young_gen.used_kb', + type: 'integer', + }, + 'elasticsearch.server.stacktrace': { + category: 'elasticsearch', + name: 'elasticsearch.server.stacktrace', + }, + 'elasticsearch.server.gc.young.one': { + category: 'elasticsearch', + description: '', + example: '', + name: 'elasticsearch.server.gc.young.one', + type: 'long', + }, + 'elasticsearch.server.gc.young.two': { + category: 'elasticsearch', + description: '', + example: '', + name: 'elasticsearch.server.gc.young.two', + type: 'long', + }, + 'elasticsearch.server.gc.overhead_seq': { + category: 'elasticsearch', + description: 'Sequence number', + example: 3449992, + name: 'elasticsearch.server.gc.overhead_seq', + type: 'long', + }, + 'elasticsearch.server.gc.collection_duration.ms': { + category: 'elasticsearch', + description: 'Time spent in GC, in milliseconds', + example: 1600, + name: 'elasticsearch.server.gc.collection_duration.ms', + type: 'float', + }, + 'elasticsearch.server.gc.observation_duration.ms': { + category: 'elasticsearch', + description: 'Total time over which collection was observed, in milliseconds', + example: 1800, + name: 'elasticsearch.server.gc.observation_duration.ms', + type: 'float', + }, + 'elasticsearch.slowlog.logger': { + category: 'elasticsearch', + description: 'Logger name', + example: 'index.search.slowlog.fetch', + name: 'elasticsearch.slowlog.logger', + type: 'keyword', + }, + 'elasticsearch.slowlog.took': { + category: 'elasticsearch', + description: 'Time it took to execute the query', + example: '300ms', + name: 'elasticsearch.slowlog.took', + type: 'keyword', + }, + 'elasticsearch.slowlog.types': { + category: 'elasticsearch', + description: 'Types', + example: '', + name: 'elasticsearch.slowlog.types', + type: 'keyword', + }, + 'elasticsearch.slowlog.stats': { + category: 'elasticsearch', + description: 'Stats groups', + example: 'group1', + name: 'elasticsearch.slowlog.stats', + type: 'keyword', + }, + 'elasticsearch.slowlog.search_type': { + category: 'elasticsearch', + description: 'Search type', + example: 'QUERY_THEN_FETCH', + name: 'elasticsearch.slowlog.search_type', + type: 'keyword', + }, + 'elasticsearch.slowlog.source_query': { + category: 'elasticsearch', + description: 'Slow query', + example: '{"query":{"match_all":{"boost":1.0}}}', + name: 'elasticsearch.slowlog.source_query', + type: 'keyword', + }, + 'elasticsearch.slowlog.extra_source': { + category: 'elasticsearch', + description: 'Extra source information', + example: '', + name: 'elasticsearch.slowlog.extra_source', + type: 'keyword', + }, + 'elasticsearch.slowlog.total_hits': { + category: 'elasticsearch', + description: 'Total hits', + example: 42, + name: 'elasticsearch.slowlog.total_hits', + type: 'keyword', + }, + 'elasticsearch.slowlog.total_shards': { + category: 'elasticsearch', + description: 'Total queried shards', + example: 22, + name: 'elasticsearch.slowlog.total_shards', + type: 'keyword', + }, + 'elasticsearch.slowlog.routing': { + category: 'elasticsearch', + description: 'Routing', + example: 's01HZ2QBk9jw4gtgaFtn', + name: 'elasticsearch.slowlog.routing', + type: 'keyword', + }, + 'elasticsearch.slowlog.id': { + category: 'elasticsearch', + description: 'Id', + example: '', + name: 'elasticsearch.slowlog.id', + type: 'keyword', + }, + 'elasticsearch.slowlog.type': { + category: 'elasticsearch', + description: 'Type', + example: 'doc', + name: 'elasticsearch.slowlog.type', + type: 'keyword', + }, + 'elasticsearch.slowlog.source': { + category: 'elasticsearch', + description: 'Source of document that was indexed', + name: 'elasticsearch.slowlog.source', + type: 'keyword', + }, + 'haproxy.frontend_name': { + category: 'haproxy', + description: 'Name of the frontend (or listener) which received and processed the connection.', + name: 'haproxy.frontend_name', + }, + 'haproxy.backend_name': { + category: 'haproxy', + description: + 'Name of the backend (or listener) which was selected to manage the connection to the server.', + name: 'haproxy.backend_name', + }, + 'haproxy.server_name': { + category: 'haproxy', + description: 'Name of the last server to which the connection was sent.', + name: 'haproxy.server_name', + }, + 'haproxy.total_waiting_time_ms': { + category: 'haproxy', + description: 'Total time in milliseconds spent waiting in the various queues', + name: 'haproxy.total_waiting_time_ms', + type: 'long', + }, + 'haproxy.connection_wait_time_ms': { + category: 'haproxy', + description: + 'Total time in milliseconds spent waiting for the connection to establish to the final server', + name: 'haproxy.connection_wait_time_ms', + type: 'long', + }, + 'haproxy.bytes_read': { + category: 'haproxy', + description: 'Total number of bytes transmitted to the client when the log is emitted.', + name: 'haproxy.bytes_read', + type: 'long', + }, + 'haproxy.time_queue': { + category: 'haproxy', + description: 'Total time in milliseconds spent waiting in the various queues.', + name: 'haproxy.time_queue', + type: 'long', + }, + 'haproxy.time_backend_connect': { + category: 'haproxy', + description: + 'Total time in milliseconds spent waiting for the connection to establish to the final server, including retries.', + name: 'haproxy.time_backend_connect', + type: 'long', + }, + 'haproxy.server_queue': { + category: 'haproxy', + description: + 'Total number of requests which were processed before this one in the server queue.', + name: 'haproxy.server_queue', + type: 'long', + }, + 'haproxy.backend_queue': { + category: 'haproxy', + description: + "Total number of requests which were processed before this one in the backend's global queue.", + name: 'haproxy.backend_queue', + type: 'long', + }, + 'haproxy.bind_name': { + category: 'haproxy', + description: 'Name of the listening address which received the connection.', + name: 'haproxy.bind_name', + }, + 'haproxy.error_message': { + category: 'haproxy', + description: 'Error message logged by HAProxy in case of error.', + name: 'haproxy.error_message', + type: 'text', + }, + 'haproxy.source': { + category: 'haproxy', + description: 'The HAProxy source of the log', + name: 'haproxy.source', + type: 'keyword', + }, + 'haproxy.termination_state': { + category: 'haproxy', + description: 'Condition the session was in when the session ended.', + name: 'haproxy.termination_state', + }, + 'haproxy.mode': { + category: 'haproxy', + description: 'mode that the frontend is operating (TCP or HTTP)', + name: 'haproxy.mode', + type: 'keyword', + }, + 'haproxy.connections.active': { + category: 'haproxy', + description: + 'Total number of concurrent connections on the process when the session was logged.', + name: 'haproxy.connections.active', + type: 'long', + }, + 'haproxy.connections.frontend': { + category: 'haproxy', + description: + 'Total number of concurrent connections on the frontend when the session was logged.', + name: 'haproxy.connections.frontend', + type: 'long', + }, + 'haproxy.connections.backend': { + category: 'haproxy', + description: + 'Total number of concurrent connections handled by the backend when the session was logged.', + name: 'haproxy.connections.backend', + type: 'long', + }, + 'haproxy.connections.server': { + category: 'haproxy', + description: + 'Total number of concurrent connections still active on the server when the session was logged.', + name: 'haproxy.connections.server', + type: 'long', + }, + 'haproxy.connections.retries': { + category: 'haproxy', + description: + 'Number of connection retries experienced by this session when trying to connect to the server.', + name: 'haproxy.connections.retries', + type: 'long', + }, + 'haproxy.client.ip': { + category: 'haproxy', + name: 'haproxy.client.ip', + type: 'alias', + }, + 'haproxy.client.port': { + category: 'haproxy', + name: 'haproxy.client.port', + type: 'alias', + }, + 'haproxy.process_name': { + category: 'haproxy', + name: 'haproxy.process_name', + type: 'alias', + }, + 'haproxy.pid': { + category: 'haproxy', + name: 'haproxy.pid', + type: 'alias', + }, + 'haproxy.destination.port': { + category: 'haproxy', + name: 'haproxy.destination.port', + type: 'alias', + }, + 'haproxy.destination.ip': { + category: 'haproxy', + name: 'haproxy.destination.ip', + type: 'alias', + }, + 'haproxy.geoip.continent_name': { + category: 'haproxy', + name: 'haproxy.geoip.continent_name', + type: 'alias', + }, + 'haproxy.geoip.country_iso_code': { + category: 'haproxy', + name: 'haproxy.geoip.country_iso_code', + type: 'alias', + }, + 'haproxy.geoip.location': { + category: 'haproxy', + name: 'haproxy.geoip.location', + type: 'alias', + }, + 'haproxy.geoip.region_name': { + category: 'haproxy', + name: 'haproxy.geoip.region_name', + type: 'alias', + }, + 'haproxy.geoip.city_name': { + category: 'haproxy', + name: 'haproxy.geoip.city_name', + type: 'alias', + }, + 'haproxy.geoip.region_iso_code': { + category: 'haproxy', + name: 'haproxy.geoip.region_iso_code', + type: 'alias', + }, + 'haproxy.http.response.captured_cookie': { + category: 'haproxy', + description: + 'Optional "name=value" entry indicating that the client had this cookie in the response. ', + name: 'haproxy.http.response.captured_cookie', + }, + 'haproxy.http.response.captured_headers': { + category: 'haproxy', + description: + 'List of headers captured in the response due to the presence of the "capture response header" statement in the frontend. ', + name: 'haproxy.http.response.captured_headers', + type: 'keyword', + }, + 'haproxy.http.response.status_code': { + category: 'haproxy', + name: 'haproxy.http.response.status_code', + type: 'alias', + }, + 'haproxy.http.request.captured_cookie': { + category: 'haproxy', + description: + 'Optional "name=value" entry indicating that the server has returned a cookie with its request. ', + name: 'haproxy.http.request.captured_cookie', + }, + 'haproxy.http.request.captured_headers': { + category: 'haproxy', + description: + 'List of headers captured in the request due to the presence of the "capture request header" statement in the frontend. ', + name: 'haproxy.http.request.captured_headers', + type: 'keyword', + }, + 'haproxy.http.request.raw_request_line': { + category: 'haproxy', + description: + 'Complete HTTP request line, including the method, request and HTTP version string.', + name: 'haproxy.http.request.raw_request_line', + type: 'keyword', + }, + 'haproxy.http.request.time_wait_without_data_ms': { + category: 'haproxy', + description: + 'Total time in milliseconds spent waiting for the server to send a full HTTP response, not counting data.', + name: 'haproxy.http.request.time_wait_without_data_ms', + type: 'long', + }, + 'haproxy.http.request.time_wait_ms': { + category: 'haproxy', + description: + 'Total time in milliseconds spent waiting for a full HTTP request from the client (not counting body) after the first byte was received.', + name: 'haproxy.http.request.time_wait_ms', + type: 'long', + }, + 'haproxy.tcp.connection_waiting_time_ms': { + category: 'haproxy', + description: 'Total time in milliseconds elapsed between the accept and the last close', + name: 'haproxy.tcp.connection_waiting_time_ms', + type: 'long', + }, + 'icinga.debug.facility': { + category: 'icinga', + description: 'Specifies what component of Icinga logged the message. ', + name: 'icinga.debug.facility', + type: 'keyword', + }, + 'icinga.debug.severity': { + category: 'icinga', + name: 'icinga.debug.severity', + type: 'alias', + }, + 'icinga.debug.message': { + category: 'icinga', + name: 'icinga.debug.message', + type: 'alias', + }, + 'icinga.main.facility': { + category: 'icinga', + description: 'Specifies what component of Icinga logged the message. ', + name: 'icinga.main.facility', + type: 'keyword', + }, + 'icinga.main.severity': { + category: 'icinga', + name: 'icinga.main.severity', + type: 'alias', + }, + 'icinga.main.message': { + category: 'icinga', + name: 'icinga.main.message', + type: 'alias', + }, + 'icinga.startup.facility': { + category: 'icinga', + description: 'Specifies what component of Icinga logged the message. ', + name: 'icinga.startup.facility', + type: 'keyword', + }, + 'icinga.startup.severity': { + category: 'icinga', + name: 'icinga.startup.severity', + type: 'alias', + }, + 'icinga.startup.message': { + category: 'icinga', + name: 'icinga.startup.message', + type: 'alias', + }, + 'iis.access.sub_status': { + category: 'iis', + description: 'The HTTP substatus code. ', + name: 'iis.access.sub_status', + type: 'long', + }, + 'iis.access.win32_status': { + category: 'iis', + description: 'The Windows status code. ', + name: 'iis.access.win32_status', + type: 'long', + }, + 'iis.access.site_name': { + category: 'iis', + description: 'The site name and instance number. ', + name: 'iis.access.site_name', + type: 'keyword', + }, + 'iis.access.server_name': { + category: 'iis', + description: 'The name of the server on which the log file entry was generated. ', + name: 'iis.access.server_name', + type: 'keyword', + }, + 'iis.access.cookie': { + category: 'iis', + description: 'The content of the cookie sent or received, if any. ', + name: 'iis.access.cookie', + type: 'keyword', + }, + 'iis.access.body_received.bytes': { + category: 'iis', + name: 'iis.access.body_received.bytes', + type: 'alias', + }, + 'iis.access.body_sent.bytes': { + category: 'iis', + name: 'iis.access.body_sent.bytes', + type: 'alias', + }, + 'iis.access.server_ip': { + category: 'iis', + name: 'iis.access.server_ip', + type: 'alias', + }, + 'iis.access.method': { + category: 'iis', + name: 'iis.access.method', + type: 'alias', + }, + 'iis.access.url': { + category: 'iis', + name: 'iis.access.url', + type: 'alias', + }, + 'iis.access.query_string': { + category: 'iis', + name: 'iis.access.query_string', + type: 'alias', + }, + 'iis.access.port': { + category: 'iis', + name: 'iis.access.port', + type: 'alias', + }, + 'iis.access.user_name': { + category: 'iis', + name: 'iis.access.user_name', + type: 'alias', + }, + 'iis.access.remote_ip': { + category: 'iis', + name: 'iis.access.remote_ip', + type: 'alias', + }, + 'iis.access.referrer': { + category: 'iis', + name: 'iis.access.referrer', + type: 'alias', + }, + 'iis.access.response_code': { + category: 'iis', + name: 'iis.access.response_code', + type: 'alias', + }, + 'iis.access.http_version': { + category: 'iis', + name: 'iis.access.http_version', + type: 'alias', + }, + 'iis.access.hostname': { + category: 'iis', + name: 'iis.access.hostname', + type: 'alias', + }, + 'iis.access.user_agent.device': { + category: 'iis', + name: 'iis.access.user_agent.device', + type: 'alias', + }, + 'iis.access.user_agent.name': { + category: 'iis', + name: 'iis.access.user_agent.name', + type: 'alias', + }, + 'iis.access.user_agent.os': { + category: 'iis', + name: 'iis.access.user_agent.os', + type: 'alias', + }, + 'iis.access.user_agent.os_name': { + category: 'iis', + name: 'iis.access.user_agent.os_name', + type: 'alias', + }, + 'iis.access.user_agent.original': { + category: 'iis', + name: 'iis.access.user_agent.original', + type: 'alias', + }, + 'iis.access.geoip.continent_name': { + category: 'iis', + name: 'iis.access.geoip.continent_name', + type: 'alias', + }, + 'iis.access.geoip.country_iso_code': { + category: 'iis', + name: 'iis.access.geoip.country_iso_code', + type: 'alias', + }, + 'iis.access.geoip.location': { + category: 'iis', + name: 'iis.access.geoip.location', + type: 'alias', + }, + 'iis.access.geoip.region_name': { + category: 'iis', + name: 'iis.access.geoip.region_name', + type: 'alias', + }, + 'iis.access.geoip.city_name': { + category: 'iis', + name: 'iis.access.geoip.city_name', + type: 'alias', + }, + 'iis.access.geoip.region_iso_code': { + category: 'iis', + name: 'iis.access.geoip.region_iso_code', + type: 'alias', + }, + 'iis.error.reason_phrase': { + category: 'iis', + description: 'The HTTP reason phrase. ', + name: 'iis.error.reason_phrase', + type: 'keyword', + }, + 'iis.error.queue_name': { + category: 'iis', + description: 'The IIS application pool name. ', + name: 'iis.error.queue_name', + type: 'keyword', + }, + 'iis.error.remote_ip': { + category: 'iis', + name: 'iis.error.remote_ip', + type: 'alias', + }, + 'iis.error.remote_port': { + category: 'iis', + name: 'iis.error.remote_port', + type: 'alias', + }, + 'iis.error.server_ip': { + category: 'iis', + name: 'iis.error.server_ip', + type: 'alias', + }, + 'iis.error.server_port': { + category: 'iis', + name: 'iis.error.server_port', + type: 'alias', + }, + 'iis.error.http_version': { + category: 'iis', + name: 'iis.error.http_version', + type: 'alias', + }, + 'iis.error.method': { + category: 'iis', + name: 'iis.error.method', + type: 'alias', + }, + 'iis.error.url': { + category: 'iis', + name: 'iis.error.url', + type: 'alias', + }, + 'iis.error.response_code': { + category: 'iis', + name: 'iis.error.response_code', + type: 'alias', + }, + 'iis.error.geoip.continent_name': { + category: 'iis', + name: 'iis.error.geoip.continent_name', + type: 'alias', + }, + 'iis.error.geoip.country_iso_code': { + category: 'iis', + name: 'iis.error.geoip.country_iso_code', + type: 'alias', + }, + 'iis.error.geoip.location': { + category: 'iis', + name: 'iis.error.geoip.location', + type: 'alias', + }, + 'iis.error.geoip.region_name': { + category: 'iis', + name: 'iis.error.geoip.region_name', + type: 'alias', + }, + 'iis.error.geoip.city_name': { + category: 'iis', + name: 'iis.error.geoip.city_name', + type: 'alias', + }, + 'iis.error.geoip.region_iso_code': { + category: 'iis', + name: 'iis.error.geoip.region_iso_code', + type: 'alias', + }, + 'kafka.log.level': { + category: 'kafka', + name: 'kafka.log.level', + type: 'alias', + }, + 'kafka.log.message': { + category: 'kafka', + name: 'kafka.log.message', + type: 'alias', + }, + 'kafka.log.component': { + category: 'kafka', + description: 'Component the log is coming from. ', + name: 'kafka.log.component', + type: 'keyword', + }, + 'kafka.log.class': { + category: 'kafka', + description: 'Java class the log is coming from. ', + name: 'kafka.log.class', + type: 'keyword', + }, + 'kafka.log.thread': { + category: 'kafka', + description: 'Thread name the log is coming from. ', + name: 'kafka.log.thread', + type: 'keyword', + }, + 'kafka.log.trace.class': { + category: 'kafka', + description: 'Java class the trace is coming from. ', + name: 'kafka.log.trace.class', + type: 'keyword', + }, + 'kafka.log.trace.message': { + category: 'kafka', + description: 'Message part of the trace. ', + name: 'kafka.log.trace.message', + type: 'text', + }, + 'kibana.log.tags': { + category: 'kibana', + description: 'Kibana logging tags. ', + name: 'kibana.log.tags', + type: 'keyword', + }, + 'kibana.log.state': { + category: 'kibana', + description: 'Current state of Kibana. ', + name: 'kibana.log.state', + type: 'keyword', + }, + 'kibana.log.meta': { + category: 'kibana', + name: 'kibana.log.meta', + type: 'object', + }, + 'kibana.log.kibana.log.meta.req.headers.referer': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.req.headers.referer', + type: 'alias', + }, + 'kibana.log.kibana.log.meta.req.referer': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.req.referer', + type: 'alias', + }, + 'kibana.log.kibana.log.meta.req.headers.user-agent': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.req.headers.user-agent', + type: 'alias', + }, + 'kibana.log.kibana.log.meta.req.remoteAddress': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.req.remoteAddress', + type: 'alias', + }, + 'kibana.log.kibana.log.meta.req.url': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.req.url', + type: 'alias', + }, + 'kibana.log.kibana.log.meta.statusCode': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.statusCode', + type: 'alias', + }, + 'kibana.log.kibana.log.meta.method': { + category: 'kibana', + name: 'kibana.log.kibana.log.meta.method', + type: 'alias', + }, + 'logstash.log.module': { + category: 'logstash', + description: 'The module or class where the event originate. ', + name: 'logstash.log.module', + type: 'keyword', + }, + 'logstash.log.thread': { + category: 'logstash', + description: 'Information about the running thread where the log originate. ', + name: 'logstash.log.thread', + type: 'keyword', + }, + 'logstash.log.log_event': { + category: 'logstash', + description: 'key and value debugging information. ', + name: 'logstash.log.log_event', + type: 'object', + }, + 'logstash.log.pipeline_id': { + category: 'logstash', + description: 'The ID of the pipeline. ', + example: 'main', + name: 'logstash.log.pipeline_id', + type: 'keyword', + }, + 'logstash.log.message': { + category: 'logstash', + name: 'logstash.log.message', + type: 'alias', + }, + 'logstash.log.level': { + category: 'logstash', + name: 'logstash.log.level', + type: 'alias', + }, + 'logstash.slowlog.module': { + category: 'logstash', + description: 'The module or class where the event originate. ', + name: 'logstash.slowlog.module', + type: 'keyword', + }, + 'logstash.slowlog.thread': { + category: 'logstash', + description: 'Information about the running thread where the log originate. ', + name: 'logstash.slowlog.thread', + type: 'keyword', + }, + 'logstash.slowlog.event': { + category: 'logstash', + description: 'Raw dump of the original event ', + name: 'logstash.slowlog.event', + type: 'keyword', + }, + 'logstash.slowlog.plugin_name': { + category: 'logstash', + description: 'Name of the plugin ', + name: 'logstash.slowlog.plugin_name', + type: 'keyword', + }, + 'logstash.slowlog.plugin_type': { + category: 'logstash', + description: 'Type of the plugin: Inputs, Filters, Outputs or Codecs. ', + name: 'logstash.slowlog.plugin_type', + type: 'keyword', + }, + 'logstash.slowlog.took_in_millis': { + category: 'logstash', + description: 'Execution time for the plugin in milliseconds. ', + name: 'logstash.slowlog.took_in_millis', + type: 'long', + }, + 'logstash.slowlog.plugin_params': { + category: 'logstash', + description: 'String value of the plugin configuration ', + name: 'logstash.slowlog.plugin_params', + type: 'keyword', + }, + 'logstash.slowlog.plugin_params_object': { + category: 'logstash', + description: 'key -> value of the configuration used by the plugin. ', + name: 'logstash.slowlog.plugin_params_object', + type: 'object', + }, + 'logstash.slowlog.level': { + category: 'logstash', + name: 'logstash.slowlog.level', + type: 'alias', + }, + 'logstash.slowlog.took_in_nanos': { + category: 'logstash', + name: 'logstash.slowlog.took_in_nanos', + type: 'alias', + }, + 'mongodb.log.component': { + category: 'mongodb', + description: 'Functional categorization of message ', + example: 'COMMAND', + name: 'mongodb.log.component', + type: 'keyword', + }, + 'mongodb.log.context': { + category: 'mongodb', + description: 'Context of message ', + example: 'initandlisten', + name: 'mongodb.log.context', + type: 'keyword', + }, + 'mongodb.log.severity': { + category: 'mongodb', + name: 'mongodb.log.severity', + type: 'alias', + }, + 'mongodb.log.message': { + category: 'mongodb', + name: 'mongodb.log.message', + type: 'alias', + }, + 'mysql.thread_id': { + category: 'mysql', + description: 'The connection or thread ID for the query. ', + name: 'mysql.thread_id', + type: 'long', + }, + 'mysql.error.thread_id': { + category: 'mysql', + name: 'mysql.error.thread_id', + type: 'alias', + }, + 'mysql.error.level': { + category: 'mysql', + name: 'mysql.error.level', + type: 'alias', + }, + 'mysql.error.message': { + category: 'mysql', + name: 'mysql.error.message', + type: 'alias', + }, + 'mysql.slowlog.lock_time.sec': { + category: 'mysql', + description: + 'The amount of time the query waited for the lock to be available. The value is in seconds, as a floating point number. ', + name: 'mysql.slowlog.lock_time.sec', + type: 'float', + }, + 'mysql.slowlog.rows_sent': { + category: 'mysql', + description: 'The number of rows returned by the query. ', + name: 'mysql.slowlog.rows_sent', + type: 'long', + }, + 'mysql.slowlog.rows_examined': { + category: 'mysql', + description: 'The number of rows scanned by the query. ', + name: 'mysql.slowlog.rows_examined', + type: 'long', + }, + 'mysql.slowlog.rows_affected': { + category: 'mysql', + description: 'The number of rows modified by the query. ', + name: 'mysql.slowlog.rows_affected', + type: 'long', + }, + 'mysql.slowlog.bytes_sent': { + category: 'mysql', + description: 'The number of bytes sent to client. ', + name: 'mysql.slowlog.bytes_sent', + type: 'long', + format: 'bytes', + }, + 'mysql.slowlog.bytes_received': { + category: 'mysql', + description: 'The number of bytes received from client. ', + name: 'mysql.slowlog.bytes_received', + type: 'long', + format: 'bytes', + }, + 'mysql.slowlog.query': { + category: 'mysql', + description: 'The slow query. ', + name: 'mysql.slowlog.query', + }, + 'mysql.slowlog.id': { + category: 'mysql', + name: 'mysql.slowlog.id', + type: 'alias', + }, + 'mysql.slowlog.schema': { + category: 'mysql', + description: 'The schema where the slow query was executed. ', + name: 'mysql.slowlog.schema', + type: 'keyword', + }, + 'mysql.slowlog.current_user': { + category: 'mysql', + description: + 'Current authenticated user, used to determine access privileges. Can differ from the value for user. ', + name: 'mysql.slowlog.current_user', + type: 'keyword', + }, + 'mysql.slowlog.last_errno': { + category: 'mysql', + description: 'Last SQL error seen. ', + name: 'mysql.slowlog.last_errno', + type: 'keyword', + }, + 'mysql.slowlog.killed': { + category: 'mysql', + description: 'Code of the reason if the query was killed. ', + name: 'mysql.slowlog.killed', + type: 'keyword', + }, + 'mysql.slowlog.query_cache_hit': { + category: 'mysql', + description: 'Whether the query cache was hit. ', + name: 'mysql.slowlog.query_cache_hit', + type: 'boolean', + }, + 'mysql.slowlog.tmp_table': { + category: 'mysql', + description: 'Whether a temporary table was used to resolve the query. ', + name: 'mysql.slowlog.tmp_table', + type: 'boolean', + }, + 'mysql.slowlog.tmp_table_on_disk': { + category: 'mysql', + description: 'Whether the query needed temporary tables on disk. ', + name: 'mysql.slowlog.tmp_table_on_disk', + type: 'boolean', + }, + 'mysql.slowlog.tmp_tables': { + category: 'mysql', + description: 'Number of temporary tables created for this query ', + name: 'mysql.slowlog.tmp_tables', + type: 'long', + }, + 'mysql.slowlog.tmp_disk_tables': { + category: 'mysql', + description: 'Number of temporary tables created on disk for this query. ', + name: 'mysql.slowlog.tmp_disk_tables', + type: 'long', + }, + 'mysql.slowlog.tmp_table_sizes': { + category: 'mysql', + description: 'Size of temporary tables created for this query.', + name: 'mysql.slowlog.tmp_table_sizes', + type: 'long', + format: 'bytes', + }, + 'mysql.slowlog.filesort': { + category: 'mysql', + description: 'Whether filesort optimization was used. ', + name: 'mysql.slowlog.filesort', + type: 'boolean', + }, + 'mysql.slowlog.filesort_on_disk': { + category: 'mysql', + description: 'Whether filesort optimization was used and it needed temporary tables on disk. ', + name: 'mysql.slowlog.filesort_on_disk', + type: 'boolean', + }, + 'mysql.slowlog.priority_queue': { + category: 'mysql', + description: 'Whether a priority queue was used for filesort. ', + name: 'mysql.slowlog.priority_queue', + type: 'boolean', + }, + 'mysql.slowlog.full_scan': { + category: 'mysql', + description: 'Whether a full table scan was needed for the slow query. ', + name: 'mysql.slowlog.full_scan', + type: 'boolean', + }, + 'mysql.slowlog.full_join': { + category: 'mysql', + description: + 'Whether a full join was needed for the slow query (no indexes were used for joins). ', + name: 'mysql.slowlog.full_join', + type: 'boolean', + }, + 'mysql.slowlog.merge_passes': { + category: 'mysql', + description: 'Number of merge passes executed for the query. ', + name: 'mysql.slowlog.merge_passes', + type: 'long', + }, + 'mysql.slowlog.sort_merge_passes': { + category: 'mysql', + description: 'Number of merge passes that the sort algorithm has had to do. ', + name: 'mysql.slowlog.sort_merge_passes', + type: 'long', + }, + 'mysql.slowlog.sort_range_count': { + category: 'mysql', + description: 'Number of sorts that were done using ranges. ', + name: 'mysql.slowlog.sort_range_count', + type: 'long', + }, + 'mysql.slowlog.sort_rows': { + category: 'mysql', + description: 'Number of sorted rows. ', + name: 'mysql.slowlog.sort_rows', + type: 'long', + }, + 'mysql.slowlog.sort_scan_count': { + category: 'mysql', + description: 'Number of sorts that were done by scanning the table. ', + name: 'mysql.slowlog.sort_scan_count', + type: 'long', + }, + 'mysql.slowlog.log_slow_rate_type': { + category: 'mysql', + description: + 'Type of slow log rate limit, it can be `session` if the rate limit is applied per session, or `query` if it applies per query. ', + name: 'mysql.slowlog.log_slow_rate_type', + type: 'keyword', + }, + 'mysql.slowlog.log_slow_rate_limit': { + category: 'mysql', + description: + 'Slow log rate limit, a value of 100 means that one in a hundred queries or sessions are being logged. ', + name: 'mysql.slowlog.log_slow_rate_limit', + type: 'keyword', + }, + 'mysql.slowlog.read_first': { + category: 'mysql', + description: 'The number of times the first entry in an index was read. ', + name: 'mysql.slowlog.read_first', + type: 'long', + }, + 'mysql.slowlog.read_last': { + category: 'mysql', + description: 'The number of times the last key in an index was read. ', + name: 'mysql.slowlog.read_last', + type: 'long', + }, + 'mysql.slowlog.read_key': { + category: 'mysql', + description: 'The number of requests to read a row based on a key. ', + name: 'mysql.slowlog.read_key', + type: 'long', + }, + 'mysql.slowlog.read_next': { + category: 'mysql', + description: 'The number of requests to read the next row in key order. ', + name: 'mysql.slowlog.read_next', + type: 'long', + }, + 'mysql.slowlog.read_prev': { + category: 'mysql', + description: 'The number of requests to read the previous row in key order. ', + name: 'mysql.slowlog.read_prev', + type: 'long', + }, + 'mysql.slowlog.read_rnd': { + category: 'mysql', + description: 'The number of requests to read a row based on a fixed position. ', + name: 'mysql.slowlog.read_rnd', + type: 'long', + }, + 'mysql.slowlog.read_rnd_next': { + category: 'mysql', + description: 'The number of requests to read the next row in the data file. ', + name: 'mysql.slowlog.read_rnd_next', + type: 'long', + }, + 'mysql.slowlog.innodb.trx_id': { + category: 'mysql', + description: 'Transaction ID ', + name: 'mysql.slowlog.innodb.trx_id', + type: 'keyword', + }, + 'mysql.slowlog.innodb.io_r_ops': { + category: 'mysql', + description: 'Number of page read operations. ', + name: 'mysql.slowlog.innodb.io_r_ops', + type: 'long', + }, + 'mysql.slowlog.innodb.io_r_bytes': { + category: 'mysql', + description: 'Bytes read during page read operations. ', + name: 'mysql.slowlog.innodb.io_r_bytes', + type: 'long', + format: 'bytes', + }, + 'mysql.slowlog.innodb.io_r_wait.sec': { + category: 'mysql', + description: 'How long it took to read all needed data from storage. ', + name: 'mysql.slowlog.innodb.io_r_wait.sec', + type: 'long', + }, + 'mysql.slowlog.innodb.rec_lock_wait.sec': { + category: 'mysql', + description: 'How long the query waited for locks. ', + name: 'mysql.slowlog.innodb.rec_lock_wait.sec', + type: 'long', + }, + 'mysql.slowlog.innodb.queue_wait.sec': { + category: 'mysql', + description: + 'How long the query waited to enter the InnoDB queue and to be executed once in the queue. ', + name: 'mysql.slowlog.innodb.queue_wait.sec', + type: 'long', + }, + 'mysql.slowlog.innodb.pages_distinct': { + category: 'mysql', + description: 'Approximated count of pages accessed to execute the query. ', + name: 'mysql.slowlog.innodb.pages_distinct', + type: 'long', + }, + 'mysql.slowlog.user': { + category: 'mysql', + name: 'mysql.slowlog.user', + type: 'alias', + }, + 'mysql.slowlog.host': { + category: 'mysql', + name: 'mysql.slowlog.host', + type: 'alias', + }, + 'mysql.slowlog.ip': { + category: 'mysql', + name: 'mysql.slowlog.ip', + type: 'alias', + }, + 'nats.log.client.id': { + category: 'nats', + description: 'The id of the client ', + name: 'nats.log.client.id', + type: 'integer', + }, + 'nats.log.msg.bytes': { + category: 'nats', + description: 'Size of the payload in bytes ', + name: 'nats.log.msg.bytes', + type: 'long', + format: 'bytes', + }, + 'nats.log.msg.type': { + category: 'nats', + description: 'The protocol message type ', + name: 'nats.log.msg.type', + type: 'keyword', + }, + 'nats.log.msg.subject': { + category: 'nats', + description: 'Subject name this message was received on ', + name: 'nats.log.msg.subject', + type: 'keyword', + }, + 'nats.log.msg.sid': { + category: 'nats', + description: 'The unique alphanumeric subscription ID of the subject ', + name: 'nats.log.msg.sid', + type: 'integer', + }, + 'nats.log.msg.reply_to': { + category: 'nats', + description: 'The inbox subject on which the publisher is listening for responses ', + name: 'nats.log.msg.reply_to', + type: 'keyword', + }, + 'nats.log.msg.max_messages': { + category: 'nats', + description: 'An optional number of messages to wait for before automatically unsubscribing ', + name: 'nats.log.msg.max_messages', + type: 'integer', + }, + 'nats.log.msg.error.message': { + category: 'nats', + description: 'Details about the error occurred ', + name: 'nats.log.msg.error.message', + type: 'text', + }, + 'nats.log.msg.queue_group': { + category: 'nats', + description: 'The queue group which subscriber will join ', + name: 'nats.log.msg.queue_group', + type: 'text', + }, + 'nginx.access.remote_ip_list': { + category: 'nginx', + description: + 'An array of remote IP addresses. It is a list because it is common to include, besides the client IP address, IP addresses from headers like `X-Forwarded-For`. Real source IP is restored to `source.ip`. ', + name: 'nginx.access.remote_ip_list', + type: 'array', + }, + 'nginx.access.body_sent.bytes': { + category: 'nginx', + name: 'nginx.access.body_sent.bytes', + type: 'alias', + }, + 'nginx.access.user_name': { + category: 'nginx', + name: 'nginx.access.user_name', + type: 'alias', + }, + 'nginx.access.method': { + category: 'nginx', + name: 'nginx.access.method', + type: 'alias', + }, + 'nginx.access.url': { + category: 'nginx', + name: 'nginx.access.url', + type: 'alias', + }, + 'nginx.access.http_version': { + category: 'nginx', + name: 'nginx.access.http_version', + type: 'alias', + }, + 'nginx.access.response_code': { + category: 'nginx', + name: 'nginx.access.response_code', + type: 'alias', + }, + 'nginx.access.referrer': { + category: 'nginx', + name: 'nginx.access.referrer', + type: 'alias', + }, + 'nginx.access.agent': { + category: 'nginx', + name: 'nginx.access.agent', + type: 'alias', + }, + 'nginx.access.user_agent.device': { + category: 'nginx', + name: 'nginx.access.user_agent.device', + type: 'alias', + }, + 'nginx.access.user_agent.name': { + category: 'nginx', + name: 'nginx.access.user_agent.name', + type: 'alias', + }, + 'nginx.access.user_agent.os': { + category: 'nginx', + name: 'nginx.access.user_agent.os', + type: 'alias', + }, + 'nginx.access.user_agent.os_name': { + category: 'nginx', + name: 'nginx.access.user_agent.os_name', + type: 'alias', + }, + 'nginx.access.user_agent.original': { + category: 'nginx', + name: 'nginx.access.user_agent.original', + type: 'alias', + }, + 'nginx.access.geoip.continent_name': { + category: 'nginx', + name: 'nginx.access.geoip.continent_name', + type: 'alias', + }, + 'nginx.access.geoip.country_iso_code': { + category: 'nginx', + name: 'nginx.access.geoip.country_iso_code', + type: 'alias', + }, + 'nginx.access.geoip.location': { + category: 'nginx', + name: 'nginx.access.geoip.location', + type: 'alias', + }, + 'nginx.access.geoip.region_name': { + category: 'nginx', + name: 'nginx.access.geoip.region_name', + type: 'alias', + }, + 'nginx.access.geoip.city_name': { + category: 'nginx', + name: 'nginx.access.geoip.city_name', + type: 'alias', + }, + 'nginx.access.geoip.region_iso_code': { + category: 'nginx', + name: 'nginx.access.geoip.region_iso_code', + type: 'alias', + }, + 'nginx.error.connection_id': { + category: 'nginx', + description: 'Connection identifier. ', + name: 'nginx.error.connection_id', + type: 'long', + }, + 'nginx.error.level': { + category: 'nginx', + name: 'nginx.error.level', + type: 'alias', + }, + 'nginx.error.pid': { + category: 'nginx', + name: 'nginx.error.pid', + type: 'alias', + }, + 'nginx.error.tid': { + category: 'nginx', + name: 'nginx.error.tid', + type: 'alias', + }, + 'nginx.error.message': { + category: 'nginx', + name: 'nginx.error.message', + type: 'alias', + }, + 'nginx.ingress_controller.remote_ip_list': { + category: 'nginx', + description: + 'An array of remote IP addresses. It is a list because it is common to include, besides the client IP address, IP addresses from headers like `X-Forwarded-For`. Real source IP is restored to `source.ip`. ', + name: 'nginx.ingress_controller.remote_ip_list', + type: 'array', + }, + 'nginx.ingress_controller.http.request.length': { + category: 'nginx', + description: 'The request length (including request line, header, and request body) ', + name: 'nginx.ingress_controller.http.request.length', + type: 'long', + format: 'bytes', + }, + 'nginx.ingress_controller.http.request.time': { + category: 'nginx', + description: 'Time elapsed since the first bytes were read from the client ', + name: 'nginx.ingress_controller.http.request.time', + type: 'double', + format: 'duration', + }, + 'nginx.ingress_controller.upstream.name': { + category: 'nginx', + description: 'The name of the upstream. ', + name: 'nginx.ingress_controller.upstream.name', + type: 'keyword', + }, + 'nginx.ingress_controller.upstream.alternative_name': { + category: 'nginx', + description: 'The name of the alternative upstream. ', + name: 'nginx.ingress_controller.upstream.alternative_name', + type: 'keyword', + }, + 'nginx.ingress_controller.upstream.response.length': { + category: 'nginx', + description: 'The length of the response obtained from the upstream server ', + name: 'nginx.ingress_controller.upstream.response.length', + type: 'long', + format: 'bytes', + }, + 'nginx.ingress_controller.upstream.response.time': { + category: 'nginx', + description: + 'The time spent on receiving the response from the upstream server as seconds with millisecond resolution ', + name: 'nginx.ingress_controller.upstream.response.time', + type: 'double', + format: 'duration', + }, + 'nginx.ingress_controller.upstream.response.status_code': { + category: 'nginx', + description: 'The status code of the response obtained from the upstream server ', + name: 'nginx.ingress_controller.upstream.response.status_code', + type: 'long', + }, + 'nginx.ingress_controller.http.request.id': { + category: 'nginx', + description: 'The randomly generated ID of the request ', + name: 'nginx.ingress_controller.http.request.id', + type: 'keyword', + }, + 'nginx.ingress_controller.upstream.ip': { + category: 'nginx', + description: + 'The IP address of the upstream server. If several servers were contacted during request processing, their addresses are separated by commas. ', + name: 'nginx.ingress_controller.upstream.ip', + type: 'ip', + }, + 'nginx.ingress_controller.upstream.port': { + category: 'nginx', + description: 'The port of the upstream server. ', + name: 'nginx.ingress_controller.upstream.port', + type: 'long', + }, + 'nginx.ingress_controller.body_sent.bytes': { + category: 'nginx', + name: 'nginx.ingress_controller.body_sent.bytes', + type: 'alias', + }, + 'nginx.ingress_controller.user_name': { + category: 'nginx', + name: 'nginx.ingress_controller.user_name', + type: 'alias', + }, + 'nginx.ingress_controller.method': { + category: 'nginx', + name: 'nginx.ingress_controller.method', + type: 'alias', + }, + 'nginx.ingress_controller.url': { + category: 'nginx', + name: 'nginx.ingress_controller.url', + type: 'alias', + }, + 'nginx.ingress_controller.http_version': { + category: 'nginx', + name: 'nginx.ingress_controller.http_version', + type: 'alias', + }, + 'nginx.ingress_controller.response_code': { + category: 'nginx', + name: 'nginx.ingress_controller.response_code', + type: 'alias', + }, + 'nginx.ingress_controller.referrer': { + category: 'nginx', + name: 'nginx.ingress_controller.referrer', + type: 'alias', + }, + 'nginx.ingress_controller.agent': { + category: 'nginx', + name: 'nginx.ingress_controller.agent', + type: 'alias', + }, + 'nginx.ingress_controller.user_agent.device': { + category: 'nginx', + name: 'nginx.ingress_controller.user_agent.device', + type: 'alias', + }, + 'nginx.ingress_controller.user_agent.name': { + category: 'nginx', + name: 'nginx.ingress_controller.user_agent.name', + type: 'alias', + }, + 'nginx.ingress_controller.user_agent.os': { + category: 'nginx', + name: 'nginx.ingress_controller.user_agent.os', + type: 'alias', + }, + 'nginx.ingress_controller.user_agent.os_name': { + category: 'nginx', + name: 'nginx.ingress_controller.user_agent.os_name', + type: 'alias', + }, + 'nginx.ingress_controller.user_agent.original': { + category: 'nginx', + name: 'nginx.ingress_controller.user_agent.original', + type: 'alias', + }, + 'nginx.ingress_controller.geoip.continent_name': { + category: 'nginx', + name: 'nginx.ingress_controller.geoip.continent_name', + type: 'alias', + }, + 'nginx.ingress_controller.geoip.country_iso_code': { + category: 'nginx', + name: 'nginx.ingress_controller.geoip.country_iso_code', + type: 'alias', + }, + 'nginx.ingress_controller.geoip.location': { + category: 'nginx', + name: 'nginx.ingress_controller.geoip.location', + type: 'alias', + }, + 'nginx.ingress_controller.geoip.region_name': { + category: 'nginx', + name: 'nginx.ingress_controller.geoip.region_name', + type: 'alias', + }, + 'nginx.ingress_controller.geoip.city_name': { + category: 'nginx', + name: 'nginx.ingress_controller.geoip.city_name', + type: 'alias', + }, + 'nginx.ingress_controller.geoip.region_iso_code': { + category: 'nginx', + name: 'nginx.ingress_controller.geoip.region_iso_code', + type: 'alias', + }, + 'osquery.result.name': { + category: 'osquery', + description: 'The name of the query that generated this event. ', + name: 'osquery.result.name', + type: 'keyword', + }, + 'osquery.result.action': { + category: 'osquery', + description: + 'For incremental data, marks whether the entry was added or removed. It can be one of "added", "removed", or "snapshot". ', + name: 'osquery.result.action', + type: 'keyword', + }, + 'osquery.result.host_identifier': { + category: 'osquery', + description: + 'The identifier for the host on which the osquery agent is running. Normally the hostname. ', + name: 'osquery.result.host_identifier', + type: 'keyword', + }, + 'osquery.result.unix_time': { + category: 'osquery', + description: + 'Unix timestamp of the event, in seconds since the epoch. Used for computing the `@timestamp` column. ', + name: 'osquery.result.unix_time', + type: 'long', + }, + 'osquery.result.calendar_time': { + category: 'osquery', + description: 'String representation of the collection time, as formatted by osquery. ', + name: 'osquery.result.calendar_time', + type: 'keyword', + }, + 'postgresql.log.timestamp': { + category: 'postgresql', + description: 'The timestamp from the log line. ', + name: 'postgresql.log.timestamp', + }, + 'postgresql.log.core_id': { + category: 'postgresql', + description: 'Core id ', + name: 'postgresql.log.core_id', + type: 'long', + }, + 'postgresql.log.database': { + category: 'postgresql', + description: 'Name of database ', + example: 'mydb', + name: 'postgresql.log.database', + }, + 'postgresql.log.query': { + category: 'postgresql', + description: 'Query statement. ', + example: 'SELECT * FROM users;', + name: 'postgresql.log.query', + }, + 'postgresql.log.query_step': { + category: 'postgresql', + description: + 'Statement step when using extended query protocol (one of statement, parse, bind or execute) ', + example: 'parse', + name: 'postgresql.log.query_step', + }, + 'postgresql.log.query_name': { + category: 'postgresql', + description: + 'Name given to a query when using extended query protocol. If it is "", or not present, this field is ignored. ', + example: 'pdo_stmt_00000001', + name: 'postgresql.log.query_name', + }, + 'postgresql.log.error.code': { + category: 'postgresql', + description: 'Error code returned by Postgres (if any)', + name: 'postgresql.log.error.code', + type: 'long', + }, + 'postgresql.log.timezone': { + category: 'postgresql', + name: 'postgresql.log.timezone', + type: 'alias', + }, + 'postgresql.log.thread_id': { + category: 'postgresql', + name: 'postgresql.log.thread_id', + type: 'alias', + }, + 'postgresql.log.user': { + category: 'postgresql', + name: 'postgresql.log.user', + type: 'alias', + }, + 'postgresql.log.level': { + category: 'postgresql', + name: 'postgresql.log.level', + type: 'alias', + }, + 'postgresql.log.message': { + category: 'postgresql', + name: 'postgresql.log.message', + type: 'alias', + }, + 'redis.log.role': { + category: 'redis', + description: + 'The role of the Redis instance. Can be one of `master`, `slave`, `child` (for RDF/AOF writing child), or `sentinel`. ', + name: 'redis.log.role', + type: 'keyword', + }, + 'redis.log.pid': { + category: 'redis', + name: 'redis.log.pid', + type: 'alias', + }, + 'redis.log.level': { + category: 'redis', + name: 'redis.log.level', + type: 'alias', + }, + 'redis.log.message': { + category: 'redis', + name: 'redis.log.message', + type: 'alias', + }, + 'redis.slowlog.cmd': { + category: 'redis', + description: 'The command executed. ', + name: 'redis.slowlog.cmd', + type: 'keyword', + }, + 'redis.slowlog.duration.us': { + category: 'redis', + description: 'How long it took to execute the command in microseconds. ', + name: 'redis.slowlog.duration.us', + type: 'long', + }, + 'redis.slowlog.id': { + category: 'redis', + description: 'The ID of the query. ', + name: 'redis.slowlog.id', + type: 'long', + }, + 'redis.slowlog.key': { + category: 'redis', + description: 'The key on which the command was executed. ', + name: 'redis.slowlog.key', + type: 'keyword', + }, + 'redis.slowlog.args': { + category: 'redis', + description: 'The arguments with which the command was called. ', + name: 'redis.slowlog.args', + type: 'keyword', + }, + 'santa.action': { + category: 'santa', + description: 'Action', + example: 'EXEC', + name: 'santa.action', + type: 'keyword', + }, + 'santa.decision': { + category: 'santa', + description: 'Decision that santad took.', + example: 'ALLOW', + name: 'santa.decision', + type: 'keyword', + }, + 'santa.reason': { + category: 'santa', + description: 'Reason for the decsision.', + example: 'CERT', + name: 'santa.reason', + type: 'keyword', + }, + 'santa.mode': { + category: 'santa', + description: 'Operating mode of Santa.', + example: 'M', + name: 'santa.mode', + type: 'keyword', + }, + 'santa.disk.volume': { + category: 'santa', + description: 'The volume name.', + name: 'santa.disk.volume', + }, + 'santa.disk.bus': { + category: 'santa', + description: 'The disk bus protocol.', + name: 'santa.disk.bus', + }, + 'santa.disk.serial': { + category: 'santa', + description: 'The disk serial number.', + name: 'santa.disk.serial', + }, + 'santa.disk.bsdname': { + category: 'santa', + description: 'The disk BSD name.', + example: 'disk1s3', + name: 'santa.disk.bsdname', + }, + 'santa.disk.model': { + category: 'santa', + description: 'The disk model.', + example: 'APPLE SSD SM0512L', + name: 'santa.disk.model', + }, + 'santa.disk.fs': { + category: 'santa', + description: 'The disk volume kind (filesystem type).', + example: 'apfs', + name: 'santa.disk.fs', + }, + 'santa.disk.mount': { + category: 'santa', + description: 'The disk volume path.', + name: 'santa.disk.mount', + }, + 'santa.certificate.common_name': { + category: 'santa', + description: 'Common name from code signing certificate.', + name: 'santa.certificate.common_name', + type: 'keyword', + }, + 'santa.certificate.sha256': { + category: 'santa', + description: 'SHA256 hash of code signing certificate.', + name: 'santa.certificate.sha256', + type: 'keyword', + }, + 'system.auth.timestamp': { + category: 'system', + name: 'system.auth.timestamp', + type: 'alias', + }, + 'system.auth.hostname': { + category: 'system', + name: 'system.auth.hostname', + type: 'alias', + }, + 'system.auth.program': { + category: 'system', + name: 'system.auth.program', + type: 'alias', + }, + 'system.auth.pid': { + category: 'system', + name: 'system.auth.pid', + type: 'alias', + }, + 'system.auth.message': { + category: 'system', + name: 'system.auth.message', + type: 'alias', + }, + 'system.auth.user': { + category: 'system', + name: 'system.auth.user', + type: 'alias', + }, + 'system.auth.ssh.method': { + category: 'system', + description: 'The SSH authentication method. Can be one of "password" or "publickey". ', + name: 'system.auth.ssh.method', + }, + 'system.auth.ssh.signature': { + category: 'system', + description: 'The signature of the client public key. ', + name: 'system.auth.ssh.signature', + }, + 'system.auth.ssh.dropped_ip': { + category: 'system', + description: 'The client IP from SSH connections that are open and immediately dropped. ', + name: 'system.auth.ssh.dropped_ip', + type: 'ip', + }, + 'system.auth.ssh.event': { + category: 'system', + description: 'The SSH event as found in the logs (Accepted, Invalid, Failed, etc.) ', + example: 'Accepted', + name: 'system.auth.ssh.event', + }, + 'system.auth.ssh.ip': { + category: 'system', + name: 'system.auth.ssh.ip', + type: 'alias', + }, + 'system.auth.ssh.port': { + category: 'system', + name: 'system.auth.ssh.port', + type: 'alias', + }, + 'system.auth.ssh.geoip.continent_name': { + category: 'system', + name: 'system.auth.ssh.geoip.continent_name', + type: 'alias', + }, + 'system.auth.ssh.geoip.country_iso_code': { + category: 'system', + name: 'system.auth.ssh.geoip.country_iso_code', + type: 'alias', + }, + 'system.auth.ssh.geoip.location': { + category: 'system', + name: 'system.auth.ssh.geoip.location', + type: 'alias', + }, + 'system.auth.ssh.geoip.region_name': { + category: 'system', + name: 'system.auth.ssh.geoip.region_name', + type: 'alias', + }, + 'system.auth.ssh.geoip.city_name': { + category: 'system', + name: 'system.auth.ssh.geoip.city_name', + type: 'alias', + }, + 'system.auth.ssh.geoip.region_iso_code': { + category: 'system', + name: 'system.auth.ssh.geoip.region_iso_code', + type: 'alias', + }, + 'system.auth.sudo.error': { + category: 'system', + description: 'The error message in case the sudo command failed. ', + example: 'user NOT in sudoers', + name: 'system.auth.sudo.error', + }, + 'system.auth.sudo.tty': { + category: 'system', + description: 'The TTY where the sudo command is executed. ', + name: 'system.auth.sudo.tty', + }, + 'system.auth.sudo.pwd': { + category: 'system', + description: 'The current directory where the sudo command is executed. ', + name: 'system.auth.sudo.pwd', + }, + 'system.auth.sudo.user': { + category: 'system', + description: 'The target user to which the sudo command is switching. ', + example: 'root', + name: 'system.auth.sudo.user', + }, + 'system.auth.sudo.command': { + category: 'system', + description: 'The command executed via sudo. ', + name: 'system.auth.sudo.command', + }, + 'system.auth.useradd.home': { + category: 'system', + description: 'The home folder for the new user.', + name: 'system.auth.useradd.home', + }, + 'system.auth.useradd.shell': { + category: 'system', + description: 'The default shell for the new user.', + name: 'system.auth.useradd.shell', + }, + 'system.auth.useradd.name': { + category: 'system', + name: 'system.auth.useradd.name', + type: 'alias', + }, + 'system.auth.useradd.uid': { + category: 'system', + name: 'system.auth.useradd.uid', + type: 'alias', + }, + 'system.auth.useradd.gid': { + category: 'system', + name: 'system.auth.useradd.gid', + type: 'alias', + }, + 'system.auth.groupadd.name': { + category: 'system', + name: 'system.auth.groupadd.name', + type: 'alias', + }, + 'system.auth.groupadd.gid': { + category: 'system', + name: 'system.auth.groupadd.gid', + type: 'alias', + }, + 'system.syslog.timestamp': { + category: 'system', + name: 'system.syslog.timestamp', + type: 'alias', + }, + 'system.syslog.hostname': { + category: 'system', + name: 'system.syslog.hostname', + type: 'alias', + }, + 'system.syslog.program': { + category: 'system', + name: 'system.syslog.program', + type: 'alias', + }, + 'system.syslog.pid': { + category: 'system', + name: 'system.syslog.pid', + type: 'alias', + }, + 'system.syslog.message': { + category: 'system', + name: 'system.syslog.message', + type: 'alias', + }, + 'traefik.access.user_identifier': { + category: 'traefik', + description: 'Is the RFC 1413 identity of the client ', + name: 'traefik.access.user_identifier', + type: 'keyword', + }, + 'traefik.access.request_count': { + category: 'traefik', + description: 'The number of requests ', + name: 'traefik.access.request_count', + type: 'long', + }, + 'traefik.access.frontend_name': { + category: 'traefik', + description: 'The name of the frontend used ', + name: 'traefik.access.frontend_name', + type: 'keyword', + }, + 'traefik.access.backend_url': { + category: 'traefik', + description: 'The url of the backend where request is forwarded', + name: 'traefik.access.backend_url', + type: 'keyword', + }, + 'traefik.access.body_sent.bytes': { + category: 'traefik', + name: 'traefik.access.body_sent.bytes', + type: 'alias', + }, + 'traefik.access.remote_ip': { + category: 'traefik', + name: 'traefik.access.remote_ip', + type: 'alias', + }, + 'traefik.access.user_name': { + category: 'traefik', + name: 'traefik.access.user_name', + type: 'alias', + }, + 'traefik.access.method': { + category: 'traefik', + name: 'traefik.access.method', + type: 'alias', + }, + 'traefik.access.url': { + category: 'traefik', + name: 'traefik.access.url', + type: 'alias', + }, + 'traefik.access.http_version': { + category: 'traefik', + name: 'traefik.access.http_version', + type: 'alias', + }, + 'traefik.access.response_code': { + category: 'traefik', + name: 'traefik.access.response_code', + type: 'alias', + }, + 'traefik.access.referrer': { + category: 'traefik', + name: 'traefik.access.referrer', + type: 'alias', + }, + 'traefik.access.agent': { + category: 'traefik', + name: 'traefik.access.agent', + type: 'alias', + }, + 'traefik.access.user_agent.device': { + category: 'traefik', + name: 'traefik.access.user_agent.device', + type: 'alias', + }, + 'traefik.access.user_agent.name': { + category: 'traefik', + name: 'traefik.access.user_agent.name', + type: 'alias', + }, + 'traefik.access.user_agent.os': { + category: 'traefik', + name: 'traefik.access.user_agent.os', + type: 'alias', + }, + 'traefik.access.user_agent.os_name': { + category: 'traefik', + name: 'traefik.access.user_agent.os_name', + type: 'alias', + }, + 'traefik.access.user_agent.original': { + category: 'traefik', + name: 'traefik.access.user_agent.original', + type: 'alias', + }, + 'traefik.access.geoip.continent_name': { + category: 'traefik', + name: 'traefik.access.geoip.continent_name', + type: 'alias', + }, + 'traefik.access.geoip.country_iso_code': { + category: 'traefik', + name: 'traefik.access.geoip.country_iso_code', + type: 'alias', + }, + 'traefik.access.geoip.location': { + category: 'traefik', + name: 'traefik.access.geoip.location', + type: 'alias', + }, + 'traefik.access.geoip.region_name': { + category: 'traefik', + name: 'traefik.access.geoip.region_name', + type: 'alias', + }, + 'traefik.access.geoip.city_name': { + category: 'traefik', + name: 'traefik.access.geoip.city_name', + type: 'alias', + }, + 'traefik.access.geoip.region_iso_code': { + category: 'traefik', + name: 'traefik.access.geoip.region_iso_code', + type: 'alias', + }, + 'activemq.caller': { + category: 'activemq', + description: 'Name of the caller issuing the logging request (class or resource). ', + name: 'activemq.caller', + type: 'keyword', + }, + 'activemq.thread': { + category: 'activemq', + description: 'Thread that generated the logging event. ', + name: 'activemq.thread', + type: 'keyword', + }, + 'activemq.user': { + category: 'activemq', + description: 'User that generated the logging event. ', + name: 'activemq.user', + type: 'keyword', + }, + 'activemq.audit': { + category: 'activemq', + description: 'Fields from ActiveMQ audit logs. ', + name: 'activemq.audit', + type: 'group', + }, + 'activemq.log.stack_trace': { + category: 'activemq', + name: 'activemq.log.stack_trace', + type: 'keyword', + }, + 'aws.cloudtrail.event_version': { + category: 'aws', + description: 'The CloudTrail version of the log event format. ', + name: 'aws.cloudtrail.event_version', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.type': { + category: 'aws', + description: 'The type of the identity ', + name: 'aws.cloudtrail.user_identity.type', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.arn': { + category: 'aws', + description: 'The Amazon Resource Name (ARN) of the principal that made the call.', + name: 'aws.cloudtrail.user_identity.arn', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.access_key_id': { + category: 'aws', + description: 'The access key ID that was used to sign the request.', + name: 'aws.cloudtrail.user_identity.access_key_id', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.session_context.mfa_authenticated': { + category: 'aws', + description: + 'The value is true if the root user or IAM user whose credentials were used for the request also was authenticated with an MFA device; otherwise, false.', + name: 'aws.cloudtrail.user_identity.session_context.mfa_authenticated', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.session_context.creation_date': { + category: 'aws', + description: 'The date and time when the temporary security credentials were issued.', + name: 'aws.cloudtrail.user_identity.session_context.creation_date', + type: 'date', + }, + 'aws.cloudtrail.user_identity.session_context.session_issuer.type': { + category: 'aws', + description: + 'The source of the temporary security credentials, such as Root, IAMUser, or Role.', + name: 'aws.cloudtrail.user_identity.session_context.session_issuer.type', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.session_context.session_issuer.principal_id': { + category: 'aws', + description: 'The internal ID of the entity that was used to get credentials.', + name: 'aws.cloudtrail.user_identity.session_context.session_issuer.principal_id', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.session_context.session_issuer.arn': { + category: 'aws', + description: + 'The ARN of the source (account, IAM user, or role) that was used to get temporary security credentials.', + name: 'aws.cloudtrail.user_identity.session_context.session_issuer.arn', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.session_context.session_issuer.account_id': { + category: 'aws', + description: 'The account that owns the entity that was used to get credentials.', + name: 'aws.cloudtrail.user_identity.session_context.session_issuer.account_id', + type: 'keyword', + }, + 'aws.cloudtrail.user_identity.invoked_by': { + category: 'aws', + description: + 'The name of the AWS service that made the request, such as Amazon EC2 Auto Scaling or AWS Elastic Beanstalk.', + name: 'aws.cloudtrail.user_identity.invoked_by', + type: 'keyword', + }, + 'aws.cloudtrail.error_code': { + category: 'aws', + description: 'The AWS service error if the request returns an error.', + name: 'aws.cloudtrail.error_code', + type: 'keyword', + }, + 'aws.cloudtrail.error_message': { + category: 'aws', + description: 'If the request returns an error, the description of the error.', + name: 'aws.cloudtrail.error_message', + type: 'keyword', + }, + 'aws.cloudtrail.request_parameters': { + category: 'aws', + description: 'The parameters, if any, that were sent with the request.', + name: 'aws.cloudtrail.request_parameters', + type: 'keyword', + }, + 'aws.cloudtrail.response_elements': { + category: 'aws', + description: + 'The response element for actions that make changes (create, update, or delete actions).', + name: 'aws.cloudtrail.response_elements', + type: 'keyword', + }, + 'aws.cloudtrail.additional_eventdata': { + category: 'aws', + description: 'Additional data about the event that was not part of the request or response.', + name: 'aws.cloudtrail.additional_eventdata', + type: 'keyword', + }, + 'aws.cloudtrail.request_id': { + category: 'aws', + description: + 'The value that identifies the request. The service being called generates this value.', + name: 'aws.cloudtrail.request_id', + type: 'keyword', + }, + 'aws.cloudtrail.event_type': { + category: 'aws', + description: 'Identifies the type of event that generated the event record.', + name: 'aws.cloudtrail.event_type', + type: 'keyword', + }, + 'aws.cloudtrail.api_version': { + category: 'aws', + description: 'Identifies the API version associated with the AwsApiCall eventType value.', + name: 'aws.cloudtrail.api_version', + type: 'keyword', + }, + 'aws.cloudtrail.management_event': { + category: 'aws', + description: 'A Boolean value that identifies whether the event is a management event.', + name: 'aws.cloudtrail.management_event', + type: 'keyword', + }, + 'aws.cloudtrail.read_only': { + category: 'aws', + description: 'Identifies whether this operation is a read-only operation.', + name: 'aws.cloudtrail.read_only', + type: 'keyword', + }, + 'aws.cloudtrail.resources.arn': { + category: 'aws', + description: 'Resource ARNs', + name: 'aws.cloudtrail.resources.arn', + type: 'keyword', + }, + 'aws.cloudtrail.resources.account_id': { + category: 'aws', + description: 'Account ID of the resource owner', + name: 'aws.cloudtrail.resources.account_id', + type: 'keyword', + }, + 'aws.cloudtrail.resources.type': { + category: 'aws', + description: 'Resource type identifier in the format: AWS::aws-service-name::data-type-name', + name: 'aws.cloudtrail.resources.type', + type: 'keyword', + }, + 'aws.cloudtrail.recipient_account_id': { + category: 'aws', + description: 'Represents the account ID that received this event.', + name: 'aws.cloudtrail.recipient_account_id', + type: 'keyword', + }, + 'aws.cloudtrail.service_event_details': { + category: 'aws', + description: 'Identifies the service event, including what triggered the event and the result.', + name: 'aws.cloudtrail.service_event_details', + type: 'keyword', + }, + 'aws.cloudtrail.shared_event_id': { + category: 'aws', + description: + 'GUID generated by CloudTrail to uniquely identify CloudTrail events from the same AWS action that is sent to different AWS accounts.', + name: 'aws.cloudtrail.shared_event_id', + type: 'keyword', + }, + 'aws.cloudtrail.vpc_endpoint_id': { + category: 'aws', + description: + 'Identifies the VPC endpoint in which requests were made from a VPC to another AWS service, such as Amazon S3.', + name: 'aws.cloudtrail.vpc_endpoint_id', + type: 'keyword', + }, + 'aws.cloudtrail.console_login.additional_eventdata.mobile_version': { + category: 'aws', + description: 'Identifies whether ConsoleLogin was from mobile version', + name: 'aws.cloudtrail.console_login.additional_eventdata.mobile_version', + type: 'boolean', + }, + 'aws.cloudtrail.console_login.additional_eventdata.login_to': { + category: 'aws', + description: 'URL for ConsoleLogin', + name: 'aws.cloudtrail.console_login.additional_eventdata.login_to', + type: 'keyword', + }, + 'aws.cloudtrail.console_login.additional_eventdata.mfa_used': { + category: 'aws', + description: 'Identifies whether multi factor authentication was used during ConsoleLogin', + name: 'aws.cloudtrail.console_login.additional_eventdata.mfa_used', + type: 'boolean', + }, + 'aws.cloudtrail.flattened.additional_eventdata': { + category: 'aws', + description: 'Additional data about the event that was not part of the request or response. ', + name: 'aws.cloudtrail.flattened.additional_eventdata', + type: 'flattened', + }, + 'aws.cloudtrail.flattened.request_parameters': { + category: 'aws', + description: 'The parameters, if any, that were sent with the request.', + name: 'aws.cloudtrail.flattened.request_parameters', + type: 'flattened', + }, + 'aws.cloudtrail.flattened.response_elements': { + category: 'aws', + description: + 'The response element for actions that make changes (create, update, or delete actions).', + name: 'aws.cloudtrail.flattened.response_elements', + type: 'flattened', + }, + 'aws.cloudtrail.flattened.service_event_details': { + category: 'aws', + description: 'Identifies the service event, including what triggered the event and the result.', + name: 'aws.cloudtrail.flattened.service_event_details', + type: 'flattened', + }, + 'aws.cloudwatch.message': { + category: 'aws', + description: 'CloudWatch log message. ', + name: 'aws.cloudwatch.message', + type: 'text', + }, + 'aws.ec2.ip_address': { + category: 'aws', + description: 'The internet address of the requester. ', + name: 'aws.ec2.ip_address', + type: 'keyword', + }, + 'aws.elb.name': { + category: 'aws', + description: 'The name of the load balancer. ', + name: 'aws.elb.name', + type: 'keyword', + }, + 'aws.elb.type': { + category: 'aws', + description: 'The type of the load balancer for v2 Load Balancers. ', + name: 'aws.elb.type', + type: 'keyword', + }, + 'aws.elb.target_group.arn': { + category: 'aws', + description: 'The ARN of the target group handling the request. ', + name: 'aws.elb.target_group.arn', + type: 'keyword', + }, + 'aws.elb.listener': { + category: 'aws', + description: 'The ELB listener that received the connection. ', + name: 'aws.elb.listener', + type: 'keyword', + }, + 'aws.elb.protocol': { + category: 'aws', + description: 'The protocol of the load balancer (http or tcp). ', + name: 'aws.elb.protocol', + type: 'keyword', + }, + 'aws.elb.request_processing_time.sec': { + category: 'aws', + description: + 'The total time in seconds since the connection or request is received until it is sent to a registered backend. ', + name: 'aws.elb.request_processing_time.sec', + type: 'float', + }, + 'aws.elb.backend_processing_time.sec': { + category: 'aws', + description: + 'The total time in seconds since the connection is sent to the backend till the backend starts responding. ', + name: 'aws.elb.backend_processing_time.sec', + type: 'float', + }, + 'aws.elb.response_processing_time.sec': { + category: 'aws', + description: + 'The total time in seconds since the response is received from the backend till it is sent to the client. ', + name: 'aws.elb.response_processing_time.sec', + type: 'float', + }, + 'aws.elb.connection_time.ms': { + category: 'aws', + description: + 'The total time of the connection in milliseconds, since it is opened till it is closed. ', + name: 'aws.elb.connection_time.ms', + type: 'long', + }, + 'aws.elb.tls_handshake_time.ms': { + category: 'aws', + description: + 'The total time for the TLS handshake to complete in milliseconds once the connection has been established. ', + name: 'aws.elb.tls_handshake_time.ms', + type: 'long', + }, + 'aws.elb.backend.ip': { + category: 'aws', + description: 'The IP address of the backend processing this connection. ', + name: 'aws.elb.backend.ip', + type: 'keyword', + }, + 'aws.elb.backend.port': { + category: 'aws', + description: 'The port in the backend processing this connection. ', + name: 'aws.elb.backend.port', + type: 'keyword', + }, + 'aws.elb.backend.http.response.status_code': { + category: 'aws', + description: + 'The status code from the backend (status code sent to the client from ELB is stored in `http.response.status_code` ', + name: 'aws.elb.backend.http.response.status_code', + type: 'keyword', + }, + 'aws.elb.ssl_cipher': { + category: 'aws', + description: 'The SSL cipher used in TLS/SSL connections. ', + name: 'aws.elb.ssl_cipher', + type: 'keyword', + }, + 'aws.elb.ssl_protocol': { + category: 'aws', + description: 'The SSL protocol used in TLS/SSL connections. ', + name: 'aws.elb.ssl_protocol', + type: 'keyword', + }, + 'aws.elb.chosen_cert.arn': { + category: 'aws', + description: + 'The ARN of the chosen certificate presented to the client in TLS/SSL connections. ', + name: 'aws.elb.chosen_cert.arn', + type: 'keyword', + }, + 'aws.elb.chosen_cert.serial': { + category: 'aws', + description: + 'The serial number of the chosen certificate presented to the client in TLS/SSL connections. ', + name: 'aws.elb.chosen_cert.serial', + type: 'keyword', + }, + 'aws.elb.incoming_tls_alert': { + category: 'aws', + description: + 'The integer value of TLS alerts received by the load balancer from the client, if present. ', + name: 'aws.elb.incoming_tls_alert', + type: 'keyword', + }, + 'aws.elb.tls_named_group': { + category: 'aws', + description: 'The TLS named group. ', + name: 'aws.elb.tls_named_group', + type: 'keyword', + }, + 'aws.elb.trace_id': { + category: 'aws', + description: 'The contents of the `X-Amzn-Trace-Id` header. ', + name: 'aws.elb.trace_id', + type: 'keyword', + }, + 'aws.elb.matched_rule_priority': { + category: 'aws', + description: 'The priority value of the rule that matched the request, if a rule matched. ', + name: 'aws.elb.matched_rule_priority', + type: 'keyword', + }, + 'aws.elb.action_executed': { + category: 'aws', + description: + 'The action executed when processing the request (forward, fixed-response, authenticate...). It can contain several values. ', + name: 'aws.elb.action_executed', + type: 'keyword', + }, + 'aws.elb.redirect_url': { + category: 'aws', + description: 'The URL used if a redirection action was executed. ', + name: 'aws.elb.redirect_url', + type: 'keyword', + }, + 'aws.elb.error.reason': { + category: 'aws', + description: 'The error reason if the executed action failed. ', + name: 'aws.elb.error.reason', + type: 'keyword', + }, + 'aws.s3access.bucket_owner': { + category: 'aws', + description: 'The canonical user ID of the owner of the source bucket. ', + name: 'aws.s3access.bucket_owner', + type: 'keyword', + }, + 'aws.s3access.bucket': { + category: 'aws', + description: 'The name of the bucket that the request was processed against. ', + name: 'aws.s3access.bucket', + type: 'keyword', + }, + 'aws.s3access.remote_ip': { + category: 'aws', + description: 'The apparent internet address of the requester. ', + name: 'aws.s3access.remote_ip', + type: 'ip', + }, + 'aws.s3access.requester': { + category: 'aws', + description: 'The canonical user ID of the requester, or a - for unauthenticated requests. ', + name: 'aws.s3access.requester', + type: 'keyword', + }, + 'aws.s3access.request_id': { + category: 'aws', + description: 'A string generated by Amazon S3 to uniquely identify each request. ', + name: 'aws.s3access.request_id', + type: 'keyword', + }, + 'aws.s3access.operation': { + category: 'aws', + description: + 'The operation listed here is declared as SOAP.operation, REST.HTTP_method.resource_type, WEBSITE.HTTP_method.resource_type, or BATCH.DELETE.OBJECT. ', + name: 'aws.s3access.operation', + type: 'keyword', + }, + 'aws.s3access.key': { + category: 'aws', + description: + 'The "key" part of the request, URL encoded, or "-" if the operation does not take a key parameter. ', + name: 'aws.s3access.key', + type: 'keyword', + }, + 'aws.s3access.request_uri': { + category: 'aws', + description: 'The Request-URI part of the HTTP request message. ', + name: 'aws.s3access.request_uri', + type: 'keyword', + }, + 'aws.s3access.http_status': { + category: 'aws', + description: 'The numeric HTTP status code of the response. ', + name: 'aws.s3access.http_status', + type: 'long', + }, + 'aws.s3access.error_code': { + category: 'aws', + description: 'The Amazon S3 Error Code, or "-" if no error occurred. ', + name: 'aws.s3access.error_code', + type: 'keyword', + }, + 'aws.s3access.bytes_sent': { + category: 'aws', + description: + 'The number of response bytes sent, excluding HTTP protocol overhead, or "-" if zero. ', + name: 'aws.s3access.bytes_sent', + type: 'long', + }, + 'aws.s3access.object_size': { + category: 'aws', + description: 'The total size of the object in question. ', + name: 'aws.s3access.object_size', + type: 'long', + }, + 'aws.s3access.total_time': { + category: 'aws', + description: + "The number of milliseconds the request was in flight from the server's perspective. ", + name: 'aws.s3access.total_time', + type: 'long', + }, + 'aws.s3access.turn_around_time': { + category: 'aws', + description: 'The number of milliseconds that Amazon S3 spent processing your request. ', + name: 'aws.s3access.turn_around_time', + type: 'long', + }, + 'aws.s3access.referrer': { + category: 'aws', + description: 'The value of the HTTP Referrer header, if present. ', + name: 'aws.s3access.referrer', + type: 'keyword', + }, + 'aws.s3access.user_agent': { + category: 'aws', + description: 'The value of the HTTP User-Agent header. ', + name: 'aws.s3access.user_agent', + type: 'keyword', + }, + 'aws.s3access.version_id': { + category: 'aws', + description: + 'The version ID in the request, or "-" if the operation does not take a versionId parameter. ', + name: 'aws.s3access.version_id', + type: 'keyword', + }, + 'aws.s3access.host_id': { + category: 'aws', + description: 'The x-amz-id-2 or Amazon S3 extended request ID. ', + name: 'aws.s3access.host_id', + type: 'keyword', + }, + 'aws.s3access.signature_version': { + category: 'aws', + description: + 'The signature version, SigV2 or SigV4, that was used to authenticate the request or a - for unauthenticated requests. ', + name: 'aws.s3access.signature_version', + type: 'keyword', + }, + 'aws.s3access.cipher_suite': { + category: 'aws', + description: + 'The Secure Sockets Layer (SSL) cipher that was negotiated for HTTPS request or a - for HTTP. ', + name: 'aws.s3access.cipher_suite', + type: 'keyword', + }, + 'aws.s3access.authentication_type': { + category: 'aws', + description: + 'The type of request authentication used, AuthHeader for authentication headers, QueryString for query string (pre-signed URL) or a - for unauthenticated requests. ', + name: 'aws.s3access.authentication_type', + type: 'keyword', + }, + 'aws.s3access.host_header': { + category: 'aws', + description: 'The endpoint used to connect to Amazon S3. ', + name: 'aws.s3access.host_header', + type: 'keyword', + }, + 'aws.s3access.tls_version': { + category: 'aws', + description: 'The Transport Layer Security (TLS) version negotiated by the client. ', + name: 'aws.s3access.tls_version', + type: 'keyword', + }, + 'aws.vpcflow.version': { + category: 'aws', + description: + 'The VPC Flow Logs version. If you use the default format, the version is 2. If you specify a custom format, the version is 3. ', + name: 'aws.vpcflow.version', + type: 'keyword', + }, + 'aws.vpcflow.account_id': { + category: 'aws', + description: 'The AWS account ID for the flow log. ', + name: 'aws.vpcflow.account_id', + type: 'keyword', + }, + 'aws.vpcflow.interface_id': { + category: 'aws', + description: 'The ID of the network interface for which the traffic is recorded. ', + name: 'aws.vpcflow.interface_id', + type: 'keyword', + }, + 'aws.vpcflow.action': { + category: 'aws', + description: 'The action that is associated with the traffic, ACCEPT or REJECT. ', + name: 'aws.vpcflow.action', + type: 'keyword', + }, + 'aws.vpcflow.log_status': { + category: 'aws', + description: 'The logging status of the flow log, OK, NODATA or SKIPDATA. ', + name: 'aws.vpcflow.log_status', + type: 'keyword', + }, + 'aws.vpcflow.instance_id': { + category: 'aws', + description: + "The ID of the instance that's associated with network interface for which the traffic is recorded, if the instance is owned by you. ", + name: 'aws.vpcflow.instance_id', + type: 'keyword', + }, + 'aws.vpcflow.pkt_srcaddr': { + category: 'aws', + description: 'The packet-level (original) source IP address of the traffic. ', + name: 'aws.vpcflow.pkt_srcaddr', + type: 'ip', + }, + 'aws.vpcflow.pkt_dstaddr': { + category: 'aws', + description: 'The packet-level (original) destination IP address for the traffic. ', + name: 'aws.vpcflow.pkt_dstaddr', + type: 'ip', + }, + 'aws.vpcflow.vpc_id': { + category: 'aws', + description: + 'The ID of the VPC that contains the network interface for which the traffic is recorded. ', + name: 'aws.vpcflow.vpc_id', + type: 'keyword', + }, + 'aws.vpcflow.subnet_id': { + category: 'aws', + description: + 'The ID of the subnet that contains the network interface for which the traffic is recorded. ', + name: 'aws.vpcflow.subnet_id', + type: 'keyword', + }, + 'aws.vpcflow.tcp_flags': { + category: 'aws', + description: 'The bitmask value for the following TCP flags: 2=SYN,18=SYN-ACK,1=FIN,4=RST ', + name: 'aws.vpcflow.tcp_flags', + type: 'keyword', + }, + 'aws.vpcflow.type': { + category: 'aws', + description: 'The type of traffic: IPv4, IPv6, or EFA. ', + name: 'aws.vpcflow.type', + type: 'keyword', + }, + 'azure.subscription_id': { + category: 'azure', + description: 'Azure subscription ID ', + name: 'azure.subscription_id', + type: 'keyword', + }, + 'azure.correlation_id': { + category: 'azure', + description: 'Correlation ID ', + name: 'azure.correlation_id', + type: 'keyword', + }, + 'azure.tenant_id': { + category: 'azure', + description: 'tenant ID ', + name: 'azure.tenant_id', + type: 'keyword', + }, + 'azure.resource.id': { + category: 'azure', + description: 'Resource ID ', + name: 'azure.resource.id', + type: 'keyword', + }, + 'azure.resource.group': { + category: 'azure', + description: 'Resource group ', + name: 'azure.resource.group', + type: 'keyword', + }, + 'azure.resource.provider': { + category: 'azure', + description: 'Resource type/namespace ', + name: 'azure.resource.provider', + type: 'keyword', + }, + 'azure.resource.namespace': { + category: 'azure', + description: 'Resource type/namespace ', + name: 'azure.resource.namespace', + type: 'keyword', + }, + 'azure.resource.name': { + category: 'azure', + description: 'Name ', + name: 'azure.resource.name', + type: 'keyword', + }, + 'azure.resource.authorization_rule': { + category: 'azure', + description: 'Authorization rule ', + name: 'azure.resource.authorization_rule', + type: 'keyword', + }, + 'azure.activitylogs.identity.claims_initiated_by_user.name': { + category: 'azure', + description: 'Name ', + name: 'azure.activitylogs.identity.claims_initiated_by_user.name', + type: 'keyword', + }, + 'azure.activitylogs.identity.claims_initiated_by_user.givenname': { + category: 'azure', + description: 'Givenname ', + name: 'azure.activitylogs.identity.claims_initiated_by_user.givenname', + type: 'keyword', + }, + 'azure.activitylogs.identity.claims_initiated_by_user.surname': { + category: 'azure', + description: 'Surname ', + name: 'azure.activitylogs.identity.claims_initiated_by_user.surname', + type: 'keyword', + }, + 'azure.activitylogs.identity.claims_initiated_by_user.fullname': { + category: 'azure', + description: 'Fullname ', + name: 'azure.activitylogs.identity.claims_initiated_by_user.fullname', + type: 'keyword', + }, + 'azure.activitylogs.identity.claims_initiated_by_user.schema': { + category: 'azure', + description: 'Schema ', + name: 'azure.activitylogs.identity.claims_initiated_by_user.schema', + type: 'keyword', + }, + 'azure.activitylogs.identity.claims.*': { + category: 'azure', + description: 'Claims ', + name: 'azure.activitylogs.identity.claims.*', + type: 'object', + }, + 'azure.activitylogs.identity.authorization.scope': { + category: 'azure', + description: 'Scope ', + name: 'azure.activitylogs.identity.authorization.scope', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.action': { + category: 'azure', + description: 'Action ', + name: 'azure.activitylogs.identity.authorization.action', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.evidence.role_assignment_scope': { + category: 'azure', + description: 'Role assignment scope ', + name: 'azure.activitylogs.identity.authorization.evidence.role_assignment_scope', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.evidence.role_definition_id': { + category: 'azure', + description: 'Role definition ID ', + name: 'azure.activitylogs.identity.authorization.evidence.role_definition_id', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.evidence.role': { + category: 'azure', + description: 'Role ', + name: 'azure.activitylogs.identity.authorization.evidence.role', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.evidence.role_assignment_id': { + category: 'azure', + description: 'Role assignment ID ', + name: 'azure.activitylogs.identity.authorization.evidence.role_assignment_id', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.evidence.principal_id': { + category: 'azure', + description: 'Principal ID ', + name: 'azure.activitylogs.identity.authorization.evidence.principal_id', + type: 'keyword', + }, + 'azure.activitylogs.identity.authorization.evidence.principal_type': { + category: 'azure', + description: 'Principal type ', + name: 'azure.activitylogs.identity.authorization.evidence.principal_type', + type: 'keyword', + }, + 'azure.activitylogs.operation_name': { + category: 'azure', + description: 'Operation name ', + name: 'azure.activitylogs.operation_name', + type: 'keyword', + }, + 'azure.activitylogs.result_type': { + category: 'azure', + description: 'Result type ', + name: 'azure.activitylogs.result_type', + type: 'keyword', + }, + 'azure.activitylogs.result_signature': { + category: 'azure', + description: 'Result signature ', + name: 'azure.activitylogs.result_signature', + type: 'keyword', + }, + 'azure.activitylogs.category': { + category: 'azure', + description: 'Category ', + name: 'azure.activitylogs.category', + type: 'keyword', + }, + 'azure.activitylogs.event_category': { + category: 'azure', + description: 'Event Category ', + name: 'azure.activitylogs.event_category', + type: 'keyword', + }, + 'azure.activitylogs.properties.service_request_id': { + category: 'azure', + description: 'Service Request Id ', + name: 'azure.activitylogs.properties.service_request_id', + type: 'keyword', + }, + 'azure.activitylogs.properties.status_code': { + category: 'azure', + description: 'Status code ', + name: 'azure.activitylogs.properties.status_code', + type: 'keyword', + }, + 'azure.auditlogs.category': { + category: 'azure', + description: 'The category of the operation. Currently, Audit is the only supported value. ', + name: 'azure.auditlogs.category', + type: 'keyword', + }, + 'azure.auditlogs.operation_name': { + category: 'azure', + description: 'The operation name ', + name: 'azure.auditlogs.operation_name', + type: 'keyword', + }, + 'azure.auditlogs.operation_version': { + category: 'azure', + description: 'The operation version ', + name: 'azure.auditlogs.operation_version', + type: 'keyword', + }, + 'azure.auditlogs.identity': { + category: 'azure', + description: 'Identity ', + name: 'azure.auditlogs.identity', + type: 'keyword', + }, + 'azure.auditlogs.tenant_id': { + category: 'azure', + description: 'Tenant ID ', + name: 'azure.auditlogs.tenant_id', + type: 'keyword', + }, + 'azure.auditlogs.result_signature': { + category: 'azure', + description: 'Result signature ', + name: 'azure.auditlogs.result_signature', + type: 'keyword', + }, + 'azure.auditlogs.properties.result': { + category: 'azure', + description: 'Log result ', + name: 'azure.auditlogs.properties.result', + type: 'keyword', + }, + 'azure.auditlogs.properties.activity_display_name': { + category: 'azure', + description: 'Activity display name ', + name: 'azure.auditlogs.properties.activity_display_name', + type: 'keyword', + }, + 'azure.auditlogs.properties.result_reason': { + category: 'azure', + description: 'Reason for the log result ', + name: 'azure.auditlogs.properties.result_reason', + type: 'keyword', + }, + 'azure.auditlogs.properties.correlation_id': { + category: 'azure', + description: 'Correlation ID ', + name: 'azure.auditlogs.properties.correlation_id', + type: 'keyword', + }, + 'azure.auditlogs.properties.logged_by_service': { + category: 'azure', + description: 'Logged by service ', + name: 'azure.auditlogs.properties.logged_by_service', + type: 'keyword', + }, + 'azure.auditlogs.properties.operation_type': { + category: 'azure', + description: 'Operation type ', + name: 'azure.auditlogs.properties.operation_type', + type: 'keyword', + }, + 'azure.auditlogs.properties.id': { + category: 'azure', + description: 'ID ', + name: 'azure.auditlogs.properties.id', + type: 'keyword', + }, + 'azure.auditlogs.properties.activity_datetime': { + category: 'azure', + description: 'Activity timestamp ', + name: 'azure.auditlogs.properties.activity_datetime', + type: 'date', + }, + 'azure.auditlogs.properties.category': { + category: 'azure', + description: 'category ', + name: 'azure.auditlogs.properties.category', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.display_name': { + category: 'azure', + description: 'Display name ', + name: 'azure.auditlogs.properties.target_resources.*.display_name', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.id': { + category: 'azure', + description: 'ID ', + name: 'azure.auditlogs.properties.target_resources.*.id', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.type': { + category: 'azure', + description: 'Type ', + name: 'azure.auditlogs.properties.target_resources.*.type', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.ip_address': { + category: 'azure', + description: 'ip Address ', + name: 'azure.auditlogs.properties.target_resources.*.ip_address', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.user_principal_name': { + category: 'azure', + description: 'User principal name ', + name: 'azure.auditlogs.properties.target_resources.*.user_principal_name', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.modified_properties.*.new_value': { + category: 'azure', + description: 'New value ', + name: 'azure.auditlogs.properties.target_resources.*.modified_properties.*.new_value', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.modified_properties.*.display_name': { + category: 'azure', + description: 'Display value ', + name: 'azure.auditlogs.properties.target_resources.*.modified_properties.*.display_name', + type: 'keyword', + }, + 'azure.auditlogs.properties.target_resources.*.modified_properties.*.old_value': { + category: 'azure', + description: 'Old value ', + name: 'azure.auditlogs.properties.target_resources.*.modified_properties.*.old_value', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.app.servicePrincipalName': { + category: 'azure', + description: 'Service principal name ', + name: 'azure.auditlogs.properties.initiated_by.app.servicePrincipalName', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.app.displayName': { + category: 'azure', + description: 'Display name ', + name: 'azure.auditlogs.properties.initiated_by.app.displayName', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.app.appId': { + category: 'azure', + description: 'App ID ', + name: 'azure.auditlogs.properties.initiated_by.app.appId', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.app.servicePrincipalId': { + category: 'azure', + description: 'Service principal ID ', + name: 'azure.auditlogs.properties.initiated_by.app.servicePrincipalId', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.user.userPrincipalName': { + category: 'azure', + description: 'User principal name ', + name: 'azure.auditlogs.properties.initiated_by.user.userPrincipalName', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.user.displayName': { + category: 'azure', + description: 'Display name ', + name: 'azure.auditlogs.properties.initiated_by.user.displayName', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.user.id': { + category: 'azure', + description: 'ID ', + name: 'azure.auditlogs.properties.initiated_by.user.id', + type: 'keyword', + }, + 'azure.auditlogs.properties.initiated_by.user.ipAddress': { + category: 'azure', + description: 'ip Address ', + name: 'azure.auditlogs.properties.initiated_by.user.ipAddress', + type: 'keyword', + }, + 'azure.signinlogs.operation_name': { + category: 'azure', + description: 'The operation name ', + name: 'azure.signinlogs.operation_name', + type: 'keyword', + }, + 'azure.signinlogs.operation_version': { + category: 'azure', + description: 'The operation version ', + name: 'azure.signinlogs.operation_version', + type: 'keyword', + }, + 'azure.signinlogs.tenant_id': { + category: 'azure', + description: 'Tenant ID ', + name: 'azure.signinlogs.tenant_id', + type: 'keyword', + }, + 'azure.signinlogs.result_signature': { + category: 'azure', + description: 'Result signature ', + name: 'azure.signinlogs.result_signature', + type: 'keyword', + }, + 'azure.signinlogs.result_description': { + category: 'azure', + description: 'Result description ', + name: 'azure.signinlogs.result_description', + type: 'keyword', + }, + 'azure.signinlogs.result_type': { + category: 'azure', + description: 'Result type ', + name: 'azure.signinlogs.result_type', + type: 'keyword', + }, + 'azure.signinlogs.identity': { + category: 'azure', + description: 'Identity ', + name: 'azure.signinlogs.identity', + type: 'keyword', + }, + 'azure.signinlogs.category': { + category: 'azure', + description: 'Category ', + name: 'azure.signinlogs.category', + type: 'keyword', + }, + 'azure.signinlogs.properties.id': { + category: 'azure', + description: 'ID ', + name: 'azure.signinlogs.properties.id', + type: 'keyword', + }, + 'azure.signinlogs.properties.created_at': { + category: 'azure', + description: 'Created date time ', + name: 'azure.signinlogs.properties.created_at', + type: 'date', + }, + 'azure.signinlogs.properties.user_display_name': { + category: 'azure', + description: 'User display name ', + name: 'azure.signinlogs.properties.user_display_name', + type: 'keyword', + }, + 'azure.signinlogs.properties.correlation_id': { + category: 'azure', + description: 'Correlation ID ', + name: 'azure.signinlogs.properties.correlation_id', + type: 'keyword', + }, + 'azure.signinlogs.properties.user_principal_name': { + category: 'azure', + description: 'User principal name ', + name: 'azure.signinlogs.properties.user_principal_name', + type: 'keyword', + }, + 'azure.signinlogs.properties.user_id': { + category: 'azure', + description: 'User ID ', + name: 'azure.signinlogs.properties.user_id', + type: 'keyword', + }, + 'azure.signinlogs.properties.app_id': { + category: 'azure', + description: 'App ID ', + name: 'azure.signinlogs.properties.app_id', + type: 'keyword', + }, + 'azure.signinlogs.properties.app_display_name': { + category: 'azure', + description: 'App display name ', + name: 'azure.signinlogs.properties.app_display_name', + type: 'keyword', + }, + 'azure.signinlogs.properties.ip_address': { + category: 'azure', + description: 'Ip address ', + name: 'azure.signinlogs.properties.ip_address', + type: 'keyword', + }, + 'azure.signinlogs.properties.client_app_used': { + category: 'azure', + description: 'Client app used ', + name: 'azure.signinlogs.properties.client_app_used', + type: 'keyword', + }, + 'azure.signinlogs.properties.conditional_access_status': { + category: 'azure', + description: 'Conditional access status ', + name: 'azure.signinlogs.properties.conditional_access_status', + type: 'keyword', + }, + 'azure.signinlogs.properties.original_request_id': { + category: 'azure', + description: 'Original request ID ', + name: 'azure.signinlogs.properties.original_request_id', + type: 'keyword', + }, + 'azure.signinlogs.properties.is_interactive': { + category: 'azure', + description: 'Is interactive ', + name: 'azure.signinlogs.properties.is_interactive', + type: 'keyword', + }, + 'azure.signinlogs.properties.token_issuer_name': { + category: 'azure', + description: 'Token issuer name ', + name: 'azure.signinlogs.properties.token_issuer_name', + type: 'keyword', + }, + 'azure.signinlogs.properties.token_issuer_type': { + category: 'azure', + description: 'Token issuer type ', + name: 'azure.signinlogs.properties.token_issuer_type', + type: 'keyword', + }, + 'azure.signinlogs.properties.processing_time_ms': { + category: 'azure', + description: 'Processing time in milliseconds ', + name: 'azure.signinlogs.properties.processing_time_ms', + type: 'float', + }, + 'azure.signinlogs.properties.risk_detail': { + category: 'azure', + description: 'Risk detail ', + name: 'azure.signinlogs.properties.risk_detail', + type: 'keyword', + }, + 'azure.signinlogs.properties.risk_level_aggregated': { + category: 'azure', + description: 'Risk level aggregated ', + name: 'azure.signinlogs.properties.risk_level_aggregated', + type: 'keyword', + }, + 'azure.signinlogs.properties.risk_level_during_signin': { + category: 'azure', + description: 'Risk level during signIn ', + name: 'azure.signinlogs.properties.risk_level_during_signin', + type: 'keyword', + }, + 'azure.signinlogs.properties.risk_state': { + category: 'azure', + description: 'Risk state ', + name: 'azure.signinlogs.properties.risk_state', + type: 'keyword', + }, + 'azure.signinlogs.properties.resource_display_name': { + category: 'azure', + description: 'Resource display name ', + name: 'azure.signinlogs.properties.resource_display_name', + type: 'keyword', + }, + 'azure.signinlogs.properties.status.error_code': { + category: 'azure', + description: 'Error code ', + name: 'azure.signinlogs.properties.status.error_code', + type: 'keyword', + }, + 'azure.signinlogs.properties.device_detail.device_id': { + category: 'azure', + description: 'Device ID ', + name: 'azure.signinlogs.properties.device_detail.device_id', + type: 'keyword', + }, + 'azure.signinlogs.properties.device_detail.operating_system': { + category: 'azure', + description: 'Operating system ', + name: 'azure.signinlogs.properties.device_detail.operating_system', + type: 'keyword', + }, + 'azure.signinlogs.properties.device_detail.browser': { + category: 'azure', + description: 'Browser ', + name: 'azure.signinlogs.properties.device_detail.browser', + type: 'keyword', + }, + 'azure.signinlogs.properties.device_detail.display_name': { + category: 'azure', + description: 'Display name ', + name: 'azure.signinlogs.properties.device_detail.display_name', + type: 'keyword', + }, + 'azure.signinlogs.properties.device_detail.trust_type': { + category: 'azure', + description: 'Trust type ', + name: 'azure.signinlogs.properties.device_detail.trust_type', + type: 'keyword', + }, + 'azure.signinlogs.properties.service_principal_id': { + category: 'azure', + description: 'Status ', + name: 'azure.signinlogs.properties.service_principal_id', + type: 'keyword', + }, + 'network.interface.name': { + category: 'network', + description: 'Name of the network interface where the traffic has been observed. ', + name: 'network.interface.name', + type: 'keyword', + }, + 'rsa.internal.msg': { + category: 'rsa', + description: 'This key is used to capture the raw message that comes into the Log Decoder', + name: 'rsa.internal.msg', + type: 'keyword', + }, + 'rsa.internal.messageid': { + category: 'rsa', + name: 'rsa.internal.messageid', + type: 'keyword', + }, + 'rsa.internal.event_desc': { + category: 'rsa', + name: 'rsa.internal.event_desc', + type: 'keyword', + }, + 'rsa.internal.message': { + category: 'rsa', + description: 'This key captures the contents of instant messages', + name: 'rsa.internal.message', + type: 'keyword', + }, + 'rsa.internal.time': { + category: 'rsa', + description: + 'This is the time at which a session hits a NetWitness Decoder. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness.', + name: 'rsa.internal.time', + type: 'date', + }, + 'rsa.internal.level': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.level', + type: 'long', + }, + 'rsa.internal.msg_id': { + category: 'rsa', + description: + 'This is the Message ID1 value that identifies the exact log parser definition which parses a particular log session. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.msg_id', + type: 'keyword', + }, + 'rsa.internal.msg_vid': { + category: 'rsa', + description: + 'This is the Message ID2 value that identifies the exact log parser definition which parses a particular log session. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.msg_vid', + type: 'keyword', + }, + 'rsa.internal.data': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.data', + type: 'keyword', + }, + 'rsa.internal.obj_server': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.obj_server', + type: 'keyword', + }, + 'rsa.internal.obj_val': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.obj_val', + type: 'keyword', + }, + 'rsa.internal.resource': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.resource', + type: 'keyword', + }, + 'rsa.internal.obj_id': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.obj_id', + type: 'keyword', + }, + 'rsa.internal.statement': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.statement', + type: 'keyword', + }, + 'rsa.internal.audit_class': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.audit_class', + type: 'keyword', + }, + 'rsa.internal.entry': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.entry', + type: 'keyword', + }, + 'rsa.internal.hcode': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.hcode', + type: 'keyword', + }, + 'rsa.internal.inode': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.inode', + type: 'long', + }, + 'rsa.internal.resource_class': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.resource_class', + type: 'keyword', + }, + 'rsa.internal.dead': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.dead', + type: 'long', + }, + 'rsa.internal.feed_desc': { + category: 'rsa', + description: + 'This is used to capture the description of the feed. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.feed_desc', + type: 'keyword', + }, + 'rsa.internal.feed_name': { + category: 'rsa', + description: + 'This is used to capture the name of the feed. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.feed_name', + type: 'keyword', + }, + 'rsa.internal.cid': { + category: 'rsa', + description: + 'This is the unique identifier used to identify a NetWitness Concentrator. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.cid', + type: 'keyword', + }, + 'rsa.internal.device_class': { + category: 'rsa', + description: + 'This is the Classification of the Log Event Source under a predefined fixed set of Event Source Classifications. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.device_class', + type: 'keyword', + }, + 'rsa.internal.device_group': { + category: 'rsa', + description: + 'This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.device_group', + type: 'keyword', + }, + 'rsa.internal.device_host': { + category: 'rsa', + description: + 'This is the Hostname of the log Event Source sending the logs to NetWitness. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.device_host', + type: 'keyword', + }, + 'rsa.internal.device_ip': { + category: 'rsa', + description: + 'This is the IPv4 address of the Log Event Source sending the logs to NetWitness. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.device_ip', + type: 'ip', + }, + 'rsa.internal.device_ipv6': { + category: 'rsa', + description: + 'This is the IPv6 address of the Log Event Source sending the logs to NetWitness. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.device_ipv6', + type: 'ip', + }, + 'rsa.internal.device_type': { + category: 'rsa', + description: + 'This is the name of the log parser which parsed a given session. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.device_type', + type: 'keyword', + }, + 'rsa.internal.device_type_id': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.device_type_id', + type: 'long', + }, + 'rsa.internal.did': { + category: 'rsa', + description: + 'This is the unique identifier used to identify a NetWitness Decoder. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.did', + type: 'keyword', + }, + 'rsa.internal.entropy_req': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the Meta Type can be either UInt16 or Float32 based on the configuration', + name: 'rsa.internal.entropy_req', + type: 'long', + }, + 'rsa.internal.entropy_res': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the Meta Type can be either UInt16 or Float32 based on the configuration', + name: 'rsa.internal.entropy_res', + type: 'long', + }, + 'rsa.internal.event_name': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.event_name', + type: 'keyword', + }, + 'rsa.internal.feed_category': { + category: 'rsa', + description: + 'This is used to capture the category of the feed. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.feed_category', + type: 'keyword', + }, + 'rsa.internal.forward_ip': { + category: 'rsa', + description: + 'This key should be used to capture the IPV4 address of a relay system which forwarded the events from the original system to NetWitness.', + name: 'rsa.internal.forward_ip', + type: 'ip', + }, + 'rsa.internal.forward_ipv6': { + category: 'rsa', + description: + 'This key is used to capture the IPV6 address of a relay system which forwarded the events from the original system to NetWitness. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.forward_ipv6', + type: 'ip', + }, + 'rsa.internal.header_id': { + category: 'rsa', + description: + 'This is the Header ID value that identifies the exact log parser header definition that parses a particular log session. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.header_id', + type: 'keyword', + }, + 'rsa.internal.lc_cid': { + category: 'rsa', + description: + 'This is a unique Identifier of a Log Collector. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.lc_cid', + type: 'keyword', + }, + 'rsa.internal.lc_ctime': { + category: 'rsa', + description: + 'This is the time at which a log is collected in a NetWitness Log Collector. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.lc_ctime', + type: 'date', + }, + 'rsa.internal.mcb_req': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the most common byte request is simply which byte for each side (0 thru 255) was seen the most', + name: 'rsa.internal.mcb_req', + type: 'long', + }, + 'rsa.internal.mcb_res': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the most common byte response is simply which byte for each side (0 thru 255) was seen the most', + name: 'rsa.internal.mcb_res', + type: 'long', + }, + 'rsa.internal.mcbc_req': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the most common byte count is the number of times the most common byte (above) was seen in the session streams', + name: 'rsa.internal.mcbc_req', + type: 'long', + }, + 'rsa.internal.mcbc_res': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the most common byte count is the number of times the most common byte (above) was seen in the session streams', + name: 'rsa.internal.mcbc_res', + type: 'long', + }, + 'rsa.internal.medium': { + category: 'rsa', + description: + 'This key is used to identify if it’s a log/packet session or Layer 2 Encapsulation Type. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness. 32 = log, 33 = correlation session, < 32 is packet session', + name: 'rsa.internal.medium', + type: 'long', + }, + 'rsa.internal.node_name': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.node_name', + type: 'keyword', + }, + 'rsa.internal.nwe_callback_id': { + category: 'rsa', + description: 'This key denotes that event is endpoint related', + name: 'rsa.internal.nwe_callback_id', + type: 'keyword', + }, + 'rsa.internal.parse_error': { + category: 'rsa', + description: + 'This is a special key that stores any Meta key validation error found while parsing a log session. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.parse_error', + type: 'keyword', + }, + 'rsa.internal.payload_req': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the payload size metrics are the payload sizes of each session side at the time of parsing. However, in order to keep', + name: 'rsa.internal.payload_req', + type: 'long', + }, + 'rsa.internal.payload_res': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, the payload size metrics are the payload sizes of each session side at the time of parsing. However, in order to keep', + name: 'rsa.internal.payload_res', + type: 'long', + }, + 'rsa.internal.process_vid_dst': { + category: 'rsa', + description: + 'Endpoint generates and uses a unique virtual ID to identify any similar group of process. This ID represents the target process.', + name: 'rsa.internal.process_vid_dst', + type: 'keyword', + }, + 'rsa.internal.process_vid_src': { + category: 'rsa', + description: + 'Endpoint generates and uses a unique virtual ID to identify any similar group of process. This ID represents the source process.', + name: 'rsa.internal.process_vid_src', + type: 'keyword', + }, + 'rsa.internal.rid': { + category: 'rsa', + description: + 'This is a special ID of the Remote Session created by NetWitness Decoder. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.rid', + type: 'long', + }, + 'rsa.internal.session_split': { + category: 'rsa', + description: + 'This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.session_split', + type: 'keyword', + }, + 'rsa.internal.site': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.internal.site', + type: 'keyword', + }, + 'rsa.internal.size': { + category: 'rsa', + description: + 'This is the size of the session as seen by the NetWitness Decoder. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.size', + type: 'long', + }, + 'rsa.internal.sourcefile': { + category: 'rsa', + description: + 'This is the name of the log file or PCAPs that can be imported into NetWitness. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.internal.sourcefile', + type: 'keyword', + }, + 'rsa.internal.ubc_req': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, Unique byte count is the number of unique bytes seen in each stream. 256 would mean all byte values of 0 thru 255 were seen at least once', + name: 'rsa.internal.ubc_req', + type: 'long', + }, + 'rsa.internal.ubc_res': { + category: 'rsa', + description: + 'This key is only used by the Entropy Parser, Unique byte count is the number of unique bytes seen in each stream. 256 would mean all byte values of 0 thru 255 were seen at least once', + name: 'rsa.internal.ubc_res', + type: 'long', + }, + 'rsa.internal.word': { + category: 'rsa', + description: + 'This is used by the Word Parsing technology to capture the first 5 character of every word in an unparsed log', + name: 'rsa.internal.word', + type: 'keyword', + }, + 'rsa.time.event_time': { + category: 'rsa', + description: + 'This key is used to capture the time mentioned in a raw session that represents the actual time an event occured in a standard normalized form', + name: 'rsa.time.event_time', + type: 'date', + }, + 'rsa.time.duration_time': { + category: 'rsa', + description: 'This key is used to capture the normalized duration/lifetime in seconds.', + name: 'rsa.time.duration_time', + type: 'double', + }, + 'rsa.time.event_time_str': { + category: 'rsa', + description: + 'This key is used to capture the incomplete time mentioned in a session as a string', + name: 'rsa.time.event_time_str', + type: 'keyword', + }, + 'rsa.time.starttime': { + category: 'rsa', + description: + 'This key is used to capture the Start time mentioned in a session in a standard form', + name: 'rsa.time.starttime', + type: 'date', + }, + 'rsa.time.month': { + category: 'rsa', + name: 'rsa.time.month', + type: 'keyword', + }, + 'rsa.time.day': { + category: 'rsa', + name: 'rsa.time.day', + type: 'keyword', + }, + 'rsa.time.endtime': { + category: 'rsa', + description: + 'This key is used to capture the End time mentioned in a session in a standard form', + name: 'rsa.time.endtime', + type: 'date', + }, + 'rsa.time.timezone': { + category: 'rsa', + description: 'This key is used to capture the timezone of the Event Time', + name: 'rsa.time.timezone', + type: 'keyword', + }, + 'rsa.time.duration_str': { + category: 'rsa', + description: 'A text string version of the duration', + name: 'rsa.time.duration_str', + type: 'keyword', + }, + 'rsa.time.date': { + category: 'rsa', + name: 'rsa.time.date', + type: 'keyword', + }, + 'rsa.time.year': { + category: 'rsa', + name: 'rsa.time.year', + type: 'keyword', + }, + 'rsa.time.recorded_time': { + category: 'rsa', + description: + "The event time as recorded by the system the event is collected from. The usage scenario is a multi-tier application where the management layer of the system records it's own timestamp at the time of collection from its child nodes. Must be in timestamp format.", + name: 'rsa.time.recorded_time', + type: 'date', + }, + 'rsa.time.datetime': { + category: 'rsa', + name: 'rsa.time.datetime', + type: 'keyword', + }, + 'rsa.time.effective_time': { + category: 'rsa', + description: + 'This key is the effective time referenced by an individual event in a Standard Timestamp format', + name: 'rsa.time.effective_time', + type: 'date', + }, + 'rsa.time.expire_time': { + category: 'rsa', + description: 'This key is the timestamp that explicitly refers to an expiration.', + name: 'rsa.time.expire_time', + type: 'date', + }, + 'rsa.time.process_time': { + category: 'rsa', + description: 'Deprecated, use duration.time', + name: 'rsa.time.process_time', + type: 'keyword', + }, + 'rsa.time.hour': { + category: 'rsa', + name: 'rsa.time.hour', + type: 'keyword', + }, + 'rsa.time.min': { + category: 'rsa', + name: 'rsa.time.min', + type: 'keyword', + }, + 'rsa.time.timestamp': { + category: 'rsa', + name: 'rsa.time.timestamp', + type: 'keyword', + }, + 'rsa.time.event_queue_time': { + category: 'rsa', + description: 'This key is the Time that the event was queued.', + name: 'rsa.time.event_queue_time', + type: 'date', + }, + 'rsa.time.p_time1': { + category: 'rsa', + name: 'rsa.time.p_time1', + type: 'keyword', + }, + 'rsa.time.tzone': { + category: 'rsa', + name: 'rsa.time.tzone', + type: 'keyword', + }, + 'rsa.time.eventtime': { + category: 'rsa', + name: 'rsa.time.eventtime', + type: 'keyword', + }, + 'rsa.time.gmtdate': { + category: 'rsa', + name: 'rsa.time.gmtdate', + type: 'keyword', + }, + 'rsa.time.gmttime': { + category: 'rsa', + name: 'rsa.time.gmttime', + type: 'keyword', + }, + 'rsa.time.p_date': { + category: 'rsa', + name: 'rsa.time.p_date', + type: 'keyword', + }, + 'rsa.time.p_month': { + category: 'rsa', + name: 'rsa.time.p_month', + type: 'keyword', + }, + 'rsa.time.p_time': { + category: 'rsa', + name: 'rsa.time.p_time', + type: 'keyword', + }, + 'rsa.time.p_time2': { + category: 'rsa', + name: 'rsa.time.p_time2', + type: 'keyword', + }, + 'rsa.time.p_year': { + category: 'rsa', + name: 'rsa.time.p_year', + type: 'keyword', + }, + 'rsa.time.expire_time_str': { + category: 'rsa', + description: + 'This key is used to capture incomplete timestamp that explicitly refers to an expiration.', + name: 'rsa.time.expire_time_str', + type: 'keyword', + }, + 'rsa.time.stamp': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.time.stamp', + type: 'date', + }, + 'rsa.misc.action': { + category: 'rsa', + name: 'rsa.misc.action', + type: 'keyword', + }, + 'rsa.misc.result': { + category: 'rsa', + description: + 'This key is used to capture the outcome/result string value of an action in a session.', + name: 'rsa.misc.result', + type: 'keyword', + }, + 'rsa.misc.severity': { + category: 'rsa', + description: 'This key is used to capture the severity given the session', + name: 'rsa.misc.severity', + type: 'keyword', + }, + 'rsa.misc.event_type': { + category: 'rsa', + description: 'This key captures the event category type as specified by the event source.', + name: 'rsa.misc.event_type', + type: 'keyword', + }, + 'rsa.misc.reference_id': { + category: 'rsa', + description: 'This key is used to capture an event id from the session directly', + name: 'rsa.misc.reference_id', + type: 'keyword', + }, + 'rsa.misc.version': { + category: 'rsa', + description: + 'This key captures Version of the application or OS which is generating the event.', + name: 'rsa.misc.version', + type: 'keyword', + }, + 'rsa.misc.disposition': { + category: 'rsa', + description: 'This key captures the The end state of an action.', + name: 'rsa.misc.disposition', + type: 'keyword', + }, + 'rsa.misc.result_code': { + category: 'rsa', + description: + 'This key is used to capture the outcome/result numeric value of an action in a session', + name: 'rsa.misc.result_code', + type: 'keyword', + }, + 'rsa.misc.category': { + category: 'rsa', + description: + 'This key is used to capture the category of an event given by the vendor in the session', + name: 'rsa.misc.category', + type: 'keyword', + }, + 'rsa.misc.obj_name': { + category: 'rsa', + description: 'This is used to capture name of object', + name: 'rsa.misc.obj_name', + type: 'keyword', + }, + 'rsa.misc.obj_type': { + category: 'rsa', + description: 'This is used to capture type of object', + name: 'rsa.misc.obj_type', + type: 'keyword', + }, + 'rsa.misc.event_source': { + category: 'rsa', + description: 'This key captures Source of the event that’s not a hostname', + name: 'rsa.misc.event_source', + type: 'keyword', + }, + 'rsa.misc.log_session_id': { + category: 'rsa', + description: 'This key is used to capture a sessionid from the session directly', + name: 'rsa.misc.log_session_id', + type: 'keyword', + }, + 'rsa.misc.group': { + category: 'rsa', + description: 'This key captures the Group Name value', + name: 'rsa.misc.group', + type: 'keyword', + }, + 'rsa.misc.policy_name': { + category: 'rsa', + description: 'This key is used to capture the Policy Name only.', + name: 'rsa.misc.policy_name', + type: 'keyword', + }, + 'rsa.misc.rule_name': { + category: 'rsa', + description: 'This key captures the Rule Name', + name: 'rsa.misc.rule_name', + type: 'keyword', + }, + 'rsa.misc.context': { + category: 'rsa', + description: 'This key captures Information which adds additional context to the event.', + name: 'rsa.misc.context', + type: 'keyword', + }, + 'rsa.misc.change_new': { + category: 'rsa', + description: + 'This key is used to capture the new values of the attribute that’s changing in a session', + name: 'rsa.misc.change_new', + type: 'keyword', + }, + 'rsa.misc.space': { + category: 'rsa', + name: 'rsa.misc.space', + type: 'keyword', + }, + 'rsa.misc.client': { + category: 'rsa', + description: + 'This key is used to capture only the name of the client application requesting resources of the server. See the user.agent meta key for capture of the specific user agent identifier or browser identification string.', + name: 'rsa.misc.client', + type: 'keyword', + }, + 'rsa.misc.msgIdPart1': { + category: 'rsa', + name: 'rsa.misc.msgIdPart1', + type: 'keyword', + }, + 'rsa.misc.msgIdPart2': { + category: 'rsa', + name: 'rsa.misc.msgIdPart2', + type: 'keyword', + }, + 'rsa.misc.change_old': { + category: 'rsa', + description: + 'This key is used to capture the old value of the attribute that’s changing in a session', + name: 'rsa.misc.change_old', + type: 'keyword', + }, + 'rsa.misc.operation_id': { + category: 'rsa', + description: + 'An alert number or operation number. The values should be unique and non-repeating.', + name: 'rsa.misc.operation_id', + type: 'keyword', + }, + 'rsa.misc.event_state': { + category: 'rsa', + description: + 'This key captures the current state of the object/item referenced within the event. Describing an on-going event.', + name: 'rsa.misc.event_state', + type: 'keyword', + }, + 'rsa.misc.group_object': { + category: 'rsa', + description: 'This key captures a collection/grouping of entities. Specific usage', + name: 'rsa.misc.group_object', + type: 'keyword', + }, + 'rsa.misc.node': { + category: 'rsa', + description: + 'Common use case is the node name within a cluster. The cluster name is reflected by the host name.', + name: 'rsa.misc.node', + type: 'keyword', + }, + 'rsa.misc.rule': { + category: 'rsa', + description: 'This key captures the Rule number', + name: 'rsa.misc.rule', + type: 'keyword', + }, + 'rsa.misc.device_name': { + category: 'rsa', + description: + 'This is used to capture name of the Device associated with the node Like: a physical disk, printer, etc', + name: 'rsa.misc.device_name', + type: 'keyword', + }, + 'rsa.misc.param': { + category: 'rsa', + description: 'This key is the parameters passed as part of a command or application, etc.', + name: 'rsa.misc.param', + type: 'keyword', + }, + 'rsa.misc.change_attrib': { + category: 'rsa', + description: + 'This key is used to capture the name of the attribute that’s changing in a session', + name: 'rsa.misc.change_attrib', + type: 'keyword', + }, + 'rsa.misc.event_computer': { + category: 'rsa', + description: + 'This key is a windows only concept, where this key is used to capture fully qualified domain name in a windows log.', + name: 'rsa.misc.event_computer', + type: 'keyword', + }, + 'rsa.misc.reference_id1': { + category: 'rsa', + description: 'This key is for Linked ID to be used as an addition to "reference.id"', + name: 'rsa.misc.reference_id1', + type: 'keyword', + }, + 'rsa.misc.event_log': { + category: 'rsa', + description: 'This key captures the Name of the event log', + name: 'rsa.misc.event_log', + type: 'keyword', + }, + 'rsa.misc.OS': { + category: 'rsa', + description: 'This key captures the Name of the Operating System', + name: 'rsa.misc.OS', + type: 'keyword', + }, + 'rsa.misc.terminal': { + category: 'rsa', + description: 'This key captures the Terminal Names only', + name: 'rsa.misc.terminal', + type: 'keyword', + }, + 'rsa.misc.msgIdPart3': { + category: 'rsa', + name: 'rsa.misc.msgIdPart3', + type: 'keyword', + }, + 'rsa.misc.filter': { + category: 'rsa', + description: 'This key captures Filter used to reduce result set', + name: 'rsa.misc.filter', + type: 'keyword', + }, + 'rsa.misc.serial_number': { + category: 'rsa', + description: 'This key is the Serial number associated with a physical asset.', + name: 'rsa.misc.serial_number', + type: 'keyword', + }, + 'rsa.misc.checksum': { + category: 'rsa', + description: + 'This key is used to capture the checksum or hash of the entity such as a file or process. Checksum should be used over checksum.src or checksum.dst when it is unclear whether the entity is a source or target of an action.', + name: 'rsa.misc.checksum', + type: 'keyword', + }, + 'rsa.misc.event_user': { + category: 'rsa', + description: + 'This key is a windows only concept, where this key is used to capture combination of domain name and username in a windows log.', + name: 'rsa.misc.event_user', + type: 'keyword', + }, + 'rsa.misc.virusname': { + category: 'rsa', + description: 'This key captures the name of the virus', + name: 'rsa.misc.virusname', + type: 'keyword', + }, + 'rsa.misc.content_type': { + category: 'rsa', + description: 'This key is used to capture Content Type only.', + name: 'rsa.misc.content_type', + type: 'keyword', + }, + 'rsa.misc.group_id': { + category: 'rsa', + description: 'This key captures Group ID Number (related to the group name)', + name: 'rsa.misc.group_id', + type: 'keyword', + }, + 'rsa.misc.policy_id': { + category: 'rsa', + description: + 'This key is used to capture the Policy ID only, this should be a numeric value, use policy.name otherwise', + name: 'rsa.misc.policy_id', + type: 'keyword', + }, + 'rsa.misc.vsys': { + category: 'rsa', + description: 'This key captures Virtual System Name', + name: 'rsa.misc.vsys', + type: 'keyword', + }, + 'rsa.misc.connection_id': { + category: 'rsa', + description: 'This key captures the Connection ID', + name: 'rsa.misc.connection_id', + type: 'keyword', + }, + 'rsa.misc.reference_id2': { + category: 'rsa', + description: + 'This key is for the 2nd Linked ID. Can be either linked to "reference.id" or "reference.id1" value but should not be used unless the other two variables are in play.', + name: 'rsa.misc.reference_id2', + type: 'keyword', + }, + 'rsa.misc.sensor': { + category: 'rsa', + description: 'This key captures Name of the sensor. Typically used in IDS/IPS based devices', + name: 'rsa.misc.sensor', + type: 'keyword', + }, + 'rsa.misc.sig_id': { + category: 'rsa', + description: 'This key captures IDS/IPS Int Signature ID', + name: 'rsa.misc.sig_id', + type: 'long', + }, + 'rsa.misc.port_name': { + category: 'rsa', + description: + 'This key is used for Physical or logical port connection but does NOT include a network port. (Example: Printer port name).', + name: 'rsa.misc.port_name', + type: 'keyword', + }, + 'rsa.misc.rule_group': { + category: 'rsa', + description: 'This key captures the Rule group name', + name: 'rsa.misc.rule_group', + type: 'keyword', + }, + 'rsa.misc.risk_num': { + category: 'rsa', + description: 'This key captures a Numeric Risk value', + name: 'rsa.misc.risk_num', + type: 'double', + }, + 'rsa.misc.trigger_val': { + category: 'rsa', + description: 'This key captures the Value of the trigger or threshold condition.', + name: 'rsa.misc.trigger_val', + type: 'keyword', + }, + 'rsa.misc.log_session_id1': { + category: 'rsa', + description: + 'This key is used to capture a Linked (Related) Session ID from the session directly', + name: 'rsa.misc.log_session_id1', + type: 'keyword', + }, + 'rsa.misc.comp_version': { + category: 'rsa', + description: 'This key captures the Version level of a sub-component of a product.', + name: 'rsa.misc.comp_version', + type: 'keyword', + }, + 'rsa.misc.content_version': { + category: 'rsa', + description: 'This key captures Version level of a signature or database content.', + name: 'rsa.misc.content_version', + type: 'keyword', + }, + 'rsa.misc.hardware_id': { + category: 'rsa', + description: + 'This key is used to capture unique identifier for a device or system (NOT a Mac address)', + name: 'rsa.misc.hardware_id', + type: 'keyword', + }, + 'rsa.misc.risk': { + category: 'rsa', + description: 'This key captures the non-numeric risk value', + name: 'rsa.misc.risk', + type: 'keyword', + }, + 'rsa.misc.event_id': { + category: 'rsa', + name: 'rsa.misc.event_id', + type: 'keyword', + }, + 'rsa.misc.reason': { + category: 'rsa', + name: 'rsa.misc.reason', + type: 'keyword', + }, + 'rsa.misc.status': { + category: 'rsa', + name: 'rsa.misc.status', + type: 'keyword', + }, + 'rsa.misc.mail_id': { + category: 'rsa', + description: 'This key is used to capture the mailbox id/name', + name: 'rsa.misc.mail_id', + type: 'keyword', + }, + 'rsa.misc.rule_uid': { + category: 'rsa', + description: 'This key is the Unique Identifier for a rule.', + name: 'rsa.misc.rule_uid', + type: 'keyword', + }, + 'rsa.misc.trigger_desc': { + category: 'rsa', + description: 'This key captures the Description of the trigger or threshold condition.', + name: 'rsa.misc.trigger_desc', + type: 'keyword', + }, + 'rsa.misc.inout': { + category: 'rsa', + name: 'rsa.misc.inout', + type: 'keyword', + }, + 'rsa.misc.p_msgid': { + category: 'rsa', + name: 'rsa.misc.p_msgid', + type: 'keyword', + }, + 'rsa.misc.data_type': { + category: 'rsa', + name: 'rsa.misc.data_type', + type: 'keyword', + }, + 'rsa.misc.msgIdPart4': { + category: 'rsa', + name: 'rsa.misc.msgIdPart4', + type: 'keyword', + }, + 'rsa.misc.error': { + category: 'rsa', + description: 'This key captures All non successful Error codes or responses', + name: 'rsa.misc.error', + type: 'keyword', + }, + 'rsa.misc.index': { + category: 'rsa', + name: 'rsa.misc.index', + type: 'keyword', + }, + 'rsa.misc.listnum': { + category: 'rsa', + description: + 'This key is used to capture listname or listnumber, primarily for collecting access-list', + name: 'rsa.misc.listnum', + type: 'keyword', + }, + 'rsa.misc.ntype': { + category: 'rsa', + name: 'rsa.misc.ntype', + type: 'keyword', + }, + 'rsa.misc.observed_val': { + category: 'rsa', + description: + 'This key captures the Value observed (from the perspective of the device generating the log).', + name: 'rsa.misc.observed_val', + type: 'keyword', + }, + 'rsa.misc.policy_value': { + category: 'rsa', + description: + 'This key captures the contents of the policy. This contains details about the policy', + name: 'rsa.misc.policy_value', + type: 'keyword', + }, + 'rsa.misc.pool_name': { + category: 'rsa', + description: 'This key captures the name of a resource pool', + name: 'rsa.misc.pool_name', + type: 'keyword', + }, + 'rsa.misc.rule_template': { + category: 'rsa', + description: + 'A default set of parameters which are overlayed onto a rule (or rulename) which efffectively constitutes a template', + name: 'rsa.misc.rule_template', + type: 'keyword', + }, + 'rsa.misc.count': { + category: 'rsa', + name: 'rsa.misc.count', + type: 'keyword', + }, + 'rsa.misc.number': { + category: 'rsa', + name: 'rsa.misc.number', + type: 'keyword', + }, + 'rsa.misc.sigcat': { + category: 'rsa', + name: 'rsa.misc.sigcat', + type: 'keyword', + }, + 'rsa.misc.type': { + category: 'rsa', + name: 'rsa.misc.type', + type: 'keyword', + }, + 'rsa.misc.comments': { + category: 'rsa', + description: 'Comment information provided in the log message', + name: 'rsa.misc.comments', + type: 'keyword', + }, + 'rsa.misc.doc_number': { + category: 'rsa', + description: 'This key captures File Identification number', + name: 'rsa.misc.doc_number', + type: 'long', + }, + 'rsa.misc.expected_val': { + category: 'rsa', + description: + 'This key captures the Value expected (from the perspective of the device generating the log).', + name: 'rsa.misc.expected_val', + type: 'keyword', + }, + 'rsa.misc.job_num': { + category: 'rsa', + description: 'This key captures the Job Number', + name: 'rsa.misc.job_num', + type: 'keyword', + }, + 'rsa.misc.spi_dst': { + category: 'rsa', + description: 'Destination SPI Index', + name: 'rsa.misc.spi_dst', + type: 'keyword', + }, + 'rsa.misc.spi_src': { + category: 'rsa', + description: 'Source SPI Index', + name: 'rsa.misc.spi_src', + type: 'keyword', + }, + 'rsa.misc.code': { + category: 'rsa', + name: 'rsa.misc.code', + type: 'keyword', + }, + 'rsa.misc.agent_id': { + category: 'rsa', + description: 'This key is used to capture agent id', + name: 'rsa.misc.agent_id', + type: 'keyword', + }, + 'rsa.misc.message_body': { + category: 'rsa', + description: 'This key captures the The contents of the message body.', + name: 'rsa.misc.message_body', + type: 'keyword', + }, + 'rsa.misc.phone': { + category: 'rsa', + name: 'rsa.misc.phone', + type: 'keyword', + }, + 'rsa.misc.sig_id_str': { + category: 'rsa', + description: 'This key captures a string object of the sigid variable.', + name: 'rsa.misc.sig_id_str', + type: 'keyword', + }, + 'rsa.misc.cmd': { + category: 'rsa', + name: 'rsa.misc.cmd', + type: 'keyword', + }, + 'rsa.misc.misc': { + category: 'rsa', + name: 'rsa.misc.misc', + type: 'keyword', + }, + 'rsa.misc.name': { + category: 'rsa', + name: 'rsa.misc.name', + type: 'keyword', + }, + 'rsa.misc.cpu': { + category: 'rsa', + description: 'This key is the CPU time used in the execution of the event being recorded.', + name: 'rsa.misc.cpu', + type: 'long', + }, + 'rsa.misc.event_desc': { + category: 'rsa', + description: + 'This key is used to capture a description of an event available directly or inferred', + name: 'rsa.misc.event_desc', + type: 'keyword', + }, + 'rsa.misc.sig_id1': { + category: 'rsa', + description: 'This key captures IDS/IPS Int Signature ID. This must be linked to the sig.id', + name: 'rsa.misc.sig_id1', + type: 'long', + }, + 'rsa.misc.im_buddyid': { + category: 'rsa', + name: 'rsa.misc.im_buddyid', + type: 'keyword', + }, + 'rsa.misc.im_client': { + category: 'rsa', + name: 'rsa.misc.im_client', + type: 'keyword', + }, + 'rsa.misc.im_userid': { + category: 'rsa', + name: 'rsa.misc.im_userid', + type: 'keyword', + }, + 'rsa.misc.pid': { + category: 'rsa', + name: 'rsa.misc.pid', + type: 'keyword', + }, + 'rsa.misc.priority': { + category: 'rsa', + name: 'rsa.misc.priority', + type: 'keyword', + }, + 'rsa.misc.context_subject': { + category: 'rsa', + description: + 'This key is to be used in an audit context where the subject is the object being identified', + name: 'rsa.misc.context_subject', + type: 'keyword', + }, + 'rsa.misc.context_target': { + category: 'rsa', + name: 'rsa.misc.context_target', + type: 'keyword', + }, + 'rsa.misc.cve': { + category: 'rsa', + description: + 'This key captures CVE (Common Vulnerabilities and Exposures) - an identifier for known information security vulnerabilities.', + name: 'rsa.misc.cve', + type: 'keyword', + }, + 'rsa.misc.fcatnum': { + category: 'rsa', + description: 'This key captures Filter Category Number. Legacy Usage', + name: 'rsa.misc.fcatnum', + type: 'keyword', + }, + 'rsa.misc.library': { + category: 'rsa', + description: 'This key is used to capture library information in mainframe devices', + name: 'rsa.misc.library', + type: 'keyword', + }, + 'rsa.misc.parent_node': { + category: 'rsa', + description: 'This key captures the Parent Node Name. Must be related to node variable.', + name: 'rsa.misc.parent_node', + type: 'keyword', + }, + 'rsa.misc.risk_info': { + category: 'rsa', + description: 'Deprecated, use New Hunting Model (inv.*, ioc, boc, eoc, analysis.*)', + name: 'rsa.misc.risk_info', + type: 'keyword', + }, + 'rsa.misc.tcp_flags': { + category: 'rsa', + description: 'This key is captures the TCP flags set in any packet of session', + name: 'rsa.misc.tcp_flags', + type: 'long', + }, + 'rsa.misc.tos': { + category: 'rsa', + description: 'This key describes the type of service', + name: 'rsa.misc.tos', + type: 'long', + }, + 'rsa.misc.vm_target': { + category: 'rsa', + description: 'VMWare Target **VMWARE** only varaible.', + name: 'rsa.misc.vm_target', + type: 'keyword', + }, + 'rsa.misc.workspace': { + category: 'rsa', + description: 'This key captures Workspace Description', + name: 'rsa.misc.workspace', + type: 'keyword', + }, + 'rsa.misc.command': { + category: 'rsa', + name: 'rsa.misc.command', + type: 'keyword', + }, + 'rsa.misc.event_category': { + category: 'rsa', + name: 'rsa.misc.event_category', + type: 'keyword', + }, + 'rsa.misc.facilityname': { + category: 'rsa', + name: 'rsa.misc.facilityname', + type: 'keyword', + }, + 'rsa.misc.forensic_info': { + category: 'rsa', + name: 'rsa.misc.forensic_info', + type: 'keyword', + }, + 'rsa.misc.jobname': { + category: 'rsa', + name: 'rsa.misc.jobname', + type: 'keyword', + }, + 'rsa.misc.mode': { + category: 'rsa', + name: 'rsa.misc.mode', + type: 'keyword', + }, + 'rsa.misc.policy': { + category: 'rsa', + name: 'rsa.misc.policy', + type: 'keyword', + }, + 'rsa.misc.policy_waiver': { + category: 'rsa', + name: 'rsa.misc.policy_waiver', + type: 'keyword', + }, + 'rsa.misc.second': { + category: 'rsa', + name: 'rsa.misc.second', + type: 'keyword', + }, + 'rsa.misc.space1': { + category: 'rsa', + name: 'rsa.misc.space1', + type: 'keyword', + }, + 'rsa.misc.subcategory': { + category: 'rsa', + name: 'rsa.misc.subcategory', + type: 'keyword', + }, + 'rsa.misc.tbdstr2': { + category: 'rsa', + name: 'rsa.misc.tbdstr2', + type: 'keyword', + }, + 'rsa.misc.alert_id': { + category: 'rsa', + description: 'Deprecated, New Hunting Model (inv.*, ioc, boc, eoc, analysis.*)', + name: 'rsa.misc.alert_id', + type: 'keyword', + }, + 'rsa.misc.checksum_dst': { + category: 'rsa', + description: + 'This key is used to capture the checksum or hash of the the target entity such as a process or file.', + name: 'rsa.misc.checksum_dst', + type: 'keyword', + }, + 'rsa.misc.checksum_src': { + category: 'rsa', + description: + 'This key is used to capture the checksum or hash of the source entity such as a file or process.', + name: 'rsa.misc.checksum_src', + type: 'keyword', + }, + 'rsa.misc.fresult': { + category: 'rsa', + description: 'This key captures the Filter Result', + name: 'rsa.misc.fresult', + type: 'long', + }, + 'rsa.misc.payload_dst': { + category: 'rsa', + description: 'This key is used to capture destination payload', + name: 'rsa.misc.payload_dst', + type: 'keyword', + }, + 'rsa.misc.payload_src': { + category: 'rsa', + description: 'This key is used to capture source payload', + name: 'rsa.misc.payload_src', + type: 'keyword', + }, + 'rsa.misc.pool_id': { + category: 'rsa', + description: 'This key captures the identifier (typically numeric field) of a resource pool', + name: 'rsa.misc.pool_id', + type: 'keyword', + }, + 'rsa.misc.process_id_val': { + category: 'rsa', + description: 'This key is a failure key for Process ID when it is not an integer value', + name: 'rsa.misc.process_id_val', + type: 'keyword', + }, + 'rsa.misc.risk_num_comm': { + category: 'rsa', + description: 'This key captures Risk Number Community', + name: 'rsa.misc.risk_num_comm', + type: 'double', + }, + 'rsa.misc.risk_num_next': { + category: 'rsa', + description: 'This key captures Risk Number NextGen', + name: 'rsa.misc.risk_num_next', + type: 'double', + }, + 'rsa.misc.risk_num_sand': { + category: 'rsa', + description: 'This key captures Risk Number SandBox', + name: 'rsa.misc.risk_num_sand', + type: 'double', + }, + 'rsa.misc.risk_num_static': { + category: 'rsa', + description: 'This key captures Risk Number Static', + name: 'rsa.misc.risk_num_static', + type: 'double', + }, + 'rsa.misc.risk_suspicious': { + category: 'rsa', + description: 'Deprecated, use New Hunting Model (inv.*, ioc, boc, eoc, analysis.*)', + name: 'rsa.misc.risk_suspicious', + type: 'keyword', + }, + 'rsa.misc.risk_warning': { + category: 'rsa', + description: 'Deprecated, use New Hunting Model (inv.*, ioc, boc, eoc, analysis.*)', + name: 'rsa.misc.risk_warning', + type: 'keyword', + }, + 'rsa.misc.snmp_oid': { + category: 'rsa', + description: 'SNMP Object Identifier', + name: 'rsa.misc.snmp_oid', + type: 'keyword', + }, + 'rsa.misc.sql': { + category: 'rsa', + description: 'This key captures the SQL query', + name: 'rsa.misc.sql', + type: 'keyword', + }, + 'rsa.misc.vuln_ref': { + category: 'rsa', + description: 'This key captures the Vulnerability Reference details', + name: 'rsa.misc.vuln_ref', + type: 'keyword', + }, + 'rsa.misc.acl_id': { + category: 'rsa', + name: 'rsa.misc.acl_id', + type: 'keyword', + }, + 'rsa.misc.acl_op': { + category: 'rsa', + name: 'rsa.misc.acl_op', + type: 'keyword', + }, + 'rsa.misc.acl_pos': { + category: 'rsa', + name: 'rsa.misc.acl_pos', + type: 'keyword', + }, + 'rsa.misc.acl_table': { + category: 'rsa', + name: 'rsa.misc.acl_table', + type: 'keyword', + }, + 'rsa.misc.admin': { + category: 'rsa', + name: 'rsa.misc.admin', + type: 'keyword', + }, + 'rsa.misc.alarm_id': { + category: 'rsa', + name: 'rsa.misc.alarm_id', + type: 'keyword', + }, + 'rsa.misc.alarmname': { + category: 'rsa', + name: 'rsa.misc.alarmname', + type: 'keyword', + }, + 'rsa.misc.app_id': { + category: 'rsa', + name: 'rsa.misc.app_id', + type: 'keyword', + }, + 'rsa.misc.audit': { + category: 'rsa', + name: 'rsa.misc.audit', + type: 'keyword', + }, + 'rsa.misc.audit_object': { + category: 'rsa', + name: 'rsa.misc.audit_object', + type: 'keyword', + }, + 'rsa.misc.auditdata': { + category: 'rsa', + name: 'rsa.misc.auditdata', + type: 'keyword', + }, + 'rsa.misc.benchmark': { + category: 'rsa', + name: 'rsa.misc.benchmark', + type: 'keyword', + }, + 'rsa.misc.bypass': { + category: 'rsa', + name: 'rsa.misc.bypass', + type: 'keyword', + }, + 'rsa.misc.cache': { + category: 'rsa', + name: 'rsa.misc.cache', + type: 'keyword', + }, + 'rsa.misc.cache_hit': { + category: 'rsa', + name: 'rsa.misc.cache_hit', + type: 'keyword', + }, + 'rsa.misc.cefversion': { + category: 'rsa', + name: 'rsa.misc.cefversion', + type: 'keyword', + }, + 'rsa.misc.cfg_attr': { + category: 'rsa', + name: 'rsa.misc.cfg_attr', + type: 'keyword', + }, + 'rsa.misc.cfg_obj': { + category: 'rsa', + name: 'rsa.misc.cfg_obj', + type: 'keyword', + }, + 'rsa.misc.cfg_path': { + category: 'rsa', + name: 'rsa.misc.cfg_path', + type: 'keyword', + }, + 'rsa.misc.changes': { + category: 'rsa', + name: 'rsa.misc.changes', + type: 'keyword', + }, + 'rsa.misc.client_ip': { + category: 'rsa', + name: 'rsa.misc.client_ip', + type: 'keyword', + }, + 'rsa.misc.clustermembers': { + category: 'rsa', + name: 'rsa.misc.clustermembers', + type: 'keyword', + }, + 'rsa.misc.cn_acttimeout': { + category: 'rsa', + name: 'rsa.misc.cn_acttimeout', + type: 'keyword', + }, + 'rsa.misc.cn_asn_src': { + category: 'rsa', + name: 'rsa.misc.cn_asn_src', + type: 'keyword', + }, + 'rsa.misc.cn_bgpv4nxthop': { + category: 'rsa', + name: 'rsa.misc.cn_bgpv4nxthop', + type: 'keyword', + }, + 'rsa.misc.cn_ctr_dst_code': { + category: 'rsa', + name: 'rsa.misc.cn_ctr_dst_code', + type: 'keyword', + }, + 'rsa.misc.cn_dst_tos': { + category: 'rsa', + name: 'rsa.misc.cn_dst_tos', + type: 'keyword', + }, + 'rsa.misc.cn_dst_vlan': { + category: 'rsa', + name: 'rsa.misc.cn_dst_vlan', + type: 'keyword', + }, + 'rsa.misc.cn_engine_id': { + category: 'rsa', + name: 'rsa.misc.cn_engine_id', + type: 'keyword', + }, + 'rsa.misc.cn_engine_type': { + category: 'rsa', + name: 'rsa.misc.cn_engine_type', + type: 'keyword', + }, + 'rsa.misc.cn_f_switch': { + category: 'rsa', + name: 'rsa.misc.cn_f_switch', + type: 'keyword', + }, + 'rsa.misc.cn_flowsampid': { + category: 'rsa', + name: 'rsa.misc.cn_flowsampid', + type: 'keyword', + }, + 'rsa.misc.cn_flowsampintv': { + category: 'rsa', + name: 'rsa.misc.cn_flowsampintv', + type: 'keyword', + }, + 'rsa.misc.cn_flowsampmode': { + category: 'rsa', + name: 'rsa.misc.cn_flowsampmode', + type: 'keyword', + }, + 'rsa.misc.cn_inacttimeout': { + category: 'rsa', + name: 'rsa.misc.cn_inacttimeout', + type: 'keyword', + }, + 'rsa.misc.cn_inpermbyts': { + category: 'rsa', + name: 'rsa.misc.cn_inpermbyts', + type: 'keyword', + }, + 'rsa.misc.cn_inpermpckts': { + category: 'rsa', + name: 'rsa.misc.cn_inpermpckts', + type: 'keyword', + }, + 'rsa.misc.cn_invalid': { + category: 'rsa', + name: 'rsa.misc.cn_invalid', + type: 'keyword', + }, + 'rsa.misc.cn_ip_proto_ver': { + category: 'rsa', + name: 'rsa.misc.cn_ip_proto_ver', + type: 'keyword', + }, + 'rsa.misc.cn_ipv4_ident': { + category: 'rsa', + name: 'rsa.misc.cn_ipv4_ident', + type: 'keyword', + }, + 'rsa.misc.cn_l_switch': { + category: 'rsa', + name: 'rsa.misc.cn_l_switch', + type: 'keyword', + }, + 'rsa.misc.cn_log_did': { + category: 'rsa', + name: 'rsa.misc.cn_log_did', + type: 'keyword', + }, + 'rsa.misc.cn_log_rid': { + category: 'rsa', + name: 'rsa.misc.cn_log_rid', + type: 'keyword', + }, + 'rsa.misc.cn_max_ttl': { + category: 'rsa', + name: 'rsa.misc.cn_max_ttl', + type: 'keyword', + }, + 'rsa.misc.cn_maxpcktlen': { + category: 'rsa', + name: 'rsa.misc.cn_maxpcktlen', + type: 'keyword', + }, + 'rsa.misc.cn_min_ttl': { + category: 'rsa', + name: 'rsa.misc.cn_min_ttl', + type: 'keyword', + }, + 'rsa.misc.cn_minpcktlen': { + category: 'rsa', + name: 'rsa.misc.cn_minpcktlen', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_1': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_1', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_10': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_10', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_2': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_2', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_3': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_3', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_4': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_4', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_5': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_5', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_6': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_6', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_7': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_7', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_8': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_8', + type: 'keyword', + }, + 'rsa.misc.cn_mpls_lbl_9': { + category: 'rsa', + name: 'rsa.misc.cn_mpls_lbl_9', + type: 'keyword', + }, + 'rsa.misc.cn_mplstoplabel': { + category: 'rsa', + name: 'rsa.misc.cn_mplstoplabel', + type: 'keyword', + }, + 'rsa.misc.cn_mplstoplabip': { + category: 'rsa', + name: 'rsa.misc.cn_mplstoplabip', + type: 'keyword', + }, + 'rsa.misc.cn_mul_dst_byt': { + category: 'rsa', + name: 'rsa.misc.cn_mul_dst_byt', + type: 'keyword', + }, + 'rsa.misc.cn_mul_dst_pks': { + category: 'rsa', + name: 'rsa.misc.cn_mul_dst_pks', + type: 'keyword', + }, + 'rsa.misc.cn_muligmptype': { + category: 'rsa', + name: 'rsa.misc.cn_muligmptype', + type: 'keyword', + }, + 'rsa.misc.cn_sampalgo': { + category: 'rsa', + name: 'rsa.misc.cn_sampalgo', + type: 'keyword', + }, + 'rsa.misc.cn_sampint': { + category: 'rsa', + name: 'rsa.misc.cn_sampint', + type: 'keyword', + }, + 'rsa.misc.cn_seqctr': { + category: 'rsa', + name: 'rsa.misc.cn_seqctr', + type: 'keyword', + }, + 'rsa.misc.cn_spackets': { + category: 'rsa', + name: 'rsa.misc.cn_spackets', + type: 'keyword', + }, + 'rsa.misc.cn_src_tos': { + category: 'rsa', + name: 'rsa.misc.cn_src_tos', + type: 'keyword', + }, + 'rsa.misc.cn_src_vlan': { + category: 'rsa', + name: 'rsa.misc.cn_src_vlan', + type: 'keyword', + }, + 'rsa.misc.cn_sysuptime': { + category: 'rsa', + name: 'rsa.misc.cn_sysuptime', + type: 'keyword', + }, + 'rsa.misc.cn_template_id': { + category: 'rsa', + name: 'rsa.misc.cn_template_id', + type: 'keyword', + }, + 'rsa.misc.cn_totbytsexp': { + category: 'rsa', + name: 'rsa.misc.cn_totbytsexp', + type: 'keyword', + }, + 'rsa.misc.cn_totflowexp': { + category: 'rsa', + name: 'rsa.misc.cn_totflowexp', + type: 'keyword', + }, + 'rsa.misc.cn_totpcktsexp': { + category: 'rsa', + name: 'rsa.misc.cn_totpcktsexp', + type: 'keyword', + }, + 'rsa.misc.cn_unixnanosecs': { + category: 'rsa', + name: 'rsa.misc.cn_unixnanosecs', + type: 'keyword', + }, + 'rsa.misc.cn_v6flowlabel': { + category: 'rsa', + name: 'rsa.misc.cn_v6flowlabel', + type: 'keyword', + }, + 'rsa.misc.cn_v6optheaders': { + category: 'rsa', + name: 'rsa.misc.cn_v6optheaders', + type: 'keyword', + }, + 'rsa.misc.comp_class': { + category: 'rsa', + name: 'rsa.misc.comp_class', + type: 'keyword', + }, + 'rsa.misc.comp_name': { + category: 'rsa', + name: 'rsa.misc.comp_name', + type: 'keyword', + }, + 'rsa.misc.comp_rbytes': { + category: 'rsa', + name: 'rsa.misc.comp_rbytes', + type: 'keyword', + }, + 'rsa.misc.comp_sbytes': { + category: 'rsa', + name: 'rsa.misc.comp_sbytes', + type: 'keyword', + }, + 'rsa.misc.cpu_data': { + category: 'rsa', + name: 'rsa.misc.cpu_data', + type: 'keyword', + }, + 'rsa.misc.criticality': { + category: 'rsa', + name: 'rsa.misc.criticality', + type: 'keyword', + }, + 'rsa.misc.cs_agency_dst': { + category: 'rsa', + name: 'rsa.misc.cs_agency_dst', + type: 'keyword', + }, + 'rsa.misc.cs_analyzedby': { + category: 'rsa', + name: 'rsa.misc.cs_analyzedby', + type: 'keyword', + }, + 'rsa.misc.cs_av_other': { + category: 'rsa', + name: 'rsa.misc.cs_av_other', + type: 'keyword', + }, + 'rsa.misc.cs_av_primary': { + category: 'rsa', + name: 'rsa.misc.cs_av_primary', + type: 'keyword', + }, + 'rsa.misc.cs_av_secondary': { + category: 'rsa', + name: 'rsa.misc.cs_av_secondary', + type: 'keyword', + }, + 'rsa.misc.cs_bgpv6nxthop': { + category: 'rsa', + name: 'rsa.misc.cs_bgpv6nxthop', + type: 'keyword', + }, + 'rsa.misc.cs_bit9status': { + category: 'rsa', + name: 'rsa.misc.cs_bit9status', + type: 'keyword', + }, + 'rsa.misc.cs_context': { + category: 'rsa', + name: 'rsa.misc.cs_context', + type: 'keyword', + }, + 'rsa.misc.cs_control': { + category: 'rsa', + name: 'rsa.misc.cs_control', + type: 'keyword', + }, + 'rsa.misc.cs_data': { + category: 'rsa', + name: 'rsa.misc.cs_data', + type: 'keyword', + }, + 'rsa.misc.cs_datecret': { + category: 'rsa', + name: 'rsa.misc.cs_datecret', + type: 'keyword', + }, + 'rsa.misc.cs_dst_tld': { + category: 'rsa', + name: 'rsa.misc.cs_dst_tld', + type: 'keyword', + }, + 'rsa.misc.cs_eth_dst_ven': { + category: 'rsa', + name: 'rsa.misc.cs_eth_dst_ven', + type: 'keyword', + }, + 'rsa.misc.cs_eth_src_ven': { + category: 'rsa', + name: 'rsa.misc.cs_eth_src_ven', + type: 'keyword', + }, + 'rsa.misc.cs_event_uuid': { + category: 'rsa', + name: 'rsa.misc.cs_event_uuid', + type: 'keyword', + }, + 'rsa.misc.cs_filetype': { + category: 'rsa', + name: 'rsa.misc.cs_filetype', + type: 'keyword', + }, + 'rsa.misc.cs_fld': { + category: 'rsa', + name: 'rsa.misc.cs_fld', + type: 'keyword', + }, + 'rsa.misc.cs_if_desc': { + category: 'rsa', + name: 'rsa.misc.cs_if_desc', + type: 'keyword', + }, + 'rsa.misc.cs_if_name': { + category: 'rsa', + name: 'rsa.misc.cs_if_name', + type: 'keyword', + }, + 'rsa.misc.cs_ip_next_hop': { + category: 'rsa', + name: 'rsa.misc.cs_ip_next_hop', + type: 'keyword', + }, + 'rsa.misc.cs_ipv4dstpre': { + category: 'rsa', + name: 'rsa.misc.cs_ipv4dstpre', + type: 'keyword', + }, + 'rsa.misc.cs_ipv4srcpre': { + category: 'rsa', + name: 'rsa.misc.cs_ipv4srcpre', + type: 'keyword', + }, + 'rsa.misc.cs_lifetime': { + category: 'rsa', + name: 'rsa.misc.cs_lifetime', + type: 'keyword', + }, + 'rsa.misc.cs_log_medium': { + category: 'rsa', + name: 'rsa.misc.cs_log_medium', + type: 'keyword', + }, + 'rsa.misc.cs_loginname': { + category: 'rsa', + name: 'rsa.misc.cs_loginname', + type: 'keyword', + }, + 'rsa.misc.cs_modulescore': { + category: 'rsa', + name: 'rsa.misc.cs_modulescore', + type: 'keyword', + }, + 'rsa.misc.cs_modulesign': { + category: 'rsa', + name: 'rsa.misc.cs_modulesign', + type: 'keyword', + }, + 'rsa.misc.cs_opswatresult': { + category: 'rsa', + name: 'rsa.misc.cs_opswatresult', + type: 'keyword', + }, + 'rsa.misc.cs_payload': { + category: 'rsa', + name: 'rsa.misc.cs_payload', + type: 'keyword', + }, + 'rsa.misc.cs_registrant': { + category: 'rsa', + name: 'rsa.misc.cs_registrant', + type: 'keyword', + }, + 'rsa.misc.cs_registrar': { + category: 'rsa', + name: 'rsa.misc.cs_registrar', + type: 'keyword', + }, + 'rsa.misc.cs_represult': { + category: 'rsa', + name: 'rsa.misc.cs_represult', + type: 'keyword', + }, + 'rsa.misc.cs_rpayload': { + category: 'rsa', + name: 'rsa.misc.cs_rpayload', + type: 'keyword', + }, + 'rsa.misc.cs_sampler_name': { + category: 'rsa', + name: 'rsa.misc.cs_sampler_name', + type: 'keyword', + }, + 'rsa.misc.cs_sourcemodule': { + category: 'rsa', + name: 'rsa.misc.cs_sourcemodule', + type: 'keyword', + }, + 'rsa.misc.cs_streams': { + category: 'rsa', + name: 'rsa.misc.cs_streams', + type: 'keyword', + }, + 'rsa.misc.cs_targetmodule': { + category: 'rsa', + name: 'rsa.misc.cs_targetmodule', + type: 'keyword', + }, + 'rsa.misc.cs_v6nxthop': { + category: 'rsa', + name: 'rsa.misc.cs_v6nxthop', + type: 'keyword', + }, + 'rsa.misc.cs_whois_server': { + category: 'rsa', + name: 'rsa.misc.cs_whois_server', + type: 'keyword', + }, + 'rsa.misc.cs_yararesult': { + category: 'rsa', + name: 'rsa.misc.cs_yararesult', + type: 'keyword', + }, + 'rsa.misc.description': { + category: 'rsa', + name: 'rsa.misc.description', + type: 'keyword', + }, + 'rsa.misc.devvendor': { + category: 'rsa', + name: 'rsa.misc.devvendor', + type: 'keyword', + }, + 'rsa.misc.distance': { + category: 'rsa', + name: 'rsa.misc.distance', + type: 'keyword', + }, + 'rsa.misc.dstburb': { + category: 'rsa', + name: 'rsa.misc.dstburb', + type: 'keyword', + }, + 'rsa.misc.edomain': { + category: 'rsa', + name: 'rsa.misc.edomain', + type: 'keyword', + }, + 'rsa.misc.edomaub': { + category: 'rsa', + name: 'rsa.misc.edomaub', + type: 'keyword', + }, + 'rsa.misc.euid': { + category: 'rsa', + name: 'rsa.misc.euid', + type: 'keyword', + }, + 'rsa.misc.facility': { + category: 'rsa', + name: 'rsa.misc.facility', + type: 'keyword', + }, + 'rsa.misc.finterface': { + category: 'rsa', + name: 'rsa.misc.finterface', + type: 'keyword', + }, + 'rsa.misc.flags': { + category: 'rsa', + name: 'rsa.misc.flags', + type: 'keyword', + }, + 'rsa.misc.gaddr': { + category: 'rsa', + name: 'rsa.misc.gaddr', + type: 'keyword', + }, + 'rsa.misc.id3': { + category: 'rsa', + name: 'rsa.misc.id3', + type: 'keyword', + }, + 'rsa.misc.im_buddyname': { + category: 'rsa', + name: 'rsa.misc.im_buddyname', + type: 'keyword', + }, + 'rsa.misc.im_croomid': { + category: 'rsa', + name: 'rsa.misc.im_croomid', + type: 'keyword', + }, + 'rsa.misc.im_croomtype': { + category: 'rsa', + name: 'rsa.misc.im_croomtype', + type: 'keyword', + }, + 'rsa.misc.im_members': { + category: 'rsa', + name: 'rsa.misc.im_members', + type: 'keyword', + }, + 'rsa.misc.im_username': { + category: 'rsa', + name: 'rsa.misc.im_username', + type: 'keyword', + }, + 'rsa.misc.ipkt': { + category: 'rsa', + name: 'rsa.misc.ipkt', + type: 'keyword', + }, + 'rsa.misc.ipscat': { + category: 'rsa', + name: 'rsa.misc.ipscat', + type: 'keyword', + }, + 'rsa.misc.ipspri': { + category: 'rsa', + name: 'rsa.misc.ipspri', + type: 'keyword', + }, + 'rsa.misc.latitude': { + category: 'rsa', + name: 'rsa.misc.latitude', + type: 'keyword', + }, + 'rsa.misc.linenum': { + category: 'rsa', + name: 'rsa.misc.linenum', + type: 'keyword', + }, + 'rsa.misc.list_name': { + category: 'rsa', + name: 'rsa.misc.list_name', + type: 'keyword', + }, + 'rsa.misc.load_data': { + category: 'rsa', + name: 'rsa.misc.load_data', + type: 'keyword', + }, + 'rsa.misc.location_floor': { + category: 'rsa', + name: 'rsa.misc.location_floor', + type: 'keyword', + }, + 'rsa.misc.location_mark': { + category: 'rsa', + name: 'rsa.misc.location_mark', + type: 'keyword', + }, + 'rsa.misc.log_id': { + category: 'rsa', + name: 'rsa.misc.log_id', + type: 'keyword', + }, + 'rsa.misc.log_type': { + category: 'rsa', + name: 'rsa.misc.log_type', + type: 'keyword', + }, + 'rsa.misc.logid': { + category: 'rsa', + name: 'rsa.misc.logid', + type: 'keyword', + }, + 'rsa.misc.logip': { + category: 'rsa', + name: 'rsa.misc.logip', + type: 'keyword', + }, + 'rsa.misc.logname': { + category: 'rsa', + name: 'rsa.misc.logname', + type: 'keyword', + }, + 'rsa.misc.longitude': { + category: 'rsa', + name: 'rsa.misc.longitude', + type: 'keyword', + }, + 'rsa.misc.lport': { + category: 'rsa', + name: 'rsa.misc.lport', + type: 'keyword', + }, + 'rsa.misc.mbug_data': { + category: 'rsa', + name: 'rsa.misc.mbug_data', + type: 'keyword', + }, + 'rsa.misc.misc_name': { + category: 'rsa', + name: 'rsa.misc.misc_name', + type: 'keyword', + }, + 'rsa.misc.msg_type': { + category: 'rsa', + name: 'rsa.misc.msg_type', + type: 'keyword', + }, + 'rsa.misc.msgid': { + category: 'rsa', + name: 'rsa.misc.msgid', + type: 'keyword', + }, + 'rsa.misc.netsessid': { + category: 'rsa', + name: 'rsa.misc.netsessid', + type: 'keyword', + }, + 'rsa.misc.num': { + category: 'rsa', + name: 'rsa.misc.num', + type: 'keyword', + }, + 'rsa.misc.number1': { + category: 'rsa', + name: 'rsa.misc.number1', + type: 'keyword', + }, + 'rsa.misc.number2': { + category: 'rsa', + name: 'rsa.misc.number2', + type: 'keyword', + }, + 'rsa.misc.nwwn': { + category: 'rsa', + name: 'rsa.misc.nwwn', + type: 'keyword', + }, + 'rsa.misc.object': { + category: 'rsa', + name: 'rsa.misc.object', + type: 'keyword', + }, + 'rsa.misc.operation': { + category: 'rsa', + name: 'rsa.misc.operation', + type: 'keyword', + }, + 'rsa.misc.opkt': { + category: 'rsa', + name: 'rsa.misc.opkt', + type: 'keyword', + }, + 'rsa.misc.orig_from': { + category: 'rsa', + name: 'rsa.misc.orig_from', + type: 'keyword', + }, + 'rsa.misc.owner_id': { + category: 'rsa', + name: 'rsa.misc.owner_id', + type: 'keyword', + }, + 'rsa.misc.p_action': { + category: 'rsa', + name: 'rsa.misc.p_action', + type: 'keyword', + }, + 'rsa.misc.p_filter': { + category: 'rsa', + name: 'rsa.misc.p_filter', + type: 'keyword', + }, + 'rsa.misc.p_group_object': { + category: 'rsa', + name: 'rsa.misc.p_group_object', + type: 'keyword', + }, + 'rsa.misc.p_id': { + category: 'rsa', + name: 'rsa.misc.p_id', + type: 'keyword', + }, + 'rsa.misc.p_msgid1': { + category: 'rsa', + name: 'rsa.misc.p_msgid1', + type: 'keyword', + }, + 'rsa.misc.p_msgid2': { + category: 'rsa', + name: 'rsa.misc.p_msgid2', + type: 'keyword', + }, + 'rsa.misc.p_result1': { + category: 'rsa', + name: 'rsa.misc.p_result1', + type: 'keyword', + }, + 'rsa.misc.password_chg': { + category: 'rsa', + name: 'rsa.misc.password_chg', + type: 'keyword', + }, + 'rsa.misc.password_expire': { + category: 'rsa', + name: 'rsa.misc.password_expire', + type: 'keyword', + }, + 'rsa.misc.permgranted': { + category: 'rsa', + name: 'rsa.misc.permgranted', + type: 'keyword', + }, + 'rsa.misc.permwanted': { + category: 'rsa', + name: 'rsa.misc.permwanted', + type: 'keyword', + }, + 'rsa.misc.pgid': { + category: 'rsa', + name: 'rsa.misc.pgid', + type: 'keyword', + }, + 'rsa.misc.policyUUID': { + category: 'rsa', + name: 'rsa.misc.policyUUID', + type: 'keyword', + }, + 'rsa.misc.prog_asp_num': { + category: 'rsa', + name: 'rsa.misc.prog_asp_num', + type: 'keyword', + }, + 'rsa.misc.program': { + category: 'rsa', + name: 'rsa.misc.program', + type: 'keyword', + }, + 'rsa.misc.real_data': { + category: 'rsa', + name: 'rsa.misc.real_data', + type: 'keyword', + }, + 'rsa.misc.rec_asp_device': { + category: 'rsa', + name: 'rsa.misc.rec_asp_device', + type: 'keyword', + }, + 'rsa.misc.rec_asp_num': { + category: 'rsa', + name: 'rsa.misc.rec_asp_num', + type: 'keyword', + }, + 'rsa.misc.rec_library': { + category: 'rsa', + name: 'rsa.misc.rec_library', + type: 'keyword', + }, + 'rsa.misc.recordnum': { + category: 'rsa', + name: 'rsa.misc.recordnum', + type: 'keyword', + }, + 'rsa.misc.ruid': { + category: 'rsa', + name: 'rsa.misc.ruid', + type: 'keyword', + }, + 'rsa.misc.sburb': { + category: 'rsa', + name: 'rsa.misc.sburb', + type: 'keyword', + }, + 'rsa.misc.sdomain_fld': { + category: 'rsa', + name: 'rsa.misc.sdomain_fld', + type: 'keyword', + }, + 'rsa.misc.sec': { + category: 'rsa', + name: 'rsa.misc.sec', + type: 'keyword', + }, + 'rsa.misc.sensorname': { + category: 'rsa', + name: 'rsa.misc.sensorname', + type: 'keyword', + }, + 'rsa.misc.seqnum': { + category: 'rsa', + name: 'rsa.misc.seqnum', + type: 'keyword', + }, + 'rsa.misc.session': { + category: 'rsa', + name: 'rsa.misc.session', + type: 'keyword', + }, + 'rsa.misc.sessiontype': { + category: 'rsa', + name: 'rsa.misc.sessiontype', + type: 'keyword', + }, + 'rsa.misc.sigUUID': { + category: 'rsa', + name: 'rsa.misc.sigUUID', + type: 'keyword', + }, + 'rsa.misc.spi': { + category: 'rsa', + name: 'rsa.misc.spi', + type: 'keyword', + }, + 'rsa.misc.srcburb': { + category: 'rsa', + name: 'rsa.misc.srcburb', + type: 'keyword', + }, + 'rsa.misc.srcdom': { + category: 'rsa', + name: 'rsa.misc.srcdom', + type: 'keyword', + }, + 'rsa.misc.srcservice': { + category: 'rsa', + name: 'rsa.misc.srcservice', + type: 'keyword', + }, + 'rsa.misc.state': { + category: 'rsa', + name: 'rsa.misc.state', + type: 'keyword', + }, + 'rsa.misc.status1': { + category: 'rsa', + name: 'rsa.misc.status1', + type: 'keyword', + }, + 'rsa.misc.svcno': { + category: 'rsa', + name: 'rsa.misc.svcno', + type: 'keyword', + }, + 'rsa.misc.system': { + category: 'rsa', + name: 'rsa.misc.system', + type: 'keyword', + }, + 'rsa.misc.tbdstr1': { + category: 'rsa', + name: 'rsa.misc.tbdstr1', + type: 'keyword', + }, + 'rsa.misc.tgtdom': { + category: 'rsa', + name: 'rsa.misc.tgtdom', + type: 'keyword', + }, + 'rsa.misc.tgtdomain': { + category: 'rsa', + name: 'rsa.misc.tgtdomain', + type: 'keyword', + }, + 'rsa.misc.threshold': { + category: 'rsa', + name: 'rsa.misc.threshold', + type: 'keyword', + }, + 'rsa.misc.type1': { + category: 'rsa', + name: 'rsa.misc.type1', + type: 'keyword', + }, + 'rsa.misc.udb_class': { + category: 'rsa', + name: 'rsa.misc.udb_class', + type: 'keyword', + }, + 'rsa.misc.url_fld': { + category: 'rsa', + name: 'rsa.misc.url_fld', + type: 'keyword', + }, + 'rsa.misc.user_div': { + category: 'rsa', + name: 'rsa.misc.user_div', + type: 'keyword', + }, + 'rsa.misc.userid': { + category: 'rsa', + name: 'rsa.misc.userid', + type: 'keyword', + }, + 'rsa.misc.username_fld': { + category: 'rsa', + name: 'rsa.misc.username_fld', + type: 'keyword', + }, + 'rsa.misc.utcstamp': { + category: 'rsa', + name: 'rsa.misc.utcstamp', + type: 'keyword', + }, + 'rsa.misc.v_instafname': { + category: 'rsa', + name: 'rsa.misc.v_instafname', + type: 'keyword', + }, + 'rsa.misc.virt_data': { + category: 'rsa', + name: 'rsa.misc.virt_data', + type: 'keyword', + }, + 'rsa.misc.vpnid': { + category: 'rsa', + name: 'rsa.misc.vpnid', + type: 'keyword', + }, + 'rsa.misc.autorun_type': { + category: 'rsa', + description: 'This is used to capture Auto Run type', + name: 'rsa.misc.autorun_type', + type: 'keyword', + }, + 'rsa.misc.cc_number': { + category: 'rsa', + description: 'Valid Credit Card Numbers only', + name: 'rsa.misc.cc_number', + type: 'long', + }, + 'rsa.misc.content': { + category: 'rsa', + description: 'This key captures the content type from protocol headers', + name: 'rsa.misc.content', + type: 'keyword', + }, + 'rsa.misc.ein_number': { + category: 'rsa', + description: 'Employee Identification Numbers only', + name: 'rsa.misc.ein_number', + type: 'long', + }, + 'rsa.misc.found': { + category: 'rsa', + description: 'This is used to capture the results of regex match', + name: 'rsa.misc.found', + type: 'keyword', + }, + 'rsa.misc.language': { + category: 'rsa', + description: 'This is used to capture list of languages the client support and what it prefers', + name: 'rsa.misc.language', + type: 'keyword', + }, + 'rsa.misc.lifetime': { + category: 'rsa', + description: 'This key is used to capture the session lifetime in seconds.', + name: 'rsa.misc.lifetime', + type: 'long', + }, + 'rsa.misc.link': { + category: 'rsa', + description: + 'This key is used to link the sessions together. This key should never be used to parse Meta data from a session (Logs/Packets) Directly, this is a Reserved key in NetWitness', + name: 'rsa.misc.link', + type: 'keyword', + }, + 'rsa.misc.match': { + category: 'rsa', + description: 'This key is for regex match name from search.ini', + name: 'rsa.misc.match', + type: 'keyword', + }, + 'rsa.misc.param_dst': { + category: 'rsa', + description: 'This key captures the command line/launch argument of the target process or file', + name: 'rsa.misc.param_dst', + type: 'keyword', + }, + 'rsa.misc.param_src': { + category: 'rsa', + description: 'This key captures source parameter', + name: 'rsa.misc.param_src', + type: 'keyword', + }, + 'rsa.misc.search_text': { + category: 'rsa', + description: 'This key captures the Search Text used', + name: 'rsa.misc.search_text', + type: 'keyword', + }, + 'rsa.misc.sig_name': { + category: 'rsa', + description: 'This key is used to capture the Signature Name only.', + name: 'rsa.misc.sig_name', + type: 'keyword', + }, + 'rsa.misc.snmp_value': { + category: 'rsa', + description: 'SNMP set request value', + name: 'rsa.misc.snmp_value', + type: 'keyword', + }, + 'rsa.misc.streams': { + category: 'rsa', + description: 'This key captures number of streams in session', + name: 'rsa.misc.streams', + type: 'long', + }, + 'rsa.db.index': { + category: 'rsa', + description: 'This key captures IndexID of the index.', + name: 'rsa.db.index', + type: 'keyword', + }, + 'rsa.db.instance': { + category: 'rsa', + description: 'This key is used to capture the database server instance name', + name: 'rsa.db.instance', + type: 'keyword', + }, + 'rsa.db.database': { + category: 'rsa', + description: + 'This key is used to capture the name of a database or an instance as seen in a session', + name: 'rsa.db.database', + type: 'keyword', + }, + 'rsa.db.transact_id': { + category: 'rsa', + description: 'This key captures the SQL transantion ID of the current session', + name: 'rsa.db.transact_id', + type: 'keyword', + }, + 'rsa.db.permissions': { + category: 'rsa', + description: 'This key captures permission or privilege level assigned to a resource.', + name: 'rsa.db.permissions', + type: 'keyword', + }, + 'rsa.db.table_name': { + category: 'rsa', + description: 'This key is used to capture the table name', + name: 'rsa.db.table_name', + type: 'keyword', + }, + 'rsa.db.db_id': { + category: 'rsa', + description: 'This key is used to capture the unique identifier for a database', + name: 'rsa.db.db_id', + type: 'keyword', + }, + 'rsa.db.db_pid': { + category: 'rsa', + description: 'This key captures the process id of a connection with database server', + name: 'rsa.db.db_pid', + type: 'long', + }, + 'rsa.db.lread': { + category: 'rsa', + description: 'This key is used for the number of logical reads', + name: 'rsa.db.lread', + type: 'long', + }, + 'rsa.db.lwrite': { + category: 'rsa', + description: 'This key is used for the number of logical writes', + name: 'rsa.db.lwrite', + type: 'long', + }, + 'rsa.db.pread': { + category: 'rsa', + description: 'This key is used for the number of physical writes', + name: 'rsa.db.pread', + type: 'long', + }, + 'rsa.network.alias_host': { + category: 'rsa', + description: + 'This key should be used when the source or destination context of a hostname is not clear.Also it captures the Device Hostname. Any Hostname that isnt ad.computer.', + name: 'rsa.network.alias_host', + type: 'keyword', + }, + 'rsa.network.domain': { + category: 'rsa', + name: 'rsa.network.domain', + type: 'keyword', + }, + 'rsa.network.host_dst': { + category: 'rsa', + description: 'This key should only be used when it’s a Destination Hostname', + name: 'rsa.network.host_dst', + type: 'keyword', + }, + 'rsa.network.network_service': { + category: 'rsa', + description: 'This is used to capture layer 7 protocols/service names', + name: 'rsa.network.network_service', + type: 'keyword', + }, + 'rsa.network.interface': { + category: 'rsa', + description: + 'This key should be used when the source or destination context of an interface is not clear', + name: 'rsa.network.interface', + type: 'keyword', + }, + 'rsa.network.network_port': { + category: 'rsa', + description: + 'Deprecated, use port. NOTE: There is a type discrepancy as currently used, TM: Int32, INDEX: UInt64 (why neither chose the correct UInt16?!)', + name: 'rsa.network.network_port', + type: 'long', + }, + 'rsa.network.eth_host': { + category: 'rsa', + description: 'Deprecated, use alias.mac', + name: 'rsa.network.eth_host', + type: 'keyword', + }, + 'rsa.network.sinterface': { + category: 'rsa', + description: 'This key should only be used when it’s a Source Interface', + name: 'rsa.network.sinterface', + type: 'keyword', + }, + 'rsa.network.dinterface': { + category: 'rsa', + description: 'This key should only be used when it’s a Destination Interface', + name: 'rsa.network.dinterface', + type: 'keyword', + }, + 'rsa.network.vlan': { + category: 'rsa', + description: 'This key should only be used to capture the ID of the Virtual LAN', + name: 'rsa.network.vlan', + type: 'long', + }, + 'rsa.network.zone_src': { + category: 'rsa', + description: 'This key should only be used when it’s a Source Zone.', + name: 'rsa.network.zone_src', + type: 'keyword', + }, + 'rsa.network.zone': { + category: 'rsa', + description: + 'This key should be used when the source or destination context of a Zone is not clear', + name: 'rsa.network.zone', + type: 'keyword', + }, + 'rsa.network.zone_dst': { + category: 'rsa', + description: 'This key should only be used when it’s a Destination Zone.', + name: 'rsa.network.zone_dst', + type: 'keyword', + }, + 'rsa.network.gateway': { + category: 'rsa', + description: 'This key is used to capture the IP Address of the gateway', + name: 'rsa.network.gateway', + type: 'keyword', + }, + 'rsa.network.icmp_type': { + category: 'rsa', + description: 'This key is used to capture the ICMP type only', + name: 'rsa.network.icmp_type', + type: 'long', + }, + 'rsa.network.mask': { + category: 'rsa', + description: 'This key is used to capture the device network IPmask.', + name: 'rsa.network.mask', + type: 'keyword', + }, + 'rsa.network.icmp_code': { + category: 'rsa', + description: 'This key is used to capture the ICMP code only', + name: 'rsa.network.icmp_code', + type: 'long', + }, + 'rsa.network.protocol_detail': { + category: 'rsa', + description: 'This key should be used to capture additional protocol information', + name: 'rsa.network.protocol_detail', + type: 'keyword', + }, + 'rsa.network.dmask': { + category: 'rsa', + description: 'This key is used for Destionation Device network mask', + name: 'rsa.network.dmask', + type: 'keyword', + }, + 'rsa.network.port': { + category: 'rsa', + description: + 'This key should only be used to capture a Network Port when the directionality is not clear', + name: 'rsa.network.port', + type: 'long', + }, + 'rsa.network.smask': { + category: 'rsa', + description: 'This key is used for capturing source Network Mask', + name: 'rsa.network.smask', + type: 'keyword', + }, + 'rsa.network.netname': { + category: 'rsa', + description: + 'This key is used to capture the network name associated with an IP range. This is configured by the end user.', + name: 'rsa.network.netname', + type: 'keyword', + }, + 'rsa.network.paddr': { + category: 'rsa', + description: 'Deprecated', + name: 'rsa.network.paddr', + type: 'ip', + }, + 'rsa.network.faddr': { + category: 'rsa', + name: 'rsa.network.faddr', + type: 'keyword', + }, + 'rsa.network.lhost': { + category: 'rsa', + name: 'rsa.network.lhost', + type: 'keyword', + }, + 'rsa.network.origin': { + category: 'rsa', + name: 'rsa.network.origin', + type: 'keyword', + }, + 'rsa.network.remote_domain_id': { + category: 'rsa', + name: 'rsa.network.remote_domain_id', + type: 'keyword', + }, + 'rsa.network.addr': { + category: 'rsa', + name: 'rsa.network.addr', + type: 'keyword', + }, + 'rsa.network.dns_a_record': { + category: 'rsa', + name: 'rsa.network.dns_a_record', + type: 'keyword', + }, + 'rsa.network.dns_ptr_record': { + category: 'rsa', + name: 'rsa.network.dns_ptr_record', + type: 'keyword', + }, + 'rsa.network.fhost': { + category: 'rsa', + name: 'rsa.network.fhost', + type: 'keyword', + }, + 'rsa.network.fport': { + category: 'rsa', + name: 'rsa.network.fport', + type: 'keyword', + }, + 'rsa.network.laddr': { + category: 'rsa', + name: 'rsa.network.laddr', + type: 'keyword', + }, + 'rsa.network.linterface': { + category: 'rsa', + name: 'rsa.network.linterface', + type: 'keyword', + }, + 'rsa.network.phost': { + category: 'rsa', + name: 'rsa.network.phost', + type: 'keyword', + }, + 'rsa.network.ad_computer_dst': { + category: 'rsa', + description: 'Deprecated, use host.dst', + name: 'rsa.network.ad_computer_dst', + type: 'keyword', + }, + 'rsa.network.eth_type': { + category: 'rsa', + description: 'This key is used to capture Ethernet Type, Used for Layer 3 Protocols Only', + name: 'rsa.network.eth_type', + type: 'long', + }, + 'rsa.network.ip_proto': { + category: 'rsa', + description: + 'This key should be used to capture the Protocol number, all the protocol nubers are converted into string in UI', + name: 'rsa.network.ip_proto', + type: 'long', + }, + 'rsa.network.dns_cname_record': { + category: 'rsa', + name: 'rsa.network.dns_cname_record', + type: 'keyword', + }, + 'rsa.network.dns_id': { + category: 'rsa', + name: 'rsa.network.dns_id', + type: 'keyword', + }, + 'rsa.network.dns_opcode': { + category: 'rsa', + name: 'rsa.network.dns_opcode', + type: 'keyword', + }, + 'rsa.network.dns_resp': { + category: 'rsa', + name: 'rsa.network.dns_resp', + type: 'keyword', + }, + 'rsa.network.dns_type': { + category: 'rsa', + name: 'rsa.network.dns_type', + type: 'keyword', + }, + 'rsa.network.domain1': { + category: 'rsa', + name: 'rsa.network.domain1', + type: 'keyword', + }, + 'rsa.network.host_type': { + category: 'rsa', + name: 'rsa.network.host_type', + type: 'keyword', + }, + 'rsa.network.packet_length': { + category: 'rsa', + name: 'rsa.network.packet_length', + type: 'keyword', + }, + 'rsa.network.host_orig': { + category: 'rsa', + description: + 'This is used to capture the original hostname in case of a Forwarding Agent or a Proxy in between.', + name: 'rsa.network.host_orig', + type: 'keyword', + }, + 'rsa.network.rpayload': { + category: 'rsa', + description: + 'This key is used to capture the total number of payload bytes seen in the retransmitted packets.', + name: 'rsa.network.rpayload', + type: 'keyword', + }, + 'rsa.network.vlan_name': { + category: 'rsa', + description: 'This key should only be used to capture the name of the Virtual LAN', + name: 'rsa.network.vlan_name', + type: 'keyword', + }, + 'rsa.investigations.ec_activity': { + category: 'rsa', + description: 'This key captures the particular event activity(Ex:Logoff)', + name: 'rsa.investigations.ec_activity', + type: 'keyword', + }, + 'rsa.investigations.ec_theme': { + category: 'rsa', + description: 'This key captures the Theme of a particular Event(Ex:Authentication)', + name: 'rsa.investigations.ec_theme', + type: 'keyword', + }, + 'rsa.investigations.ec_subject': { + category: 'rsa', + description: 'This key captures the Subject of a particular Event(Ex:User)', + name: 'rsa.investigations.ec_subject', + type: 'keyword', + }, + 'rsa.investigations.ec_outcome': { + category: 'rsa', + description: 'This key captures the outcome of a particular Event(Ex:Success)', + name: 'rsa.investigations.ec_outcome', + type: 'keyword', + }, + 'rsa.investigations.event_cat': { + category: 'rsa', + description: 'This key captures the Event category number', + name: 'rsa.investigations.event_cat', + type: 'long', + }, + 'rsa.investigations.event_cat_name': { + category: 'rsa', + description: 'This key captures the event category name corresponding to the event cat code', + name: 'rsa.investigations.event_cat_name', + type: 'keyword', + }, + 'rsa.investigations.event_vcat': { + category: 'rsa', + description: + 'This is a vendor supplied category. This should be used in situations where the vendor has adopted their own event_category taxonomy.', + name: 'rsa.investigations.event_vcat', + type: 'keyword', + }, + 'rsa.investigations.analysis_file': { + category: 'rsa', + description: + 'This is used to capture all indicators used in a File Analysis. This key should be used to capture an analysis of a file', + name: 'rsa.investigations.analysis_file', + type: 'keyword', + }, + 'rsa.investigations.analysis_service': { + category: 'rsa', + description: + 'This is used to capture all indicators used in a Service Analysis. This key should be used to capture an analysis of a service', + name: 'rsa.investigations.analysis_service', + type: 'keyword', + }, + 'rsa.investigations.analysis_session': { + category: 'rsa', + description: + 'This is used to capture all indicators used for a Session Analysis. This key should be used to capture an analysis of a session', + name: 'rsa.investigations.analysis_session', + type: 'keyword', + }, + 'rsa.investigations.boc': { + category: 'rsa', + description: 'This is used to capture behaviour of compromise', + name: 'rsa.investigations.boc', + type: 'keyword', + }, + 'rsa.investigations.eoc': { + category: 'rsa', + description: 'This is used to capture Enablers of Compromise', + name: 'rsa.investigations.eoc', + type: 'keyword', + }, + 'rsa.investigations.inv_category': { + category: 'rsa', + description: 'This used to capture investigation category', + name: 'rsa.investigations.inv_category', + type: 'keyword', + }, + 'rsa.investigations.inv_context': { + category: 'rsa', + description: 'This used to capture investigation context', + name: 'rsa.investigations.inv_context', + type: 'keyword', + }, + 'rsa.investigations.ioc': { + category: 'rsa', + description: 'This is key capture indicator of compromise', + name: 'rsa.investigations.ioc', + type: 'keyword', + }, + 'rsa.counters.dclass_c1': { + category: 'rsa', + description: + 'This is a generic counter key that should be used with the label dclass.c1.str only', + name: 'rsa.counters.dclass_c1', + type: 'long', + }, + 'rsa.counters.dclass_c2': { + category: 'rsa', + description: + 'This is a generic counter key that should be used with the label dclass.c2.str only', + name: 'rsa.counters.dclass_c2', + type: 'long', + }, + 'rsa.counters.event_counter': { + category: 'rsa', + description: 'This is used to capture the number of times an event repeated', + name: 'rsa.counters.event_counter', + type: 'long', + }, + 'rsa.counters.dclass_r1': { + category: 'rsa', + description: + 'This is a generic ratio key that should be used with the label dclass.r1.str only', + name: 'rsa.counters.dclass_r1', + type: 'keyword', + }, + 'rsa.counters.dclass_c3': { + category: 'rsa', + description: + 'This is a generic counter key that should be used with the label dclass.c3.str only', + name: 'rsa.counters.dclass_c3', + type: 'long', + }, + 'rsa.counters.dclass_c1_str': { + category: 'rsa', + description: + 'This is a generic counter string key that should be used with the label dclass.c1 only', + name: 'rsa.counters.dclass_c1_str', + type: 'keyword', + }, + 'rsa.counters.dclass_c2_str': { + category: 'rsa', + description: + 'This is a generic counter string key that should be used with the label dclass.c2 only', + name: 'rsa.counters.dclass_c2_str', + type: 'keyword', + }, + 'rsa.counters.dclass_r1_str': { + category: 'rsa', + description: + 'This is a generic ratio string key that should be used with the label dclass.r1 only', + name: 'rsa.counters.dclass_r1_str', + type: 'keyword', + }, + 'rsa.counters.dclass_r2': { + category: 'rsa', + description: + 'This is a generic ratio key that should be used with the label dclass.r2.str only', + name: 'rsa.counters.dclass_r2', + type: 'keyword', + }, + 'rsa.counters.dclass_c3_str': { + category: 'rsa', + description: + 'This is a generic counter string key that should be used with the label dclass.c3 only', + name: 'rsa.counters.dclass_c3_str', + type: 'keyword', + }, + 'rsa.counters.dclass_r3': { + category: 'rsa', + description: + 'This is a generic ratio key that should be used with the label dclass.r3.str only', + name: 'rsa.counters.dclass_r3', + type: 'keyword', + }, + 'rsa.counters.dclass_r2_str': { + category: 'rsa', + description: + 'This is a generic ratio string key that should be used with the label dclass.r2 only', + name: 'rsa.counters.dclass_r2_str', + type: 'keyword', + }, + 'rsa.counters.dclass_r3_str': { + category: 'rsa', + description: + 'This is a generic ratio string key that should be used with the label dclass.r3 only', + name: 'rsa.counters.dclass_r3_str', + type: 'keyword', + }, + 'rsa.identity.auth_method': { + category: 'rsa', + description: 'This key is used to capture authentication methods used only', + name: 'rsa.identity.auth_method', + type: 'keyword', + }, + 'rsa.identity.user_role': { + category: 'rsa', + description: 'This key is used to capture the Role of a user only', + name: 'rsa.identity.user_role', + type: 'keyword', + }, + 'rsa.identity.dn': { + category: 'rsa', + description: 'X.500 (LDAP) Distinguished Name', + name: 'rsa.identity.dn', + type: 'keyword', + }, + 'rsa.identity.logon_type': { + category: 'rsa', + description: 'This key is used to capture the type of logon method used.', + name: 'rsa.identity.logon_type', + type: 'keyword', + }, + 'rsa.identity.profile': { + category: 'rsa', + description: 'This key is used to capture the user profile', + name: 'rsa.identity.profile', + type: 'keyword', + }, + 'rsa.identity.accesses': { + category: 'rsa', + description: 'This key is used to capture actual privileges used in accessing an object', + name: 'rsa.identity.accesses', + type: 'keyword', + }, + 'rsa.identity.realm': { + category: 'rsa', + description: 'Radius realm or similar grouping of accounts', + name: 'rsa.identity.realm', + type: 'keyword', + }, + 'rsa.identity.user_sid_dst': { + category: 'rsa', + description: 'This key captures Destination User Session ID', + name: 'rsa.identity.user_sid_dst', + type: 'keyword', + }, + 'rsa.identity.dn_src': { + category: 'rsa', + description: + 'An X.500 (LDAP) Distinguished name that is used in a context that indicates a Source dn', + name: 'rsa.identity.dn_src', + type: 'keyword', + }, + 'rsa.identity.org': { + category: 'rsa', + description: 'This key captures the User organization', + name: 'rsa.identity.org', + type: 'keyword', + }, + 'rsa.identity.dn_dst': { + category: 'rsa', + description: + 'An X.500 (LDAP) Distinguished name that used in a context that indicates a Destination dn', + name: 'rsa.identity.dn_dst', + type: 'keyword', + }, + 'rsa.identity.firstname': { + category: 'rsa', + description: + 'This key is for First Names only, this is used for Healthcare predominantly to capture Patients information', + name: 'rsa.identity.firstname', + type: 'keyword', + }, + 'rsa.identity.lastname': { + category: 'rsa', + description: + 'This key is for Last Names only, this is used for Healthcare predominantly to capture Patients information', + name: 'rsa.identity.lastname', + type: 'keyword', + }, + 'rsa.identity.user_dept': { + category: 'rsa', + description: "User's Department Names only", + name: 'rsa.identity.user_dept', + type: 'keyword', + }, + 'rsa.identity.user_sid_src': { + category: 'rsa', + description: 'This key captures Source User Session ID', + name: 'rsa.identity.user_sid_src', + type: 'keyword', + }, + 'rsa.identity.federated_sp': { + category: 'rsa', + description: + 'This key is the Federated Service Provider. This is the application requesting authentication.', + name: 'rsa.identity.federated_sp', + type: 'keyword', + }, + 'rsa.identity.federated_idp': { + category: 'rsa', + description: + 'This key is the federated Identity Provider. This is the server providing the authentication.', + name: 'rsa.identity.federated_idp', + type: 'keyword', + }, + 'rsa.identity.logon_type_desc': { + category: 'rsa', + description: + "This key is used to capture the textual description of an integer logon type as stored in the meta key 'logon.type'.", + name: 'rsa.identity.logon_type_desc', + type: 'keyword', + }, + 'rsa.identity.middlename': { + category: 'rsa', + description: + 'This key is for Middle Names only, this is used for Healthcare predominantly to capture Patients information', + name: 'rsa.identity.middlename', + type: 'keyword', + }, + 'rsa.identity.password': { + category: 'rsa', + description: 'This key is for Passwords seen in any session, plain text or encrypted', + name: 'rsa.identity.password', + type: 'keyword', + }, + 'rsa.identity.host_role': { + category: 'rsa', + description: 'This key should only be used to capture the role of a Host Machine', + name: 'rsa.identity.host_role', + type: 'keyword', + }, + 'rsa.identity.ldap': { + category: 'rsa', + description: + 'This key is for Uninterpreted LDAP values. Ldap Values that don’t have a clear query or response context', + name: 'rsa.identity.ldap', + type: 'keyword', + }, + 'rsa.identity.ldap_query': { + category: 'rsa', + description: 'This key is the Search criteria from an LDAP search', + name: 'rsa.identity.ldap_query', + type: 'keyword', + }, + 'rsa.identity.ldap_response': { + category: 'rsa', + description: 'This key is to capture Results from an LDAP search', + name: 'rsa.identity.ldap_response', + type: 'keyword', + }, + 'rsa.identity.owner': { + category: 'rsa', + description: + 'This is used to capture username the process or service is running as, the author of the task', + name: 'rsa.identity.owner', + type: 'keyword', + }, + 'rsa.identity.service_account': { + category: 'rsa', + description: + 'This key is a windows specific key, used for capturing name of the account a service (referenced in the event) is running under. Legacy Usage', + name: 'rsa.identity.service_account', + type: 'keyword', + }, + 'rsa.email.email_dst': { + category: 'rsa', + description: + 'This key is used to capture the Destination email address only, when the destination context is not clear use email', + name: 'rsa.email.email_dst', + type: 'keyword', + }, + 'rsa.email.email_src': { + category: 'rsa', + description: + 'This key is used to capture the source email address only, when the source context is not clear use email', + name: 'rsa.email.email_src', + type: 'keyword', + }, + 'rsa.email.subject': { + category: 'rsa', + description: 'This key is used to capture the subject string from an Email only.', + name: 'rsa.email.subject', + type: 'keyword', + }, + 'rsa.email.email': { + category: 'rsa', + description: + 'This key is used to capture a generic email address where the source or destination context is not clear', + name: 'rsa.email.email', + type: 'keyword', + }, + 'rsa.email.trans_from': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.email.trans_from', + type: 'keyword', + }, + 'rsa.email.trans_to': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.email.trans_to', + type: 'keyword', + }, + 'rsa.file.privilege': { + category: 'rsa', + description: 'Deprecated, use permissions', + name: 'rsa.file.privilege', + type: 'keyword', + }, + 'rsa.file.attachment': { + category: 'rsa', + description: 'This key captures the attachment file name', + name: 'rsa.file.attachment', + type: 'keyword', + }, + 'rsa.file.filesystem': { + category: 'rsa', + name: 'rsa.file.filesystem', + type: 'keyword', + }, + 'rsa.file.binary': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.file.binary', + type: 'keyword', + }, + 'rsa.file.filename_dst': { + category: 'rsa', + description: 'This is used to capture name of the file targeted by the action', + name: 'rsa.file.filename_dst', + type: 'keyword', + }, + 'rsa.file.filename_src': { + category: 'rsa', + description: + 'This is used to capture name of the parent filename, the file which performed the action', + name: 'rsa.file.filename_src', + type: 'keyword', + }, + 'rsa.file.filename_tmp': { + category: 'rsa', + name: 'rsa.file.filename_tmp', + type: 'keyword', + }, + 'rsa.file.directory_dst': { + category: 'rsa', + description: + 'This key is used to capture the directory of the target process or file', + name: 'rsa.file.directory_dst', + type: 'keyword', + }, + 'rsa.file.directory_src': { + category: 'rsa', + description: 'This key is used to capture the directory of the source process or file', + name: 'rsa.file.directory_src', + type: 'keyword', + }, + 'rsa.file.file_entropy': { + category: 'rsa', + description: 'This is used to capture entropy vale of a file', + name: 'rsa.file.file_entropy', + type: 'double', + }, + 'rsa.file.file_vendor': { + category: 'rsa', + description: 'This is used to capture Company name of file located in version_info', + name: 'rsa.file.file_vendor', + type: 'keyword', + }, + 'rsa.file.task_name': { + category: 'rsa', + description: 'This is used to capture name of the task', + name: 'rsa.file.task_name', + type: 'keyword', + }, + 'rsa.web.fqdn': { + category: 'rsa', + description: 'Fully Qualified Domain Names', + name: 'rsa.web.fqdn', + type: 'keyword', + }, + 'rsa.web.web_cookie': { + category: 'rsa', + description: 'This key is used to capture the Web cookies specifically.', + name: 'rsa.web.web_cookie', + type: 'keyword', + }, + 'rsa.web.alias_host': { + category: 'rsa', + name: 'rsa.web.alias_host', + type: 'keyword', + }, + 'rsa.web.reputation_num': { + category: 'rsa', + description: 'Reputation Number of an entity. Typically used for Web Domains', + name: 'rsa.web.reputation_num', + type: 'double', + }, + 'rsa.web.web_ref_domain': { + category: 'rsa', + description: "Web referer's domain", + name: 'rsa.web.web_ref_domain', + type: 'keyword', + }, + 'rsa.web.web_ref_query': { + category: 'rsa', + description: "This key captures Web referer's query portion of the URL", + name: 'rsa.web.web_ref_query', + type: 'keyword', + }, + 'rsa.web.remote_domain': { + category: 'rsa', + name: 'rsa.web.remote_domain', + type: 'keyword', + }, + 'rsa.web.web_ref_page': { + category: 'rsa', + description: "This key captures Web referer's page information", + name: 'rsa.web.web_ref_page', + type: 'keyword', + }, + 'rsa.web.web_ref_root': { + category: 'rsa', + description: "Web referer's root URL path", + name: 'rsa.web.web_ref_root', + type: 'keyword', + }, + 'rsa.web.cn_asn_dst': { + category: 'rsa', + name: 'rsa.web.cn_asn_dst', + type: 'keyword', + }, + 'rsa.web.cn_rpackets': { + category: 'rsa', + name: 'rsa.web.cn_rpackets', + type: 'keyword', + }, + 'rsa.web.urlpage': { + category: 'rsa', + name: 'rsa.web.urlpage', + type: 'keyword', + }, + 'rsa.web.urlroot': { + category: 'rsa', + name: 'rsa.web.urlroot', + type: 'keyword', + }, + 'rsa.web.p_url': { + category: 'rsa', + name: 'rsa.web.p_url', + type: 'keyword', + }, + 'rsa.web.p_user_agent': { + category: 'rsa', + name: 'rsa.web.p_user_agent', + type: 'keyword', + }, + 'rsa.web.p_web_cookie': { + category: 'rsa', + name: 'rsa.web.p_web_cookie', + type: 'keyword', + }, + 'rsa.web.p_web_method': { + category: 'rsa', + name: 'rsa.web.p_web_method', + type: 'keyword', + }, + 'rsa.web.p_web_referer': { + category: 'rsa', + name: 'rsa.web.p_web_referer', + type: 'keyword', + }, + 'rsa.web.web_extension_tmp': { + category: 'rsa', + name: 'rsa.web.web_extension_tmp', + type: 'keyword', + }, + 'rsa.web.web_page': { + category: 'rsa', + name: 'rsa.web.web_page', + type: 'keyword', + }, + 'rsa.threat.threat_category': { + category: 'rsa', + description: 'This key captures Threat Name/Threat Category/Categorization of alert', + name: 'rsa.threat.threat_category', + type: 'keyword', + }, + 'rsa.threat.threat_desc': { + category: 'rsa', + description: + 'This key is used to capture the threat description from the session directly or inferred', + name: 'rsa.threat.threat_desc', + type: 'keyword', + }, + 'rsa.threat.alert': { + category: 'rsa', + description: 'This key is used to capture name of the alert', + name: 'rsa.threat.alert', + type: 'keyword', + }, + 'rsa.threat.threat_source': { + category: 'rsa', + description: 'This key is used to capture source of the threat', + name: 'rsa.threat.threat_source', + type: 'keyword', + }, + 'rsa.crypto.crypto': { + category: 'rsa', + description: 'This key is used to capture the Encryption Type or Encryption Key only', + name: 'rsa.crypto.crypto', + type: 'keyword', + }, + 'rsa.crypto.cipher_src': { + category: 'rsa', + description: 'This key is for Source (Client) Cipher', + name: 'rsa.crypto.cipher_src', + type: 'keyword', + }, + 'rsa.crypto.cert_subject': { + category: 'rsa', + description: 'This key is used to capture the Certificate organization only', + name: 'rsa.crypto.cert_subject', + type: 'keyword', + }, + 'rsa.crypto.peer': { + category: 'rsa', + description: "This key is for Encryption peer's IP Address", + name: 'rsa.crypto.peer', + type: 'keyword', + }, + 'rsa.crypto.cipher_size_src': { + category: 'rsa', + description: 'This key captures Source (Client) Cipher Size', + name: 'rsa.crypto.cipher_size_src', + type: 'long', + }, + 'rsa.crypto.ike': { + category: 'rsa', + description: 'IKE negotiation phase.', + name: 'rsa.crypto.ike', + type: 'keyword', + }, + 'rsa.crypto.scheme': { + category: 'rsa', + description: 'This key captures the Encryption scheme used', + name: 'rsa.crypto.scheme', + type: 'keyword', + }, + 'rsa.crypto.peer_id': { + category: 'rsa', + description: 'This key is for Encryption peer’s identity', + name: 'rsa.crypto.peer_id', + type: 'keyword', + }, + 'rsa.crypto.sig_type': { + category: 'rsa', + description: 'This key captures the Signature Type', + name: 'rsa.crypto.sig_type', + type: 'keyword', + }, + 'rsa.crypto.cert_issuer': { + category: 'rsa', + name: 'rsa.crypto.cert_issuer', + type: 'keyword', + }, + 'rsa.crypto.cert_host_name': { + category: 'rsa', + description: 'Deprecated key defined only in table map.', + name: 'rsa.crypto.cert_host_name', + type: 'keyword', + }, + 'rsa.crypto.cert_error': { + category: 'rsa', + description: 'This key captures the Certificate Error String', + name: 'rsa.crypto.cert_error', + type: 'keyword', + }, + 'rsa.crypto.cipher_dst': { + category: 'rsa', + description: 'This key is for Destination (Server) Cipher', + name: 'rsa.crypto.cipher_dst', + type: 'keyword', + }, + 'rsa.crypto.cipher_size_dst': { + category: 'rsa', + description: 'This key captures Destination (Server) Cipher Size', + name: 'rsa.crypto.cipher_size_dst', + type: 'long', + }, + 'rsa.crypto.ssl_ver_src': { + category: 'rsa', + description: 'Deprecated, use version', + name: 'rsa.crypto.ssl_ver_src', + type: 'keyword', + }, + 'rsa.crypto.d_certauth': { + category: 'rsa', + name: 'rsa.crypto.d_certauth', + type: 'keyword', + }, + 'rsa.crypto.s_certauth': { + category: 'rsa', + name: 'rsa.crypto.s_certauth', + type: 'keyword', + }, + 'rsa.crypto.ike_cookie1': { + category: 'rsa', + description: 'ID of the negotiation — sent for ISAKMP Phase One', + name: 'rsa.crypto.ike_cookie1', + type: 'keyword', + }, + 'rsa.crypto.ike_cookie2': { + category: 'rsa', + description: 'ID of the negotiation — sent for ISAKMP Phase Two', + name: 'rsa.crypto.ike_cookie2', + type: 'keyword', + }, + 'rsa.crypto.cert_checksum': { + category: 'rsa', + name: 'rsa.crypto.cert_checksum', + type: 'keyword', + }, + 'rsa.crypto.cert_host_cat': { + category: 'rsa', + description: 'This key is used for the hostname category value of a certificate', + name: 'rsa.crypto.cert_host_cat', + type: 'keyword', + }, + 'rsa.crypto.cert_serial': { + category: 'rsa', + description: 'This key is used to capture the Certificate serial number only', + name: 'rsa.crypto.cert_serial', + type: 'keyword', + }, + 'rsa.crypto.cert_status': { + category: 'rsa', + description: 'This key captures Certificate validation status', + name: 'rsa.crypto.cert_status', + type: 'keyword', + }, + 'rsa.crypto.ssl_ver_dst': { + category: 'rsa', + description: 'Deprecated, use version', + name: 'rsa.crypto.ssl_ver_dst', + type: 'keyword', + }, + 'rsa.crypto.cert_keysize': { + category: 'rsa', + name: 'rsa.crypto.cert_keysize', + type: 'keyword', + }, + 'rsa.crypto.cert_username': { + category: 'rsa', + name: 'rsa.crypto.cert_username', + type: 'keyword', + }, + 'rsa.crypto.https_insact': { + category: 'rsa', + name: 'rsa.crypto.https_insact', + type: 'keyword', + }, + 'rsa.crypto.https_valid': { + category: 'rsa', + name: 'rsa.crypto.https_valid', + type: 'keyword', + }, + 'rsa.crypto.cert_ca': { + category: 'rsa', + description: 'This key is used to capture the Certificate signing authority only', + name: 'rsa.crypto.cert_ca', + type: 'keyword', + }, + 'rsa.crypto.cert_common': { + category: 'rsa', + description: 'This key is used to capture the Certificate common name only', + name: 'rsa.crypto.cert_common', + type: 'keyword', + }, + 'rsa.wireless.wlan_ssid': { + category: 'rsa', + description: 'This key is used to capture the ssid of a Wireless Session', + name: 'rsa.wireless.wlan_ssid', + type: 'keyword', + }, + 'rsa.wireless.access_point': { + category: 'rsa', + description: 'This key is used to capture the access point name.', + name: 'rsa.wireless.access_point', + type: 'keyword', + }, + 'rsa.wireless.wlan_channel': { + category: 'rsa', + description: 'This is used to capture the channel names', + name: 'rsa.wireless.wlan_channel', + type: 'long', + }, + 'rsa.wireless.wlan_name': { + category: 'rsa', + description: 'This key captures either WLAN number/name', + name: 'rsa.wireless.wlan_name', + type: 'keyword', + }, + 'rsa.storage.disk_volume': { + category: 'rsa', + description: 'A unique name assigned to logical units (volumes) within a physical disk', + name: 'rsa.storage.disk_volume', + type: 'keyword', + }, + 'rsa.storage.lun': { + category: 'rsa', + description: 'Logical Unit Number.This key is a very useful concept in Storage.', + name: 'rsa.storage.lun', + type: 'keyword', + }, + 'rsa.storage.pwwn': { + category: 'rsa', + description: 'This uniquely identifies a port on a HBA.', + name: 'rsa.storage.pwwn', + type: 'keyword', + }, + 'rsa.physical.org_dst': { + category: 'rsa', + description: + 'This is used to capture the destination organization based on the GEOPIP Maxmind database.', + name: 'rsa.physical.org_dst', + type: 'keyword', + }, + 'rsa.physical.org_src': { + category: 'rsa', + description: + 'This is used to capture the source organization based on the GEOPIP Maxmind database.', + name: 'rsa.physical.org_src', + type: 'keyword', + }, + 'rsa.healthcare.patient_fname': { + category: 'rsa', + description: + 'This key is for First Names only, this is used for Healthcare predominantly to capture Patients information', + name: 'rsa.healthcare.patient_fname', + type: 'keyword', + }, + 'rsa.healthcare.patient_id': { + category: 'rsa', + description: 'This key captures the unique ID for a patient', + name: 'rsa.healthcare.patient_id', + type: 'keyword', + }, + 'rsa.healthcare.patient_lname': { + category: 'rsa', + description: + 'This key is for Last Names only, this is used for Healthcare predominantly to capture Patients information', + name: 'rsa.healthcare.patient_lname', + type: 'keyword', + }, + 'rsa.healthcare.patient_mname': { + category: 'rsa', + description: + 'This key is for Middle Names only, this is used for Healthcare predominantly to capture Patients information', + name: 'rsa.healthcare.patient_mname', + type: 'keyword', + }, + 'rsa.endpoint.host_state': { + category: 'rsa', + description: + 'This key is used to capture the current state of the machine, such as blacklisted, infected, firewall disabled and so on', + name: 'rsa.endpoint.host_state', + type: 'keyword', + }, + 'rsa.endpoint.registry_key': { + category: 'rsa', + description: 'This key captures the path to the registry key', + name: 'rsa.endpoint.registry_key', + type: 'keyword', + }, + 'rsa.endpoint.registry_value': { + category: 'rsa', + description: 'This key captures values or decorators used within a registry entry', + name: 'rsa.endpoint.registry_value', + type: 'keyword', + }, + 'forcepoint.virus_id': { + category: 'forcepoint', + description: 'Virus ID ', + name: 'forcepoint.virus_id', + type: 'keyword', + }, + 'checkpoint.app_risk': { + category: 'checkpoint', + description: 'Application risk.', + name: 'checkpoint.app_risk', + type: 'keyword', + }, + 'checkpoint.app_severity': { + category: 'checkpoint', + description: 'Application threat severity.', + name: 'checkpoint.app_severity', + type: 'keyword', + }, + 'checkpoint.app_sig_id': { + category: 'checkpoint', + description: 'The signature ID which the application was detected by.', + name: 'checkpoint.app_sig_id', + type: 'keyword', + }, + 'checkpoint.auth_method': { + category: 'checkpoint', + description: 'Password authentication protocol used.', + name: 'checkpoint.auth_method', + type: 'keyword', + }, + 'checkpoint.category': { + category: 'checkpoint', + description: 'Category.', + name: 'checkpoint.category', + type: 'keyword', + }, + 'checkpoint.confidence_level': { + category: 'checkpoint', + description: 'Confidence level determined.', + name: 'checkpoint.confidence_level', + type: 'integer', + }, + 'checkpoint.connectivity_state': { + category: 'checkpoint', + description: 'Connectivity state.', + name: 'checkpoint.connectivity_state', + type: 'keyword', + }, + 'checkpoint.cookie': { + category: 'checkpoint', + description: 'IKE cookie.', + name: 'checkpoint.cookie', + type: 'keyword', + }, + 'checkpoint.dst_phone_number': { + category: 'checkpoint', + description: 'Destination IP-Phone.', + name: 'checkpoint.dst_phone_number', + type: 'keyword', + }, + 'checkpoint.email_control': { + category: 'checkpoint', + description: 'Engine name.', + name: 'checkpoint.email_control', + type: 'keyword', + }, + 'checkpoint.email_id': { + category: 'checkpoint', + description: 'Internal email ID.', + name: 'checkpoint.email_id', + type: 'keyword', + }, + 'checkpoint.email_recipients_num': { + category: 'checkpoint', + description: 'Number of recipients.', + name: 'checkpoint.email_recipients_num', + type: 'long', + }, + 'checkpoint.email_session_id': { + category: 'checkpoint', + description: 'Internal email session ID.', + name: 'checkpoint.email_session_id', + type: 'keyword', + }, + 'checkpoint.email_spool_id': { + category: 'checkpoint', + description: 'Internal email spool ID.', + name: 'checkpoint.email_spool_id', + type: 'keyword', + }, + 'checkpoint.email_subject': { + category: 'checkpoint', + description: 'Email subject.', + name: 'checkpoint.email_subject', + type: 'keyword', + }, + 'checkpoint.event_count': { + category: 'checkpoint', + description: 'Number of events associated with the log.', + name: 'checkpoint.event_count', + type: 'long', + }, + 'checkpoint.frequency': { + category: 'checkpoint', + description: 'Scan frequency.', + name: 'checkpoint.frequency', + type: 'keyword', + }, + 'checkpoint.icmp_type': { + category: 'checkpoint', + description: 'ICMP type.', + name: 'checkpoint.icmp_type', + type: 'long', + }, + 'checkpoint.icmp_code': { + category: 'checkpoint', + description: 'ICMP code.', + name: 'checkpoint.icmp_code', + type: 'long', + }, + 'checkpoint.identity_type': { + category: 'checkpoint', + description: 'Identity type.', + name: 'checkpoint.identity_type', + type: 'keyword', + }, + 'checkpoint.incident_extension': { + category: 'checkpoint', + description: 'Format of original data.', + name: 'checkpoint.incident_extension', + type: 'keyword', + }, + 'checkpoint.integrity_av_invoke_type': { + category: 'checkpoint', + description: 'Scan invoke type.', + name: 'checkpoint.integrity_av_invoke_type', + type: 'keyword', + }, + 'checkpoint.malware_family': { + category: 'checkpoint', + description: 'Malware family.', + name: 'checkpoint.malware_family', + type: 'keyword', + }, + 'checkpoint.peer_gateway': { + category: 'checkpoint', + description: 'Main IP of the peer Security Gateway.', + name: 'checkpoint.peer_gateway', + type: 'ip', + }, + 'checkpoint.performance_impact': { + category: 'checkpoint', + description: 'Protection performance impact.', + name: 'checkpoint.performance_impact', + type: 'integer', + }, + 'checkpoint.protection_id': { + category: 'checkpoint', + description: 'Protection malware ID.', + name: 'checkpoint.protection_id', + type: 'keyword', + }, + 'checkpoint.protection_name': { + category: 'checkpoint', + description: 'Specific signature name of the attack.', + name: 'checkpoint.protection_name', + type: 'keyword', + }, + 'checkpoint.protection_type': { + category: 'checkpoint', + description: 'Type of protection used to detect the attack.', + name: 'checkpoint.protection_type', + type: 'keyword', + }, + 'checkpoint.scan_result': { + category: 'checkpoint', + description: 'Scan result.', + name: 'checkpoint.scan_result', + type: 'keyword', + }, + 'checkpoint.sensor_mode': { + category: 'checkpoint', + description: 'Sensor mode.', + name: 'checkpoint.sensor_mode', + type: 'keyword', + }, + 'checkpoint.severity': { + category: 'checkpoint', + description: 'Threat severity.', + name: 'checkpoint.severity', + type: 'keyword', + }, + 'checkpoint.spyware_name': { + category: 'checkpoint', + description: 'Spyware name.', + name: 'checkpoint.spyware_name', + type: 'keyword', + }, + 'checkpoint.spyware_status': { + category: 'checkpoint', + description: 'Spyware status.', + name: 'checkpoint.spyware_status', + type: 'keyword', + }, + 'checkpoint.subs_exp': { + category: 'checkpoint', + description: 'The expiration date of the subscription.', + name: 'checkpoint.subs_exp', + type: 'date', + }, + 'checkpoint.tcp_flags': { + category: 'checkpoint', + description: 'TCP packet flags.', + name: 'checkpoint.tcp_flags', + type: 'keyword', + }, + 'checkpoint.termination_reason': { + category: 'checkpoint', + description: 'Termination reason.', + name: 'checkpoint.termination_reason', + type: 'keyword', + }, + 'checkpoint.update_status': { + category: 'checkpoint', + description: 'Update status.', + name: 'checkpoint.update_status', + type: 'keyword', + }, + 'checkpoint.user_status': { + category: 'checkpoint', + description: 'User response.', + name: 'checkpoint.user_status', + type: 'keyword', + }, + 'checkpoint.uuid': { + category: 'checkpoint', + description: 'External ID.', + name: 'checkpoint.uuid', + type: 'keyword', + }, + 'checkpoint.virus_name': { + category: 'checkpoint', + description: 'Virus name.', + name: 'checkpoint.virus_name', + type: 'keyword', + }, + 'checkpoint.voip_log_type': { + category: 'checkpoint', + description: 'VoIP log types.', + name: 'checkpoint.voip_log_type', + type: 'keyword', + }, + 'cef.extensions.cp_app_risk': { + category: 'cef', + name: 'cef.extensions.cp_app_risk', + type: 'keyword', + }, + 'cef.extensions.cp_severity': { + category: 'cef', + name: 'cef.extensions.cp_severity', + type: 'keyword', + }, + 'cef.extensions.ifname': { + category: 'cef', + name: 'cef.extensions.ifname', + type: 'keyword', + }, + 'cef.extensions.inzone': { + category: 'cef', + name: 'cef.extensions.inzone', + type: 'keyword', + }, + 'cef.extensions.layer_uuid': { + category: 'cef', + name: 'cef.extensions.layer_uuid', + type: 'keyword', + }, + 'cef.extensions.layer_name': { + category: 'cef', + name: 'cef.extensions.layer_name', + type: 'keyword', + }, + 'cef.extensions.logid': { + category: 'cef', + name: 'cef.extensions.logid', + type: 'keyword', + }, + 'cef.extensions.loguid': { + category: 'cef', + name: 'cef.extensions.loguid', + type: 'keyword', + }, + 'cef.extensions.match_id': { + category: 'cef', + name: 'cef.extensions.match_id', + type: 'keyword', + }, + 'cef.extensions.nat_addtnl_rulenum': { + category: 'cef', + name: 'cef.extensions.nat_addtnl_rulenum', + type: 'keyword', + }, + 'cef.extensions.nat_rulenum': { + category: 'cef', + name: 'cef.extensions.nat_rulenum', + type: 'keyword', + }, + 'cef.extensions.origin': { + category: 'cef', + name: 'cef.extensions.origin', + type: 'keyword', + }, + 'cef.extensions.originsicname': { + category: 'cef', + name: 'cef.extensions.originsicname', + type: 'keyword', + }, + 'cef.extensions.outzone': { + category: 'cef', + name: 'cef.extensions.outzone', + type: 'keyword', + }, + 'cef.extensions.parent_rule': { + category: 'cef', + name: 'cef.extensions.parent_rule', + type: 'keyword', + }, + 'cef.extensions.product': { + category: 'cef', + name: 'cef.extensions.product', + type: 'keyword', + }, + 'cef.extensions.rule_action': { + category: 'cef', + name: 'cef.extensions.rule_action', + type: 'keyword', + }, + 'cef.extensions.rule_uid': { + category: 'cef', + name: 'cef.extensions.rule_uid', + type: 'keyword', + }, + 'cef.extensions.sequencenum': { + category: 'cef', + name: 'cef.extensions.sequencenum', + type: 'keyword', + }, + 'cef.extensions.service_id': { + category: 'cef', + name: 'cef.extensions.service_id', + type: 'keyword', + }, + 'cef.extensions.version': { + category: 'cef', + name: 'cef.extensions.version', + type: 'keyword', + }, + 'checkpoint.calc_desc': { + category: 'checkpoint', + description: 'Log description. ', + name: 'checkpoint.calc_desc', + type: 'keyword', + }, + 'checkpoint.dst_country': { + category: 'checkpoint', + description: 'Destination country. ', + name: 'checkpoint.dst_country', + type: 'keyword', + }, + 'checkpoint.dst_user_name': { + category: 'checkpoint', + description: 'Connected user name on the destination IP. ', + name: 'checkpoint.dst_user_name', + type: 'keyword', + }, + 'checkpoint.sys_message': { + category: 'checkpoint', + description: 'System messages ', + name: 'checkpoint.sys_message', + type: 'keyword', + }, + 'checkpoint.logid': { + category: 'checkpoint', + description: 'System messages ', + name: 'checkpoint.logid', + type: 'keyword', + }, + 'checkpoint.failure_impact': { + category: 'checkpoint', + description: 'The impact of update service failure. ', + name: 'checkpoint.failure_impact', + type: 'keyword', + }, + 'checkpoint.id': { + category: 'checkpoint', + description: 'Override application ID. ', + name: 'checkpoint.id', + type: 'integer', + }, + 'checkpoint.information': { + category: 'checkpoint', + description: 'Policy installation status for a specific blade. ', + name: 'checkpoint.information', + type: 'keyword', + }, + 'checkpoint.layer_name': { + category: 'checkpoint', + description: 'Layer name. ', + name: 'checkpoint.layer_name', + type: 'keyword', + }, + 'checkpoint.layer_uuid': { + category: 'checkpoint', + description: 'Layer UUID. ', + name: 'checkpoint.layer_uuid', + type: 'keyword', + }, + 'checkpoint.log_id': { + category: 'checkpoint', + description: 'Unique identity for logs. ', + name: 'checkpoint.log_id', + type: 'integer', + }, + 'checkpoint.origin_sic_name': { + category: 'checkpoint', + description: 'Machine SIC. ', + name: 'checkpoint.origin_sic_name', + type: 'keyword', + }, + 'checkpoint.policy_mgmt': { + category: 'checkpoint', + description: 'Name of the Management Server that manages this Security Gateway. ', + name: 'checkpoint.policy_mgmt', + type: 'keyword', + }, + 'checkpoint.policy_name': { + category: 'checkpoint', + description: 'Name of the last policy that this Security Gateway fetched. ', + name: 'checkpoint.policy_name', + type: 'keyword', + }, + 'checkpoint.protocol': { + category: 'checkpoint', + description: 'Protocol detected on the connection. ', + name: 'checkpoint.protocol', + type: 'keyword', + }, + 'checkpoint.proxy_src_ip': { + category: 'checkpoint', + description: 'Sender source IP (even when using proxy). ', + name: 'checkpoint.proxy_src_ip', + type: 'ip', + }, + 'checkpoint.rule': { + category: 'checkpoint', + description: 'Matched rule number. ', + name: 'checkpoint.rule', + type: 'integer', + }, + 'checkpoint.rule_action': { + category: 'checkpoint', + description: 'Action of the matched rule in the access policy. ', + name: 'checkpoint.rule_action', + type: 'keyword', + }, + 'checkpoint.scan_direction': { + category: 'checkpoint', + description: 'Scan direction. ', + name: 'checkpoint.scan_direction', + type: 'keyword', + }, + 'checkpoint.session_id': { + category: 'checkpoint', + description: 'Log uuid. ', + name: 'checkpoint.session_id', + type: 'keyword', + }, + 'checkpoint.source_os': { + category: 'checkpoint', + description: 'OS which generated the attack. ', + name: 'checkpoint.source_os', + type: 'keyword', + }, + 'checkpoint.src_country': { + category: 'checkpoint', + description: 'Country name, derived from connection source IP address. ', + name: 'checkpoint.src_country', + type: 'keyword', + }, + 'checkpoint.src_user_name': { + category: 'checkpoint', + description: 'User name connected to source IP ', + name: 'checkpoint.src_user_name', + type: 'keyword', + }, + 'checkpoint.ticket_id': { + category: 'checkpoint', + description: 'Unique ID per file. ', + name: 'checkpoint.ticket_id', + type: 'keyword', + }, + 'checkpoint.tls_server_host_name': { + category: 'checkpoint', + description: 'SNI/CN from encrypted TLS connection used by URLF for categorization. ', + name: 'checkpoint.tls_server_host_name', + type: 'keyword', + }, + 'checkpoint.verdict': { + category: 'checkpoint', + description: 'TE engine verdict Possible values: Malicious/Benign/Error. ', + name: 'checkpoint.verdict', + type: 'keyword', + }, + 'checkpoint.user': { + category: 'checkpoint', + description: 'Source user name. ', + name: 'checkpoint.user', + type: 'keyword', + }, + 'checkpoint.vendor_list': { + category: 'checkpoint', + description: 'The vendor name that provided the verdict for a malicious URL. ', + name: 'checkpoint.vendor_list', + type: 'keyword', + }, + 'checkpoint.web_server_type': { + category: 'checkpoint', + description: 'Web server detected in the HTTP response. ', + name: 'checkpoint.web_server_type', + type: 'keyword', + }, + 'checkpoint.client_name': { + category: 'checkpoint', + description: 'Client Application or Software Blade that detected the event. ', + name: 'checkpoint.client_name', + type: 'keyword', + }, + 'checkpoint.client_version': { + category: 'checkpoint', + description: 'Build version of SandBlast Agent client installed on the computer. ', + name: 'checkpoint.client_version', + type: 'keyword', + }, + 'checkpoint.extension_version': { + category: 'checkpoint', + description: 'Build version of the SandBlast Agent browser extension. ', + name: 'checkpoint.extension_version', + type: 'keyword', + }, + 'checkpoint.host_time': { + category: 'checkpoint', + description: 'Local time on the endpoint computer. ', + name: 'checkpoint.host_time', + type: 'keyword', + }, + 'checkpoint.installed_products': { + category: 'checkpoint', + description: 'List of installed Endpoint Software Blades. ', + name: 'checkpoint.installed_products', + type: 'keyword', + }, + 'checkpoint.cc': { + category: 'checkpoint', + description: 'The Carbon Copy address of the email. ', + name: 'checkpoint.cc', + type: 'keyword', + }, + 'checkpoint.parent_process_username': { + category: 'checkpoint', + description: 'Owner username of the parent process of the process that triggered the attack. ', + name: 'checkpoint.parent_process_username', + type: 'keyword', + }, + 'checkpoint.process_username': { + category: 'checkpoint', + description: 'Owner username of the process that triggered the attack. ', + name: 'checkpoint.process_username', + type: 'keyword', + }, + 'checkpoint.audit_status': { + category: 'checkpoint', + description: 'Audit Status. Can be Success or Failure. ', + name: 'checkpoint.audit_status', + type: 'keyword', + }, + 'checkpoint.objecttable': { + category: 'checkpoint', + description: 'Table of affected objects. ', + name: 'checkpoint.objecttable', + type: 'keyword', + }, + 'checkpoint.objecttype': { + category: 'checkpoint', + description: 'The type of the affected object. ', + name: 'checkpoint.objecttype', + type: 'keyword', + }, + 'checkpoint.operation_number': { + category: 'checkpoint', + description: 'The operation nuber. ', + name: 'checkpoint.operation_number', + type: 'keyword', + }, + 'checkpoint.suppressed_logs': { + category: 'checkpoint', + description: + 'Aggregated connections for five minutes on the same source, destination and port. ', + name: 'checkpoint.suppressed_logs', + type: 'integer', + }, + 'checkpoint.blade_name': { + category: 'checkpoint', + description: 'Blade name. ', + name: 'checkpoint.blade_name', + type: 'keyword', + }, + 'checkpoint.status': { + category: 'checkpoint', + description: 'Ok/Warning/Error. ', + name: 'checkpoint.status', + type: 'keyword', + }, + 'checkpoint.short_desc': { + category: 'checkpoint', + description: 'Short description of the process that was executed. ', + name: 'checkpoint.short_desc', + type: 'keyword', + }, + 'checkpoint.long_desc': { + category: 'checkpoint', + description: 'More information on the process (usually describing error reason in failure). ', + name: 'checkpoint.long_desc', + type: 'keyword', + }, + 'checkpoint.scan_hosts_hour': { + category: 'checkpoint', + description: 'Number of unique hosts during the last hour. ', + name: 'checkpoint.scan_hosts_hour', + type: 'integer', + }, + 'checkpoint.scan_hosts_day': { + category: 'checkpoint', + description: 'Number of unique hosts during the last day. ', + name: 'checkpoint.scan_hosts_day', + type: 'integer', + }, + 'checkpoint.scan_hosts_week': { + category: 'checkpoint', + description: 'Number of unique hosts during the last week. ', + name: 'checkpoint.scan_hosts_week', + type: 'integer', + }, + 'checkpoint.unique_detected_hour': { + category: 'checkpoint', + description: 'Detected virus for a specific host during the last hour. ', + name: 'checkpoint.unique_detected_hour', + type: 'integer', + }, + 'checkpoint.unique_detected_day': { + category: 'checkpoint', + description: 'Detected virus for a specific host during the last day. ', + name: 'checkpoint.unique_detected_day', + type: 'integer', + }, + 'checkpoint.unique_detected_week': { + category: 'checkpoint', + description: 'Detected virus for a specific host during the last week. ', + name: 'checkpoint.unique_detected_week', + type: 'integer', + }, + 'checkpoint.scan_mail': { + category: 'checkpoint', + description: 'Number of emails that were scanned by "AB malicious activity" engine. ', + name: 'checkpoint.scan_mail', + type: 'integer', + }, + 'checkpoint.additional_ip': { + category: 'checkpoint', + description: 'DNS host name. ', + name: 'checkpoint.additional_ip', + type: 'keyword', + }, + 'checkpoint.description': { + category: 'checkpoint', + description: 'Additional explanation how the security gateway enforced the connection. ', + name: 'checkpoint.description', + type: 'keyword', + }, + 'checkpoint.email_spam_category': { + category: 'checkpoint', + description: 'Email categories. Possible values: spam/not spam/phishing. ', + name: 'checkpoint.email_spam_category', + type: 'keyword', + }, + 'checkpoint.email_control_analysis': { + category: 'checkpoint', + description: 'Message classification, received from spam vendor engine. ', + name: 'checkpoint.email_control_analysis', + type: 'keyword', + }, + 'checkpoint.scan_results': { + category: 'checkpoint', + description: '"Infected"/description of a failure. ', + name: 'checkpoint.scan_results', + type: 'keyword', + }, + 'checkpoint.original_queue_id': { + category: 'checkpoint', + description: 'Original postfix email queue id. ', + name: 'checkpoint.original_queue_id', + type: 'keyword', + }, + 'checkpoint.risk': { + category: 'checkpoint', + description: 'Risk level we got from the engine. ', + name: 'checkpoint.risk', + type: 'keyword', + }, + 'checkpoint.observable_name': { + category: 'checkpoint', + description: 'IOC observable signature name. ', + name: 'checkpoint.observable_name', + type: 'keyword', + }, + 'checkpoint.observable_id': { + category: 'checkpoint', + description: 'IOC observable signature id. ', + name: 'checkpoint.observable_id', + type: 'keyword', + }, + 'checkpoint.observable_comment': { + category: 'checkpoint', + description: 'IOC observable signature description. ', + name: 'checkpoint.observable_comment', + type: 'keyword', + }, + 'checkpoint.indicator_name': { + category: 'checkpoint', + description: 'IOC indicator name. ', + name: 'checkpoint.indicator_name', + type: 'keyword', + }, + 'checkpoint.indicator_description': { + category: 'checkpoint', + description: 'IOC indicator description. ', + name: 'checkpoint.indicator_description', + type: 'keyword', + }, + 'checkpoint.indicator_reference': { + category: 'checkpoint', + description: 'IOC indicator reference. ', + name: 'checkpoint.indicator_reference', + type: 'keyword', + }, + 'checkpoint.indicator_uuid': { + category: 'checkpoint', + description: 'IOC indicator uuid. ', + name: 'checkpoint.indicator_uuid', + type: 'keyword', + }, + 'checkpoint.app_desc': { + category: 'checkpoint', + description: 'Application description. ', + name: 'checkpoint.app_desc', + type: 'keyword', + }, + 'checkpoint.app_id': { + category: 'checkpoint', + description: 'Application ID. ', + name: 'checkpoint.app_id', + type: 'integer', + }, + 'checkpoint.certificate_resource': { + category: 'checkpoint', + description: 'HTTPS resource Possible values: SNI or domain name (DN). ', + name: 'checkpoint.certificate_resource', + type: 'keyword', + }, + 'checkpoint.certificate_validation': { + category: 'checkpoint', + description: + 'Precise error, describing HTTPS certificate failure under "HTTPS categorize websites" feature. ', + name: 'checkpoint.certificate_validation', + type: 'keyword', + }, + 'checkpoint.browse_time': { + category: 'checkpoint', + description: 'Application session browse time. ', + name: 'checkpoint.browse_time', + type: 'keyword', + }, + 'checkpoint.limit_requested': { + category: 'checkpoint', + description: 'Indicates whether data limit was requested for the session. ', + name: 'checkpoint.limit_requested', + type: 'integer', + }, + 'checkpoint.limit_applied': { + category: 'checkpoint', + description: 'Indicates whether the session was actually date limited. ', + name: 'checkpoint.limit_applied', + type: 'integer', + }, + 'checkpoint.dropped_total': { + category: 'checkpoint', + description: 'Amount of dropped packets (both incoming and outgoing). ', + name: 'checkpoint.dropped_total', + type: 'integer', + }, + 'checkpoint.client_type_os': { + category: 'checkpoint', + description: 'Client OS detected in the HTTP request. ', + name: 'checkpoint.client_type_os', + type: 'keyword', + }, + 'checkpoint.name': { + category: 'checkpoint', + description: 'Application name. ', + name: 'checkpoint.name', + type: 'keyword', + }, + 'checkpoint.properties': { + category: 'checkpoint', + description: 'Application categories. ', + name: 'checkpoint.properties', + type: 'keyword', + }, + 'checkpoint.sig_id': { + category: 'checkpoint', + description: "Application's signature ID which how it was detected by. ", + name: 'checkpoint.sig_id', + type: 'keyword', + }, + 'checkpoint.desc': { + category: 'checkpoint', + description: 'Override application description. ', + name: 'checkpoint.desc', + type: 'keyword', + }, + 'checkpoint.referrer_self_uid': { + category: 'checkpoint', + description: 'UUID of the current log. ', + name: 'checkpoint.referrer_self_uid', + type: 'keyword', + }, + 'checkpoint.referrer_parent_uid': { + category: 'checkpoint', + description: 'Log UUID of the referring application. ', + name: 'checkpoint.referrer_parent_uid', + type: 'keyword', + }, + 'checkpoint.needs_browse_time': { + category: 'checkpoint', + description: 'Browse time required for the connection. ', + name: 'checkpoint.needs_browse_time', + type: 'integer', + }, + 'checkpoint.cluster_info': { + category: 'checkpoint', + description: + 'Cluster information. Possible options: Failover reason/cluster state changes/CP cluster or 3rd party. ', + name: 'checkpoint.cluster_info', + type: 'keyword', + }, + 'checkpoint.sync': { + category: 'checkpoint', + description: 'Sync status and the reason (stable, at risk). ', + name: 'checkpoint.sync', + type: 'keyword', + }, + 'checkpoint.file_direction': { + category: 'checkpoint', + description: 'File direction. Possible options: upload/download. ', + name: 'checkpoint.file_direction', + type: 'keyword', + }, + 'checkpoint.invalid_file_size': { + category: 'checkpoint', + description: 'File_size field is valid only if this field is set to 0. ', + name: 'checkpoint.invalid_file_size', + type: 'integer', + }, + 'checkpoint.top_archive_file_name': { + category: 'checkpoint', + description: 'In case of archive file: the file that was sent/received. ', + name: 'checkpoint.top_archive_file_name', + type: 'keyword', + }, + 'checkpoint.data_type_name': { + category: 'checkpoint', + description: 'Data type in rulebase that was matched. ', + name: 'checkpoint.data_type_name', + type: 'keyword', + }, + 'checkpoint.specific_data_type_name': { + category: 'checkpoint', + description: 'Compound/Group scenario, data type that was matched. ', + name: 'checkpoint.specific_data_type_name', + type: 'keyword', + }, + 'checkpoint.word_list': { + category: 'checkpoint', + description: 'Words matched by data type. ', + name: 'checkpoint.word_list', + type: 'keyword', + }, + 'checkpoint.info': { + category: 'checkpoint', + description: 'Special log message. ', + name: 'checkpoint.info', + type: 'keyword', + }, + 'checkpoint.outgoing_url': { + category: 'checkpoint', + description: 'URL related to this log (for HTTP). ', + name: 'checkpoint.outgoing_url', + type: 'keyword', + }, + 'checkpoint.dlp_rule_name': { + category: 'checkpoint', + description: 'Matched rule name. ', + name: 'checkpoint.dlp_rule_name', + type: 'keyword', + }, + 'checkpoint.dlp_recipients': { + category: 'checkpoint', + description: 'Mail recipients. ', + name: 'checkpoint.dlp_recipients', + type: 'keyword', + }, + 'checkpoint.dlp_subject': { + category: 'checkpoint', + description: 'Mail subject. ', + name: 'checkpoint.dlp_subject', + type: 'keyword', + }, + 'checkpoint.dlp_word_list': { + category: 'checkpoint', + description: 'Phrases matched by data type. ', + name: 'checkpoint.dlp_word_list', + type: 'keyword', + }, + 'checkpoint.dlp_template_score': { + category: 'checkpoint', + description: 'Template data type match score. ', + name: 'checkpoint.dlp_template_score', + type: 'keyword', + }, + 'checkpoint.message_size': { + category: 'checkpoint', + description: 'Mail/post size. ', + name: 'checkpoint.message_size', + type: 'integer', + }, + 'checkpoint.dlp_incident_uid': { + category: 'checkpoint', + description: 'Unique ID of the matched rule. ', + name: 'checkpoint.dlp_incident_uid', + type: 'keyword', + }, + 'checkpoint.dlp_related_incident_uid': { + category: 'checkpoint', + description: 'Other ID related to this one. ', + name: 'checkpoint.dlp_related_incident_uid', + type: 'keyword', + }, + 'checkpoint.dlp_data_type_name': { + category: 'checkpoint', + description: 'Matched data type. ', + name: 'checkpoint.dlp_data_type_name', + type: 'keyword', + }, + 'checkpoint.dlp_data_type_uid': { + category: 'checkpoint', + description: 'Unique ID of the matched data type. ', + name: 'checkpoint.dlp_data_type_uid', + type: 'keyword', + }, + 'checkpoint.dlp_violation_description': { + category: 'checkpoint', + description: 'Violation descriptions described in the rulebase. ', + name: 'checkpoint.dlp_violation_description', + type: 'keyword', + }, + 'checkpoint.dlp_relevant_data_types': { + category: 'checkpoint', + description: 'In case of Compound/Group: the inner data types that were matched. ', + name: 'checkpoint.dlp_relevant_data_types', + type: 'keyword', + }, + 'checkpoint.dlp_action_reason': { + category: 'checkpoint', + description: 'Action chosen reason. ', + name: 'checkpoint.dlp_action_reason', + type: 'keyword', + }, + 'checkpoint.dlp_categories': { + category: 'checkpoint', + description: 'Data type category. ', + name: 'checkpoint.dlp_categories', + type: 'keyword', + }, + 'checkpoint.dlp_transint': { + category: 'checkpoint', + description: 'HTTP/SMTP/FTP. ', + name: 'checkpoint.dlp_transint', + type: 'keyword', + }, + 'checkpoint.duplicate': { + category: 'checkpoint', + description: + 'Log marked as duplicated, when mail is split and the Security Gateway sees it twice. ', + name: 'checkpoint.duplicate', + type: 'keyword', + }, + 'checkpoint.matched_file': { + category: 'checkpoint', + description: 'Unique ID of the matched data type. ', + name: 'checkpoint.matched_file', + type: 'keyword', + }, + 'checkpoint.matched_file_text_segments': { + category: 'checkpoint', + description: 'Fingerprint: number of text segments matched by this traffic. ', + name: 'checkpoint.matched_file_text_segments', + type: 'integer', + }, + 'checkpoint.matched_file_percentage': { + category: 'checkpoint', + description: 'Fingerprint: match percentage of the traffic. ', + name: 'checkpoint.matched_file_percentage', + type: 'integer', + }, + 'checkpoint.dlp_additional_action': { + category: 'checkpoint', + description: 'Watermark/None. ', + name: 'checkpoint.dlp_additional_action', + type: 'keyword', + }, + 'checkpoint.dlp_watermark_profile': { + category: 'checkpoint', + description: 'Watermark which was applied. ', + name: 'checkpoint.dlp_watermark_profile', + type: 'keyword', + }, + 'checkpoint.dlp_repository_id': { + category: 'checkpoint', + description: 'ID of scanned repository. ', + name: 'checkpoint.dlp_repository_id', + type: 'keyword', + }, + 'checkpoint.dlp_repository_root_path': { + category: 'checkpoint', + description: 'Repository path. ', + name: 'checkpoint.dlp_repository_root_path', + type: 'keyword', + }, + 'checkpoint.scan_id': { + category: 'checkpoint', + description: 'Sequential number of scan. ', + name: 'checkpoint.scan_id', + type: 'keyword', + }, + 'checkpoint.special_properties': { + category: 'checkpoint', + description: + "If this field is set to '1' the log will not be shown (in use for monitoring scan progress). ", + name: 'checkpoint.special_properties', + type: 'integer', + }, + 'checkpoint.dlp_repository_total_size': { + category: 'checkpoint', + description: 'Repository size. ', + name: 'checkpoint.dlp_repository_total_size', + type: 'integer', + }, + 'checkpoint.dlp_repository_files_number': { + category: 'checkpoint', + description: 'Number of files in repository. ', + name: 'checkpoint.dlp_repository_files_number', + type: 'integer', + }, + 'checkpoint.dlp_repository_scanned_files_number': { + category: 'checkpoint', + description: 'Number of scanned files in repository. ', + name: 'checkpoint.dlp_repository_scanned_files_number', + type: 'integer', + }, + 'checkpoint.duration': { + category: 'checkpoint', + description: 'Scan duration. ', + name: 'checkpoint.duration', + type: 'keyword', + }, + 'checkpoint.dlp_fingerprint_long_status': { + category: 'checkpoint', + description: 'Scan status - long format. ', + name: 'checkpoint.dlp_fingerprint_long_status', + type: 'keyword', + }, + 'checkpoint.dlp_fingerprint_short_status': { + category: 'checkpoint', + description: 'Scan status - short format. ', + name: 'checkpoint.dlp_fingerprint_short_status', + type: 'keyword', + }, + 'checkpoint.dlp_repository_directories_number': { + category: 'checkpoint', + description: 'Number of directories in repository. ', + name: 'checkpoint.dlp_repository_directories_number', + type: 'integer', + }, + 'checkpoint.dlp_repository_unreachable_directories_number': { + category: 'checkpoint', + description: 'Number of directories the Security Gateway was unable to read. ', + name: 'checkpoint.dlp_repository_unreachable_directories_number', + type: 'integer', + }, + 'checkpoint.dlp_fingerprint_files_number': { + category: 'checkpoint', + description: 'Number of successfully scanned files in repository. ', + name: 'checkpoint.dlp_fingerprint_files_number', + type: 'integer', + }, + 'checkpoint.dlp_repository_skipped_files_number': { + category: 'checkpoint', + description: 'Skipped number of files because of configuration. ', + name: 'checkpoint.dlp_repository_skipped_files_number', + type: 'integer', + }, + 'checkpoint.dlp_repository_scanned_directories_number': { + category: 'checkpoint', + description: 'Amount of directories scanned. ', + name: 'checkpoint.dlp_repository_scanned_directories_number', + type: 'integer', + }, + 'checkpoint.number_of_errors': { + category: 'checkpoint', + description: 'Number of files that were not scanned due to an error. ', + name: 'checkpoint.number_of_errors', + type: 'integer', + }, + 'checkpoint.next_scheduled_scan_date': { + category: 'checkpoint', + description: 'Next scan scheduled time according to time object. ', + name: 'checkpoint.next_scheduled_scan_date', + type: 'keyword', + }, + 'checkpoint.dlp_repository_scanned_total_size': { + category: 'checkpoint', + description: 'Size scanned. ', + name: 'checkpoint.dlp_repository_scanned_total_size', + type: 'integer', + }, + 'checkpoint.dlp_repository_reached_directories_number': { + category: 'checkpoint', + description: 'Number of scanned directories in repository. ', + name: 'checkpoint.dlp_repository_reached_directories_number', + type: 'integer', + }, + 'checkpoint.dlp_repository_not_scanned_directories_percentage': { + category: 'checkpoint', + description: 'Percentage of directories the Security Gateway was unable to read. ', + name: 'checkpoint.dlp_repository_not_scanned_directories_percentage', + type: 'integer', + }, + 'checkpoint.speed': { + category: 'checkpoint', + description: 'Current scan speed. ', + name: 'checkpoint.speed', + type: 'integer', + }, + 'checkpoint.dlp_repository_scan_progress': { + category: 'checkpoint', + description: 'Scan percentage. ', + name: 'checkpoint.dlp_repository_scan_progress', + type: 'integer', + }, + 'checkpoint.sub_policy_name': { + category: 'checkpoint', + description: 'Layer name. ', + name: 'checkpoint.sub_policy_name', + type: 'keyword', + }, + 'checkpoint.sub_policy_uid': { + category: 'checkpoint', + description: 'Layer uid. ', + name: 'checkpoint.sub_policy_uid', + type: 'keyword', + }, + 'checkpoint.fw_message': { + category: 'checkpoint', + description: 'Used for various firewall errors. ', + name: 'checkpoint.fw_message', + type: 'keyword', + }, + 'checkpoint.message': { + category: 'checkpoint', + description: 'ISP link has failed. ', + name: 'checkpoint.message', + type: 'keyword', + }, + 'checkpoint.isp_link': { + category: 'checkpoint', + description: 'Name of ISP link. ', + name: 'checkpoint.isp_link', + type: 'keyword', + }, + 'checkpoint.fw_subproduct': { + category: 'checkpoint', + description: 'Can be vpn/non vpn. ', + name: 'checkpoint.fw_subproduct', + type: 'keyword', + }, + 'checkpoint.sctp_error': { + category: 'checkpoint', + description: 'Error information, what caused sctp to fail on out_of_state. ', + name: 'checkpoint.sctp_error', + type: 'keyword', + }, + 'checkpoint.chunk_type': { + category: 'checkpoint', + description: 'Chunck of the sctp stream. ', + name: 'checkpoint.chunk_type', + type: 'keyword', + }, + 'checkpoint.sctp_association_state': { + category: 'checkpoint', + description: 'The bad state you were trying to update to. ', + name: 'checkpoint.sctp_association_state', + type: 'keyword', + }, + 'checkpoint.tcp_packet_out_of_state': { + category: 'checkpoint', + description: 'State violation. ', + name: 'checkpoint.tcp_packet_out_of_state', + type: 'keyword', + }, + 'checkpoint.connectivity_level': { + category: 'checkpoint', + description: 'Log for a new connection in wire mode. ', + name: 'checkpoint.connectivity_level', + type: 'keyword', + }, + 'checkpoint.ip_option': { + category: 'checkpoint', + description: 'IP option that was dropped. ', + name: 'checkpoint.ip_option', + type: 'integer', + }, + 'checkpoint.tcp_state': { + category: 'checkpoint', + description: 'Log reinting a tcp state change. ', + name: 'checkpoint.tcp_state', + type: 'keyword', + }, + 'checkpoint.expire_time': { + category: 'checkpoint', + description: 'Connection closing time. ', + name: 'checkpoint.expire_time', + type: 'keyword', + }, + 'checkpoint.rpc_prog': { + category: 'checkpoint', + description: 'Log for new RPC state - prog values. ', + name: 'checkpoint.rpc_prog', + type: 'integer', + }, + 'checkpoint.dce-rpc_interface_uuid': { + category: 'checkpoint', + description: 'Log for new RPC state - UUID values ', + name: 'checkpoint.dce-rpc_interface_uuid', + type: 'keyword', + }, + 'checkpoint.elapsed': { + category: 'checkpoint', + description: 'Time passed since start time. ', + name: 'checkpoint.elapsed', + type: 'keyword', + }, + 'checkpoint.icmp': { + category: 'checkpoint', + description: 'Number of packets, received by the client. ', + name: 'checkpoint.icmp', + type: 'keyword', + }, + 'checkpoint.capture_uuid': { + category: 'checkpoint', + description: 'UUID generated for the capture. Used when enabling the capture when logging. ', + name: 'checkpoint.capture_uuid', + type: 'keyword', + }, + 'checkpoint.diameter_app_ID': { + category: 'checkpoint', + description: 'The ID of diameter application. ', + name: 'checkpoint.diameter_app_ID', + type: 'integer', + }, + 'checkpoint.diameter_cmd_code': { + category: 'checkpoint', + description: 'Diameter not allowed application command id. ', + name: 'checkpoint.diameter_cmd_code', + type: 'integer', + }, + 'checkpoint.diameter_msg_type': { + category: 'checkpoint', + description: 'Diameter message type. ', + name: 'checkpoint.diameter_msg_type', + type: 'keyword', + }, + 'checkpoint.cp_message': { + category: 'checkpoint', + description: 'Used to log a general message. ', + name: 'checkpoint.cp_message', + type: 'integer', + }, + 'checkpoint.log_delay': { + category: 'checkpoint', + description: 'Time left before deleting template. ', + name: 'checkpoint.log_delay', + type: 'integer', + }, + 'checkpoint.attack_status': { + category: 'checkpoint', + description: 'In case of a malicious event on an endpoint computer, the status of the attack. ', + name: 'checkpoint.attack_status', + type: 'keyword', + }, + 'checkpoint.impacted_files': { + category: 'checkpoint', + description: + 'In case of an infection on an endpoint computer, the list of files that the malware impacted. ', + name: 'checkpoint.impacted_files', + type: 'keyword', + }, + 'checkpoint.remediated_files': { + category: 'checkpoint', + description: + 'In case of an infection and a successful cleaning of that infection, this is a list of remediated files on the computer. ', + name: 'checkpoint.remediated_files', + type: 'keyword', + }, + 'checkpoint.triggered_by': { + category: 'checkpoint', + description: + 'The name of the mechanism that triggered the Software Blade to enforce a protection. ', + name: 'checkpoint.triggered_by', + type: 'keyword', + }, + 'checkpoint.https_inspection_rule_id': { + category: 'checkpoint', + description: 'ID of the matched rule. ', + name: 'checkpoint.https_inspection_rule_id', + type: 'keyword', + }, + 'checkpoint.https_inspection_rule_name': { + category: 'checkpoint', + description: 'Name of the matched rule. ', + name: 'checkpoint.https_inspection_rule_name', + type: 'keyword', + }, + 'checkpoint.app_properties': { + category: 'checkpoint', + description: 'List of all found categories. ', + name: 'checkpoint.app_properties', + type: 'keyword', + }, + 'checkpoint.https_validation': { + category: 'checkpoint', + description: 'Precise error, describing HTTPS inspection failure. ', + name: 'checkpoint.https_validation', + type: 'keyword', + }, + 'checkpoint.https_inspection_action': { + category: 'checkpoint', + description: 'HTTPS inspection action (Inspect/Bypass/Error). ', + name: 'checkpoint.https_inspection_action', + type: 'keyword', + }, + 'checkpoint.icap_service_id': { + category: 'checkpoint', + description: 'Service ID, can work with multiple servers, treated as services. ', + name: 'checkpoint.icap_service_id', + type: 'integer', + }, + 'checkpoint.icap_server_name': { + category: 'checkpoint', + description: 'Server name. ', + name: 'checkpoint.icap_server_name', + type: 'keyword', + }, + 'checkpoint.internal_error': { + category: 'checkpoint', + description: 'Internal error, for troubleshooting ', + name: 'checkpoint.internal_error', + type: 'keyword', + }, + 'checkpoint.icap_more_info': { + category: 'checkpoint', + description: 'Free text for verdict. ', + name: 'checkpoint.icap_more_info', + type: 'integer', + }, + 'checkpoint.reply_status': { + category: 'checkpoint', + description: 'ICAP reply status code, e.g. 200 or 204. ', + name: 'checkpoint.reply_status', + type: 'integer', + }, + 'checkpoint.icap_server_service': { + category: 'checkpoint', + description: 'Service name, as given in the ICAP URI ', + name: 'checkpoint.icap_server_service', + type: 'keyword', + }, + 'checkpoint.mirror_and_decrypt_type': { + category: 'checkpoint', + description: + 'Information about decrypt and forward. Possible values: Mirror only, Decrypt and mirror, Partial mirroring (HTTPS inspection Bypass). ', + name: 'checkpoint.mirror_and_decrypt_type', + type: 'keyword', + }, + 'checkpoint.interface_name': { + category: 'checkpoint', + description: 'Designated interface for mirror And decrypt. ', + name: 'checkpoint.interface_name', + type: 'keyword', + }, + 'checkpoint.session_uid': { + category: 'checkpoint', + description: 'HTTP session-id. ', + name: 'checkpoint.session_uid', + type: 'keyword', + }, + 'checkpoint.broker_publisher': { + category: 'checkpoint', + description: 'IP address of the broker publisher who shared the session information. ', + name: 'checkpoint.broker_publisher', + type: 'ip', + }, + 'checkpoint.src_user_dn': { + category: 'checkpoint', + description: 'User distinguished name connected to source IP. ', + name: 'checkpoint.src_user_dn', + type: 'keyword', + }, + 'checkpoint.proxy_user_name': { + category: 'checkpoint', + description: 'User name connected to proxy IP. ', + name: 'checkpoint.proxy_user_name', + type: 'keyword', + }, + 'checkpoint.proxy_machine_name': { + category: 'checkpoint', + description: 'Machine name connected to proxy IP. ', + name: 'checkpoint.proxy_machine_name', + type: 'integer', + }, + 'checkpoint.proxy_user_dn': { + category: 'checkpoint', + description: 'User distinguished name connected to proxy IP. ', + name: 'checkpoint.proxy_user_dn', + type: 'keyword', + }, + 'checkpoint.query': { + category: 'checkpoint', + description: 'DNS query. ', + name: 'checkpoint.query', + type: 'keyword', + }, + 'checkpoint.dns_query': { + category: 'checkpoint', + description: 'DNS query. ', + name: 'checkpoint.dns_query', + type: 'keyword', + }, + 'checkpoint.inspection_item': { + category: 'checkpoint', + description: 'Blade element performed inspection. ', + name: 'checkpoint.inspection_item', + type: 'keyword', + }, + 'checkpoint.inspection_category': { + category: 'checkpoint', + description: 'Inspection category: protocol anomaly, signature etc. ', + name: 'checkpoint.inspection_category', + type: 'keyword', + }, + 'checkpoint.inspection_profile': { + category: 'checkpoint', + description: 'Profile which the activated protection belongs to. ', + name: 'checkpoint.inspection_profile', + type: 'keyword', + }, + 'checkpoint.summary': { + category: 'checkpoint', + description: 'Summary message of a non-compliant DNS traffic drops or detects. ', + name: 'checkpoint.summary', + type: 'keyword', + }, + 'checkpoint.question_rdata': { + category: 'checkpoint', + description: 'List of question records domains. ', + name: 'checkpoint.question_rdata', + type: 'keyword', + }, + 'checkpoint.answer_rdata': { + category: 'checkpoint', + description: 'List of answer resource records to the questioned domains. ', + name: 'checkpoint.answer_rdata', + type: 'keyword', + }, + 'checkpoint.authority_rdata': { + category: 'checkpoint', + description: 'List of authoritative servers. ', + name: 'checkpoint.authority_rdata', + type: 'keyword', + }, + 'checkpoint.additional_rdata': { + category: 'checkpoint', + description: 'List of additional resource records. ', + name: 'checkpoint.additional_rdata', + type: 'keyword', + }, + 'checkpoint.files_names': { + category: 'checkpoint', + description: 'List of files requested by FTP. ', + name: 'checkpoint.files_names', + type: 'keyword', + }, + 'checkpoint.ftp_user': { + category: 'checkpoint', + description: 'FTP username. ', + name: 'checkpoint.ftp_user', + type: 'keyword', + }, + 'checkpoint.mime_from': { + category: 'checkpoint', + description: "Sender's address. ", + name: 'checkpoint.mime_from', + type: 'keyword', + }, + 'checkpoint.mime_to': { + category: 'checkpoint', + description: 'List of receiver address. ', + name: 'checkpoint.mime_to', + type: 'keyword', + }, + 'checkpoint.bcc': { + category: 'checkpoint', + description: 'List of BCC addresses. ', + name: 'checkpoint.bcc', + type: 'keyword', + }, + 'checkpoint.content_type': { + category: 'checkpoint', + description: + 'Mail content type. Possible values: application/msword, text/html, image/gif etc. ', + name: 'checkpoint.content_type', + type: 'keyword', + }, + 'checkpoint.user_agent': { + category: 'checkpoint', + description: 'String identifying requesting software user agent. ', + name: 'checkpoint.user_agent', + type: 'keyword', + }, + 'checkpoint.referrer': { + category: 'checkpoint', + description: 'Referrer HTTP request header, previous web page address. ', + name: 'checkpoint.referrer', + type: 'keyword', + }, + 'checkpoint.http_location': { + category: 'checkpoint', + description: 'Response header, indicates the URL to redirect a page to. ', + name: 'checkpoint.http_location', + type: 'keyword', + }, + 'checkpoint.content_disposition': { + category: 'checkpoint', + description: 'Indicates how the content is expected to be displayed inline in the browser. ', + name: 'checkpoint.content_disposition', + type: 'keyword', + }, + 'checkpoint.via': { + category: 'checkpoint', + description: + 'Via header is added by proxies for tracking purposes to avoid sending reqests in loop. ', + name: 'checkpoint.via', + type: 'keyword', + }, + 'checkpoint.http_server': { + category: 'checkpoint', + description: + 'Server HTTP header value, contains information about the software used by the origin server, which handles the request. ', + name: 'checkpoint.http_server', + type: 'keyword', + }, + 'checkpoint.content_length': { + category: 'checkpoint', + description: 'Indicates the size of the entity-body of the HTTP header. ', + name: 'checkpoint.content_length', + type: 'keyword', + }, + 'checkpoint.authorization': { + category: 'checkpoint', + description: 'Authorization HTTP header value. ', + name: 'checkpoint.authorization', + type: 'keyword', + }, + 'checkpoint.http_host': { + category: 'checkpoint', + description: 'Domain name of the server that the HTTP request is sent to. ', + name: 'checkpoint.http_host', + type: 'keyword', + }, + 'checkpoint.inspection_settings_log': { + category: 'checkpoint', + description: 'Indicats that the log was released by inspection settings. ', + name: 'checkpoint.inspection_settings_log', + type: 'keyword', + }, + 'checkpoint.cvpn_resource': { + category: 'checkpoint', + description: 'Mobile Access application. ', + name: 'checkpoint.cvpn_resource', + type: 'keyword', + }, + 'checkpoint.cvpn_category': { + category: 'checkpoint', + description: 'Mobile Access application type. ', + name: 'checkpoint.cvpn_category', + type: 'keyword', + }, + 'checkpoint.url': { + category: 'checkpoint', + description: 'Translated URL. ', + name: 'checkpoint.url', + type: 'keyword', + }, + 'checkpoint.reject_id': { + category: 'checkpoint', + description: + 'A reject ID that corresponds to the one presented in the Mobile Access error page. ', + name: 'checkpoint.reject_id', + type: 'keyword', + }, + 'checkpoint.fs-proto': { + category: 'checkpoint', + description: 'The file share protocol used in mobile acess file share application. ', + name: 'checkpoint.fs-proto', + type: 'keyword', + }, + 'checkpoint.app_package': { + category: 'checkpoint', + description: 'Unique identifier of the application on the protected mobile device. ', + name: 'checkpoint.app_package', + type: 'keyword', + }, + 'checkpoint.appi_name': { + category: 'checkpoint', + description: 'Name of application downloaded on the protected mobile device. ', + name: 'checkpoint.appi_name', + type: 'keyword', + }, + 'checkpoint.app_repackaged': { + category: 'checkpoint', + description: + 'Indicates whether the original application was repackage not by the official developer. ', + name: 'checkpoint.app_repackaged', + type: 'keyword', + }, + 'checkpoint.app_sid_id': { + category: 'checkpoint', + description: 'Unique SHA identifier of a mobile application. ', + name: 'checkpoint.app_sid_id', + type: 'keyword', + }, + 'checkpoint.app_version': { + category: 'checkpoint', + description: 'Version of the application downloaded on the protected mobile device. ', + name: 'checkpoint.app_version', + type: 'keyword', + }, + 'checkpoint.developer_certificate_name': { + category: 'checkpoint', + description: + "Name of the developer's certificate that was used to sign the mobile application. ", + name: 'checkpoint.developer_certificate_name', + type: 'keyword', + }, + 'checkpoint.email_message_id': { + category: 'checkpoint', + description: 'Email session id (uniqe ID of the mail). ', + name: 'checkpoint.email_message_id', + type: 'keyword', + }, + 'checkpoint.email_queue_id': { + category: 'checkpoint', + description: 'Postfix email queue id. ', + name: 'checkpoint.email_queue_id', + type: 'keyword', + }, + 'checkpoint.email_queue_name': { + category: 'checkpoint', + description: 'Postfix email queue name. ', + name: 'checkpoint.email_queue_name', + type: 'keyword', + }, + 'checkpoint.file_name': { + category: 'checkpoint', + description: 'Malicious file name. ', + name: 'checkpoint.file_name', + type: 'keyword', + }, + 'checkpoint.failure_reason': { + category: 'checkpoint', + description: 'MTA failure description. ', + name: 'checkpoint.failure_reason', + type: 'keyword', + }, + 'checkpoint.email_headers': { + category: 'checkpoint', + description: 'String containing all the email headers. ', + name: 'checkpoint.email_headers', + type: 'keyword', + }, + 'checkpoint.arrival_time': { + category: 'checkpoint', + description: 'Email arrival timestamp. ', + name: 'checkpoint.arrival_time', + type: 'keyword', + }, + 'checkpoint.email_status': { + category: 'checkpoint', + description: + "Describes the email's state. Possible options: delivered, deferred, skipped, bounced, hold, new, scan_started, scan_ended ", + name: 'checkpoint.email_status', + type: 'keyword', + }, + 'checkpoint.status_update': { + category: 'checkpoint', + description: 'Last time log was updated. ', + name: 'checkpoint.status_update', + type: 'keyword', + }, + 'checkpoint.delivery_time': { + category: 'checkpoint', + description: 'Timestamp of when email was delivered (MTA finished handling the email. ', + name: 'checkpoint.delivery_time', + type: 'keyword', + }, + 'checkpoint.links_num': { + category: 'checkpoint', + description: 'Number of links in the mail. ', + name: 'checkpoint.links_num', + type: 'integer', + }, + 'checkpoint.attachments_num': { + category: 'checkpoint', + description: 'Number of attachments in the mail. ', + name: 'checkpoint.attachments_num', + type: 'integer', + }, + 'checkpoint.email_content': { + category: 'checkpoint', + description: + 'Mail contents. Possible options: attachments/links & attachments/links/text only. ', + name: 'checkpoint.email_content', + type: 'keyword', + }, + 'checkpoint.allocated_ports': { + category: 'checkpoint', + description: 'Amount of allocated ports. ', + name: 'checkpoint.allocated_ports', + type: 'integer', + }, + 'checkpoint.capacity': { + category: 'checkpoint', + description: 'Capacity of the ports. ', + name: 'checkpoint.capacity', + type: 'integer', + }, + 'checkpoint.ports_usage': { + category: 'checkpoint', + description: 'Percentage of allocated ports. ', + name: 'checkpoint.ports_usage', + type: 'integer', + }, + 'checkpoint.nat_exhausted_pool': { + category: 'checkpoint', + description: '4-tuple of an exhausted pool. ', + name: 'checkpoint.nat_exhausted_pool', + type: 'keyword', + }, + 'checkpoint.nat_rulenum': { + category: 'checkpoint', + description: 'NAT rulebase first matched rule. ', + name: 'checkpoint.nat_rulenum', + type: 'integer', + }, + 'checkpoint.nat_addtnl_rulenum': { + category: 'checkpoint', + description: + 'When matching 2 automatic rules , second rule match will be shown otherwise field will be 0. ', + name: 'checkpoint.nat_addtnl_rulenum', + type: 'integer', + }, + 'checkpoint.message_info': { + category: 'checkpoint', + description: 'Used for information messages, for example:NAT connection has ended. ', + name: 'checkpoint.message_info', + type: 'keyword', + }, + 'checkpoint.nat46': { + category: 'checkpoint', + description: 'NAT 46 status, in most cases "enabled". ', + name: 'checkpoint.nat46', + type: 'keyword', + }, + 'checkpoint.end_time': { + category: 'checkpoint', + description: 'TCP connection end time. ', + name: 'checkpoint.end_time', + type: 'keyword', + }, + 'checkpoint.tcp_end_reason': { + category: 'checkpoint', + description: 'Reason for TCP connection closure. ', + name: 'checkpoint.tcp_end_reason', + type: 'keyword', + }, + 'checkpoint.cgnet': { + category: 'checkpoint', + description: 'Describes NAT allocation for specific subscriber. ', + name: 'checkpoint.cgnet', + type: 'keyword', + }, + 'checkpoint.subscriber': { + category: 'checkpoint', + description: 'Source IP before CGNAT. ', + name: 'checkpoint.subscriber', + type: 'ip', + }, + 'checkpoint.hide_ip': { + category: 'checkpoint', + description: 'Source IP which will be used after CGNAT. ', + name: 'checkpoint.hide_ip', + type: 'ip', + }, + 'checkpoint.int_start': { + category: 'checkpoint', + description: 'Subscriber start int which will be used for NAT. ', + name: 'checkpoint.int_start', + type: 'integer', + }, + 'checkpoint.int_end': { + category: 'checkpoint', + description: 'Subscriber end int which will be used for NAT. ', + name: 'checkpoint.int_end', + type: 'integer', + }, + 'checkpoint.packet_amount': { + category: 'checkpoint', + description: 'Amount of packets dropped. ', + name: 'checkpoint.packet_amount', + type: 'integer', + }, + 'checkpoint.monitor_reason': { + category: 'checkpoint', + description: 'Aggregated logs of monitored packets. ', + name: 'checkpoint.monitor_reason', + type: 'keyword', + }, + 'checkpoint.drops_amount': { + category: 'checkpoint', + description: 'Amount of multicast packets dropped. ', + name: 'checkpoint.drops_amount', + type: 'integer', + }, + 'checkpoint.securexl_message': { + category: 'checkpoint', + description: + 'Two options for a SecureXL message: 1. Missed accounting records after heavy load on logging system. 2. FW log message regarding a packet drop. ', + name: 'checkpoint.securexl_message', + type: 'keyword', + }, + 'checkpoint.conns_amount': { + category: 'checkpoint', + description: 'Connections amount of aggregated log info. ', + name: 'checkpoint.conns_amount', + type: 'integer', + }, + 'checkpoint.scope': { + category: 'checkpoint', + description: 'IP related to the attack. ', + name: 'checkpoint.scope', + type: 'keyword', + }, + 'checkpoint.analyzed_on': { + category: 'checkpoint', + description: 'Check Point ThreatCloud / emulator name. ', + name: 'checkpoint.analyzed_on', + type: 'keyword', + }, + 'checkpoint.detected_on': { + category: 'checkpoint', + description: 'System and applications version the file was emulated on. ', + name: 'checkpoint.detected_on', + type: 'keyword', + }, + 'checkpoint.dropped_file_name': { + category: 'checkpoint', + description: 'List of names dropped from the original file. ', + name: 'checkpoint.dropped_file_name', + type: 'keyword', + }, + 'checkpoint.dropped_file_type': { + category: 'checkpoint', + description: 'List of file types dropped from the original file. ', + name: 'checkpoint.dropped_file_type', + type: 'keyword', + }, + 'checkpoint.dropped_file_hash': { + category: 'checkpoint', + description: 'List of file hashes dropped from the original file. ', + name: 'checkpoint.dropped_file_hash', + type: 'keyword', + }, + 'checkpoint.dropped_file_verdict': { + category: 'checkpoint', + description: 'List of file verdics dropped from the original file. ', + name: 'checkpoint.dropped_file_verdict', + type: 'keyword', + }, + 'checkpoint.emulated_on': { + category: 'checkpoint', + description: 'Images the files were emulated on. ', + name: 'checkpoint.emulated_on', + type: 'keyword', + }, + 'checkpoint.extracted_file_type': { + category: 'checkpoint', + description: 'Types of extracted files in case of an archive. ', + name: 'checkpoint.extracted_file_type', + type: 'keyword', + }, + 'checkpoint.extracted_file_names': { + category: 'checkpoint', + description: 'Names of extracted files in case of an archive. ', + name: 'checkpoint.extracted_file_names', + type: 'keyword', + }, + 'checkpoint.extracted_file_hash': { + category: 'checkpoint', + description: 'Archive hash in case of extracted files. ', + name: 'checkpoint.extracted_file_hash', + type: 'keyword', + }, + 'checkpoint.extracted_file_verdict': { + category: 'checkpoint', + description: 'Verdict of extracted files in case of an archive. ', + name: 'checkpoint.extracted_file_verdict', + type: 'keyword', + }, + 'checkpoint.extracted_file_uid': { + category: 'checkpoint', + description: 'UID of extracted files in case of an archive. ', + name: 'checkpoint.extracted_file_uid', + type: 'keyword', + }, + 'checkpoint.mitre_initial_access': { + category: 'checkpoint', + description: 'The adversary is trying to break into your network. ', + name: 'checkpoint.mitre_initial_access', + type: 'keyword', + }, + 'checkpoint.mitre_execution': { + category: 'checkpoint', + description: 'The adversary is trying to run malicious code. ', + name: 'checkpoint.mitre_execution', + type: 'keyword', + }, + 'checkpoint.mitre_persistence': { + category: 'checkpoint', + description: 'The adversary is trying to maintain his foothold. ', + name: 'checkpoint.mitre_persistence', + type: 'keyword', + }, + 'checkpoint.mitre_privilege_escalation': { + category: 'checkpoint', + description: 'The adversary is trying to gain higher-level permissions. ', + name: 'checkpoint.mitre_privilege_escalation', + type: 'keyword', + }, + 'checkpoint.mitre_defense_evasion': { + category: 'checkpoint', + description: 'The adversary is trying to avoid being detected. ', + name: 'checkpoint.mitre_defense_evasion', + type: 'keyword', + }, + 'checkpoint.mitre_credential_access': { + category: 'checkpoint', + description: 'The adversary is trying to steal account names and passwords. ', + name: 'checkpoint.mitre_credential_access', + type: 'keyword', + }, + 'checkpoint.mitre_discovery': { + category: 'checkpoint', + description: 'The adversary is trying to expose information about your environment. ', + name: 'checkpoint.mitre_discovery', + type: 'keyword', + }, + 'checkpoint.mitre_lateral_movement': { + category: 'checkpoint', + description: 'The adversary is trying to explore your environment. ', + name: 'checkpoint.mitre_lateral_movement', + type: 'keyword', + }, + 'checkpoint.mitre_collection': { + category: 'checkpoint', + description: 'The adversary is trying to collect data of interest to achieve his goal. ', + name: 'checkpoint.mitre_collection', + type: 'keyword', + }, + 'checkpoint.mitre_command_and_control': { + category: 'checkpoint', + description: + 'The adversary is trying to communicate with compromised systems in order to control them. ', + name: 'checkpoint.mitre_command_and_control', + type: 'keyword', + }, + 'checkpoint.mitre_exfiltration': { + category: 'checkpoint', + description: 'The adversary is trying to steal data. ', + name: 'checkpoint.mitre_exfiltration', + type: 'keyword', + }, + 'checkpoint.mitre_impact': { + category: 'checkpoint', + description: + 'The adversary is trying to manipulate, interrupt, or destroy your systems and data. ', + name: 'checkpoint.mitre_impact', + type: 'keyword', + }, + 'checkpoint.parent_file_hash': { + category: 'checkpoint', + description: "Archive's hash in case of extracted files. ", + name: 'checkpoint.parent_file_hash', + type: 'keyword', + }, + 'checkpoint.parent_file_name': { + category: 'checkpoint', + description: "Archive's name in case of extracted files. ", + name: 'checkpoint.parent_file_name', + type: 'keyword', + }, + 'checkpoint.parent_file_uid': { + category: 'checkpoint', + description: "Archive's UID in case of extracted files. ", + name: 'checkpoint.parent_file_uid', + type: 'keyword', + }, + 'checkpoint.similiar_iocs': { + category: 'checkpoint', + description: 'Other IoCs similar to the ones found, related to the malicious file. ', + name: 'checkpoint.similiar_iocs', + type: 'keyword', + }, + 'checkpoint.similar_hashes': { + category: 'checkpoint', + description: 'Hashes found similar to the malicious file. ', + name: 'checkpoint.similar_hashes', + type: 'keyword', + }, + 'checkpoint.similar_strings': { + category: 'checkpoint', + description: 'Strings found similar to the malicious file. ', + name: 'checkpoint.similar_strings', + type: 'keyword', + }, + 'checkpoint.similar_communication': { + category: 'checkpoint', + description: 'Network action found similar to the malicious file. ', + name: 'checkpoint.similar_communication', + type: 'keyword', + }, + 'checkpoint.te_verdict_determined_by': { + category: 'checkpoint', + description: 'Emulators determined file verdict. ', + name: 'checkpoint.te_verdict_determined_by', + type: 'keyword', + }, + 'checkpoint.packet_capture_unique_id': { + category: 'checkpoint', + description: 'Identifier of the packet capture files. ', + name: 'checkpoint.packet_capture_unique_id', + type: 'keyword', + }, + 'checkpoint.total_attachments': { + category: 'checkpoint', + description: 'The number of attachments in an email. ', + name: 'checkpoint.total_attachments', + type: 'integer', + }, + 'checkpoint.additional_info': { + category: 'checkpoint', + description: 'ID of original file/mail which are sent by admin. ', + name: 'checkpoint.additional_info', + type: 'keyword', + }, + 'checkpoint.content_risk': { + category: 'checkpoint', + description: 'File risk. ', + name: 'checkpoint.content_risk', + type: 'integer', + }, + 'checkpoint.operation': { + category: 'checkpoint', + description: 'Operation made by Threat Extraction. ', + name: 'checkpoint.operation', + type: 'keyword', + }, + 'checkpoint.scrubbed_content': { + category: 'checkpoint', + description: 'Active content that was found. ', + name: 'checkpoint.scrubbed_content', + type: 'keyword', + }, + 'checkpoint.scrub_time': { + category: 'checkpoint', + description: 'Extraction process duration. ', + name: 'checkpoint.scrub_time', + type: 'keyword', + }, + 'checkpoint.scrub_download_time': { + category: 'checkpoint', + description: 'File download time from resource. ', + name: 'checkpoint.scrub_download_time', + type: 'keyword', + }, + 'checkpoint.scrub_total_time': { + category: 'checkpoint', + description: 'Threat extraction total file handling time. ', + name: 'checkpoint.scrub_total_time', + type: 'keyword', + }, + 'checkpoint.scrub_activity': { + category: 'checkpoint', + description: 'The result of the extraction ', + name: 'checkpoint.scrub_activity', + type: 'keyword', + }, + 'checkpoint.watermark': { + category: 'checkpoint', + description: 'Reports whether watermark is added to the cleaned file. ', + name: 'checkpoint.watermark', + type: 'keyword', + }, + 'checkpoint.source_object': { + category: 'checkpoint', + description: 'Matched object name on source column. ', + name: 'checkpoint.source_object', + type: 'integer', + }, + 'checkpoint.destination_object': { + category: 'checkpoint', + description: 'Matched object name on destination column. ', + name: 'checkpoint.destination_object', + type: 'keyword', + }, + 'checkpoint.drop_reason': { + category: 'checkpoint', + description: 'Drop reason description. ', + name: 'checkpoint.drop_reason', + type: 'keyword', + }, + 'checkpoint.hit': { + category: 'checkpoint', + description: 'Number of hits on a rule. ', + name: 'checkpoint.hit', + type: 'integer', + }, + 'checkpoint.rulebase_id': { + category: 'checkpoint', + description: 'Layer number. ', + name: 'checkpoint.rulebase_id', + type: 'integer', + }, + 'checkpoint.first_hit_time': { + category: 'checkpoint', + description: 'First hit time in current interval. ', + name: 'checkpoint.first_hit_time', + type: 'integer', + }, + 'checkpoint.last_hit_time': { + category: 'checkpoint', + description: 'Last hit time in current interval. ', + name: 'checkpoint.last_hit_time', + type: 'integer', + }, + 'checkpoint.rematch_info': { + category: 'checkpoint', + description: + 'Information sent when old connections cannot be matched during policy installation. ', + name: 'checkpoint.rematch_info', + type: 'keyword', + }, + 'checkpoint.last_rematch_time': { + category: 'checkpoint', + description: 'Connection rematched time. ', + name: 'checkpoint.last_rematch_time', + type: 'keyword', + }, + 'checkpoint.action_reason': { + category: 'checkpoint', + description: 'Connection drop reason. ', + name: 'checkpoint.action_reason', + type: 'integer', + }, + 'checkpoint.c_bytes': { + category: 'checkpoint', + description: 'Boolean value indicates whether bytes sent from the client side are used. ', + name: 'checkpoint.c_bytes', + type: 'integer', + }, + 'checkpoint.context_num': { + category: 'checkpoint', + description: 'Serial number of the log for a specific connection. ', + name: 'checkpoint.context_num', + type: 'integer', + }, + 'checkpoint.match_id': { + category: 'checkpoint', + description: 'Private key of the rule ', + name: 'checkpoint.match_id', + type: 'integer', + }, + 'checkpoint.alert': { + category: 'checkpoint', + description: 'Alert level of matched rule (for connection logs). ', + name: 'checkpoint.alert', + type: 'keyword', + }, + 'checkpoint.parent_rule': { + category: 'checkpoint', + description: 'Parent rule number, in case of inline layer. ', + name: 'checkpoint.parent_rule', + type: 'integer', + }, + 'checkpoint.match_fk': { + category: 'checkpoint', + description: 'Rule number. ', + name: 'checkpoint.match_fk', + type: 'integer', + }, + 'checkpoint.dropped_outgoing': { + category: 'checkpoint', + description: 'Number of outgoing bytes dropped when using UP-limit feature. ', + name: 'checkpoint.dropped_outgoing', + type: 'integer', + }, + 'checkpoint.dropped_incoming': { + category: 'checkpoint', + description: 'Number of incoming bytes dropped when using UP-limit feature. ', + name: 'checkpoint.dropped_incoming', + type: 'integer', + }, + 'checkpoint.media_type': { + category: 'checkpoint', + description: 'Media used (audio, video, etc.) ', + name: 'checkpoint.media_type', + type: 'keyword', + }, + 'checkpoint.sip_reason': { + category: 'checkpoint', + description: "Explains why 'source_ip' isn't allowed to redirect (handover). ", + name: 'checkpoint.sip_reason', + type: 'keyword', + }, + 'checkpoint.voip_method': { + category: 'checkpoint', + description: 'Registration request. ', + name: 'checkpoint.voip_method', + type: 'keyword', + }, + 'checkpoint.registered_ip-phones': { + category: 'checkpoint', + description: 'Registered IP-Phones. ', + name: 'checkpoint.registered_ip-phones', + type: 'keyword', + }, + 'checkpoint.voip_reg_user_type': { + category: 'checkpoint', + description: 'Registered IP-Phone type. ', + name: 'checkpoint.voip_reg_user_type', + type: 'keyword', + }, + 'checkpoint.voip_call_id': { + category: 'checkpoint', + description: 'Call-ID. ', + name: 'checkpoint.voip_call_id', + type: 'keyword', + }, + 'checkpoint.voip_reg_int': { + category: 'checkpoint', + description: 'Registration port. ', + name: 'checkpoint.voip_reg_int', + type: 'integer', + }, + 'checkpoint.voip_reg_ipp': { + category: 'checkpoint', + description: 'Registration IP protocol. ', + name: 'checkpoint.voip_reg_ipp', + type: 'integer', + }, + 'checkpoint.voip_reg_period': { + category: 'checkpoint', + description: 'Registration period. ', + name: 'checkpoint.voip_reg_period', + type: 'integer', + }, + 'checkpoint.src_phone_number': { + category: 'checkpoint', + description: 'Source IP-Phone. ', + name: 'checkpoint.src_phone_number', + type: 'keyword', + }, + 'checkpoint.voip_from_user_type': { + category: 'checkpoint', + description: 'Source IP-Phone type. ', + name: 'checkpoint.voip_from_user_type', + type: 'keyword', + }, + 'checkpoint.voip_to_user_type': { + category: 'checkpoint', + description: 'Destination IP-Phone type. ', + name: 'checkpoint.voip_to_user_type', + type: 'keyword', + }, + 'checkpoint.voip_call_dir': { + category: 'checkpoint', + description: 'Call direction: in/out. ', + name: 'checkpoint.voip_call_dir', + type: 'keyword', + }, + 'checkpoint.voip_call_state': { + category: 'checkpoint', + description: 'Call state. Possible values: in/out. ', + name: 'checkpoint.voip_call_state', + type: 'keyword', + }, + 'checkpoint.voip_call_term_time': { + category: 'checkpoint', + description: 'Call termination time stamp. ', + name: 'checkpoint.voip_call_term_time', + type: 'keyword', + }, + 'checkpoint.voip_duration': { + category: 'checkpoint', + description: 'Call duration (seconds). ', + name: 'checkpoint.voip_duration', + type: 'keyword', + }, + 'checkpoint.voip_media_port': { + category: 'checkpoint', + description: 'Media int. ', + name: 'checkpoint.voip_media_port', + type: 'keyword', + }, + 'checkpoint.voip_media_ipp': { + category: 'checkpoint', + description: 'Media IP protocol. ', + name: 'checkpoint.voip_media_ipp', + type: 'keyword', + }, + 'checkpoint.voip_est_codec': { + category: 'checkpoint', + description: 'Estimated codec. ', + name: 'checkpoint.voip_est_codec', + type: 'keyword', + }, + 'checkpoint.voip_exp': { + category: 'checkpoint', + description: 'Expiration. ', + name: 'checkpoint.voip_exp', + type: 'integer', + }, + 'checkpoint.voip_attach_sz': { + category: 'checkpoint', + description: 'Attachment size. ', + name: 'checkpoint.voip_attach_sz', + type: 'integer', + }, + 'checkpoint.voip_attach_action_info': { + category: 'checkpoint', + description: 'Attachment action Info. ', + name: 'checkpoint.voip_attach_action_info', + type: 'keyword', + }, + 'checkpoint.voip_media_codec': { + category: 'checkpoint', + description: 'Estimated codec. ', + name: 'checkpoint.voip_media_codec', + type: 'keyword', + }, + 'checkpoint.voip_reject_reason': { + category: 'checkpoint', + description: 'Reject reason. ', + name: 'checkpoint.voip_reject_reason', + type: 'keyword', + }, + 'checkpoint.voip_reason_info': { + category: 'checkpoint', + description: 'Information. ', + name: 'checkpoint.voip_reason_info', + type: 'keyword', + }, + 'checkpoint.voip_config': { + category: 'checkpoint', + description: 'Configuration. ', + name: 'checkpoint.voip_config', + type: 'keyword', + }, + 'checkpoint.voip_reg_server': { + category: 'checkpoint', + description: 'Registrar server IP address. ', + name: 'checkpoint.voip_reg_server', + type: 'ip', + }, + 'checkpoint.scv_user': { + category: 'checkpoint', + description: 'Username whose packets are dropped on SCV. ', + name: 'checkpoint.scv_user', + type: 'keyword', + }, + 'checkpoint.scv_message_info': { + category: 'checkpoint', + description: 'Drop reason. ', + name: 'checkpoint.scv_message_info', + type: 'keyword', + }, + 'checkpoint.ppp': { + category: 'checkpoint', + description: 'Authentication status. ', + name: 'checkpoint.ppp', + type: 'keyword', + }, + 'checkpoint.scheme': { + category: 'checkpoint', + description: 'Describes the scheme used for the log. ', + name: 'checkpoint.scheme', + type: 'keyword', + }, + 'checkpoint.machine': { + category: 'checkpoint', + description: 'L2TP machine which triggered the log and the log refers to it. ', + name: 'checkpoint.machine', + type: 'keyword', + }, + 'checkpoint.vpn_feature_name': { + category: 'checkpoint', + description: 'L2TP /IKE / Link Selection. ', + name: 'checkpoint.vpn_feature_name', + type: 'keyword', + }, + 'checkpoint.reject_category': { + category: 'checkpoint', + description: 'Authentication failure reason. ', + name: 'checkpoint.reject_category', + type: 'keyword', + }, + 'checkpoint.peer_ip_probing_status_update': { + category: 'checkpoint', + description: 'IP address response status. ', + name: 'checkpoint.peer_ip_probing_status_update', + type: 'keyword', + }, + 'checkpoint.peer_ip': { + category: 'checkpoint', + description: 'IP address which the client connects to. ', + name: 'checkpoint.peer_ip', + type: 'keyword', + }, + 'checkpoint.link_probing_status_update': { + category: 'checkpoint', + description: 'IP address response status. ', + name: 'checkpoint.link_probing_status_update', + type: 'keyword', + }, + 'checkpoint.source_interface': { + category: 'checkpoint', + description: 'External Interface name for source interface or Null if not found. ', + name: 'checkpoint.source_interface', + type: 'keyword', + }, + 'checkpoint.next_hop_ip': { + category: 'checkpoint', + description: 'Next hop IP address. ', + name: 'checkpoint.next_hop_ip', + type: 'keyword', + }, + 'checkpoint.srckeyid': { + category: 'checkpoint', + description: 'Initiator Spi ID. ', + name: 'checkpoint.srckeyid', + type: 'keyword', + }, + 'checkpoint.dstkeyid': { + category: 'checkpoint', + description: 'Responder Spi ID. ', + name: 'checkpoint.dstkeyid', + type: 'keyword', + }, + 'checkpoint.encryption_failure': { + category: 'checkpoint', + description: 'Message indicating why the encryption failed. ', + name: 'checkpoint.encryption_failure', + type: 'keyword', + }, + 'checkpoint.ike_ids': { + category: 'checkpoint', + description: 'All QM ids. ', + name: 'checkpoint.ike_ids', + type: 'keyword', + }, + 'checkpoint.community': { + category: 'checkpoint', + description: 'Community name for the IPSec key and the use of the IKEv. ', + name: 'checkpoint.community', + type: 'keyword', + }, + 'checkpoint.ike': { + category: 'checkpoint', + description: 'IKEMode (PHASE1, PHASE2, etc..). ', + name: 'checkpoint.ike', + type: 'keyword', + }, + 'checkpoint.cookieI': { + category: 'checkpoint', + description: 'Initiator cookie. ', + name: 'checkpoint.cookieI', + type: 'keyword', + }, + 'checkpoint.cookieR': { + category: 'checkpoint', + description: 'Responder cookie. ', + name: 'checkpoint.cookieR', + type: 'keyword', + }, + 'checkpoint.msgid': { + category: 'checkpoint', + description: 'Message ID. ', + name: 'checkpoint.msgid', + type: 'keyword', + }, + 'checkpoint.methods': { + category: 'checkpoint', + description: 'IPSEc methods. ', + name: 'checkpoint.methods', + type: 'keyword', + }, + 'checkpoint.connection_uid': { + category: 'checkpoint', + description: 'Calculation of md5 of the IP and user name as UID. ', + name: 'checkpoint.connection_uid', + type: 'keyword', + }, + 'checkpoint.site_name': { + category: 'checkpoint', + description: 'Site name. ', + name: 'checkpoint.site_name', + type: 'keyword', + }, + 'checkpoint.esod_rule_name': { + category: 'checkpoint', + description: 'Unknown rule name. ', + name: 'checkpoint.esod_rule_name', + type: 'keyword', + }, + 'checkpoint.esod_rule_action': { + category: 'checkpoint', + description: 'Unknown rule action. ', + name: 'checkpoint.esod_rule_action', + type: 'keyword', + }, + 'checkpoint.esod_rule_type': { + category: 'checkpoint', + description: 'Unknown rule type. ', + name: 'checkpoint.esod_rule_type', + type: 'keyword', + }, + 'checkpoint.esod_noncompliance_reason': { + category: 'checkpoint', + description: 'Non-compliance reason. ', + name: 'checkpoint.esod_noncompliance_reason', + type: 'keyword', + }, + 'checkpoint.esod_associated_policies': { + category: 'checkpoint', + description: 'Associated policies. ', + name: 'checkpoint.esod_associated_policies', + type: 'keyword', + }, + 'checkpoint.spyware_type': { + category: 'checkpoint', + description: 'Spyware type. ', + name: 'checkpoint.spyware_type', + type: 'keyword', + }, + 'checkpoint.anti_virus_type': { + category: 'checkpoint', + description: 'Anti virus type. ', + name: 'checkpoint.anti_virus_type', + type: 'keyword', + }, + 'checkpoint.end_user_firewall_type': { + category: 'checkpoint', + description: 'End user firewall type. ', + name: 'checkpoint.end_user_firewall_type', + type: 'keyword', + }, + 'checkpoint.esod_scan_status': { + category: 'checkpoint', + description: 'Scan failed. ', + name: 'checkpoint.esod_scan_status', + type: 'keyword', + }, + 'checkpoint.esod_access_status': { + category: 'checkpoint', + description: 'Access denied. ', + name: 'checkpoint.esod_access_status', + type: 'keyword', + }, + 'checkpoint.client_type': { + category: 'checkpoint', + description: 'Endpoint Connect. ', + name: 'checkpoint.client_type', + type: 'keyword', + }, + 'checkpoint.precise_error': { + category: 'checkpoint', + description: 'HTTP parser error. ', + name: 'checkpoint.precise_error', + type: 'keyword', + }, + 'checkpoint.method': { + category: 'checkpoint', + description: 'HTTP method. ', + name: 'checkpoint.method', + type: 'keyword', + }, + 'checkpoint.trusted_domain': { + category: 'checkpoint', + description: 'In case of phishing event, the domain, which the attacker was impersonating. ', + name: 'checkpoint.trusted_domain', + type: 'keyword', + }, + 'cisco.asa.message_id': { + category: 'cisco', + description: 'The Cisco ASA message identifier. ', + name: 'cisco.asa.message_id', + type: 'keyword', + }, + 'cisco.asa.suffix': { + category: 'cisco', + description: 'Optional suffix after %ASA identifier. ', + example: 'session', + name: 'cisco.asa.suffix', + type: 'keyword', + }, + 'cisco.asa.source_interface': { + category: 'cisco', + description: 'Source interface for the flow or event. ', + name: 'cisco.asa.source_interface', + type: 'keyword', + }, + 'cisco.asa.destination_interface': { + category: 'cisco', + description: 'Destination interface for the flow or event. ', + name: 'cisco.asa.destination_interface', + type: 'keyword', + }, + 'cisco.asa.rule_name': { + category: 'cisco', + description: 'Name of the Access Control List rule that matched this event. ', + name: 'cisco.asa.rule_name', + type: 'keyword', + }, + 'cisco.asa.source_username': { + category: 'cisco', + description: 'Name of the user that is the source for this event. ', + name: 'cisco.asa.source_username', + type: 'keyword', + }, + 'cisco.asa.destination_username': { + category: 'cisco', + description: 'Name of the user that is the destination for this event. ', + name: 'cisco.asa.destination_username', + type: 'keyword', + }, + 'cisco.asa.mapped_source_ip': { + category: 'cisco', + description: 'The translated source IP address. ', + name: 'cisco.asa.mapped_source_ip', + type: 'ip', + }, + 'cisco.asa.mapped_source_host': { + category: 'cisco', + description: 'The translated source host. ', + name: 'cisco.asa.mapped_source_host', + type: 'keyword', + }, + 'cisco.asa.mapped_source_port': { + category: 'cisco', + description: 'The translated source port. ', + name: 'cisco.asa.mapped_source_port', + type: 'long', + }, + 'cisco.asa.mapped_destination_ip': { + category: 'cisco', + description: 'The translated destination IP address. ', + name: 'cisco.asa.mapped_destination_ip', + type: 'ip', + }, + 'cisco.asa.mapped_destination_host': { + category: 'cisco', + description: 'The translated destination host. ', + name: 'cisco.asa.mapped_destination_host', + type: 'keyword', + }, + 'cisco.asa.mapped_destination_port': { + category: 'cisco', + description: 'The translated destination port. ', + name: 'cisco.asa.mapped_destination_port', + type: 'long', + }, + 'cisco.asa.threat_level': { + category: 'cisco', + description: + 'Threat level for malware / botnet traffic. One of very-low, low, moderate, high or very-high. ', + name: 'cisco.asa.threat_level', + type: 'keyword', + }, + 'cisco.asa.threat_category': { + category: 'cisco', + description: + 'Category for the malware / botnet traffic. For example: virus, botnet, trojan, etc. ', + name: 'cisco.asa.threat_category', + type: 'keyword', + }, + 'cisco.asa.connection_id': { + category: 'cisco', + description: 'Unique identifier for a flow. ', + name: 'cisco.asa.connection_id', + type: 'keyword', + }, + 'cisco.asa.icmp_type': { + category: 'cisco', + description: 'ICMP type. ', + name: 'cisco.asa.icmp_type', + type: 'short', + }, + 'cisco.asa.icmp_code': { + category: 'cisco', + description: 'ICMP code. ', + name: 'cisco.asa.icmp_code', + type: 'short', + }, + 'cisco.asa.connection_type': { + category: 'cisco', + description: 'The VPN connection type ', + name: 'cisco.asa.connection_type', + type: 'keyword', + }, + 'cisco.asa.dap_records': { + category: 'cisco', + description: 'The assigned DAP records ', + name: 'cisco.asa.dap_records', + type: 'keyword', + }, + 'cisco.ftd.message_id': { + category: 'cisco', + description: 'The Cisco FTD message identifier. ', + name: 'cisco.ftd.message_id', + type: 'keyword', + }, + 'cisco.ftd.suffix': { + category: 'cisco', + description: 'Optional suffix after %FTD identifier. ', + example: 'session', + name: 'cisco.ftd.suffix', + type: 'keyword', + }, + 'cisco.ftd.source_interface': { + category: 'cisco', + description: 'Source interface for the flow or event. ', + name: 'cisco.ftd.source_interface', + type: 'keyword', + }, + 'cisco.ftd.destination_interface': { + category: 'cisco', + description: 'Destination interface for the flow or event. ', + name: 'cisco.ftd.destination_interface', + type: 'keyword', + }, + 'cisco.ftd.rule_name': { + category: 'cisco', + description: 'Name of the Access Control List rule that matched this event. ', + name: 'cisco.ftd.rule_name', + type: 'keyword', + }, + 'cisco.ftd.source_username': { + category: 'cisco', + description: 'Name of the user that is the source for this event. ', + name: 'cisco.ftd.source_username', + type: 'keyword', + }, + 'cisco.ftd.destination_username': { + category: 'cisco', + description: 'Name of the user that is the destination for this event. ', + name: 'cisco.ftd.destination_username', + type: 'keyword', + }, + 'cisco.ftd.mapped_source_ip': { + category: 'cisco', + description: 'The translated source IP address. Use ECS source.nat.ip. ', + name: 'cisco.ftd.mapped_source_ip', + type: 'ip', + }, + 'cisco.ftd.mapped_source_host': { + category: 'cisco', + description: 'The translated source host. ', + name: 'cisco.ftd.mapped_source_host', + type: 'keyword', + }, + 'cisco.ftd.mapped_source_port': { + category: 'cisco', + description: 'The translated source port. Use ECS source.nat.port. ', + name: 'cisco.ftd.mapped_source_port', + type: 'long', + }, + 'cisco.ftd.mapped_destination_ip': { + category: 'cisco', + description: 'The translated destination IP address. Use ECS destination.nat.ip. ', + name: 'cisco.ftd.mapped_destination_ip', + type: 'ip', + }, + 'cisco.ftd.mapped_destination_host': { + category: 'cisco', + description: 'The translated destination host. ', + name: 'cisco.ftd.mapped_destination_host', + type: 'keyword', + }, + 'cisco.ftd.mapped_destination_port': { + category: 'cisco', + description: 'The translated destination port. Use ECS destination.nat.port. ', + name: 'cisco.ftd.mapped_destination_port', + type: 'long', + }, + 'cisco.ftd.threat_level': { + category: 'cisco', + description: + 'Threat level for malware / botnet traffic. One of very-low, low, moderate, high or very-high. ', + name: 'cisco.ftd.threat_level', + type: 'keyword', + }, + 'cisco.ftd.threat_category': { + category: 'cisco', + description: + 'Category for the malware / botnet traffic. For example: virus, botnet, trojan, etc. ', + name: 'cisco.ftd.threat_category', + type: 'keyword', + }, + 'cisco.ftd.connection_id': { + category: 'cisco', + description: 'Unique identifier for a flow. ', + name: 'cisco.ftd.connection_id', + type: 'keyword', + }, + 'cisco.ftd.icmp_type': { + category: 'cisco', + description: 'ICMP type. ', + name: 'cisco.ftd.icmp_type', + type: 'short', + }, + 'cisco.ftd.icmp_code': { + category: 'cisco', + description: 'ICMP code. ', + name: 'cisco.ftd.icmp_code', + type: 'short', + }, + 'cisco.ftd.security': { + category: 'cisco', + description: 'Raw fields for Security Events.', + name: 'cisco.ftd.security', + type: 'object', + }, + 'cisco.ftd.connection_type': { + category: 'cisco', + description: 'The VPN connection type ', + name: 'cisco.ftd.connection_type', + type: 'keyword', + }, + 'cisco.ftd.dap_records': { + category: 'cisco', + description: 'The assigned DAP records ', + name: 'cisco.ftd.dap_records', + type: 'keyword', + }, + 'cisco.ios.access_list': { + category: 'cisco', + description: 'Name of the IP access list. ', + name: 'cisco.ios.access_list', + type: 'keyword', + }, + 'cisco.ios.facility': { + category: 'cisco', + description: + 'The facility to which the message refers (for example, SNMP, SYS, and so forth). A facility can be a hardware device, a protocol, or a module of the system software. It denotes the source or the cause of the system message. ', + example: 'SEC', + name: 'cisco.ios.facility', + type: 'keyword', + }, + 'coredns.id': { + category: 'coredns', + description: 'id of the DNS transaction ', + name: 'coredns.id', + type: 'keyword', + }, + 'coredns.query.size': { + category: 'coredns', + description: 'size of the DNS query ', + name: 'coredns.query.size', + type: 'integer', + format: 'bytes', + }, + 'coredns.query.class': { + category: 'coredns', + description: 'DNS query class ', + name: 'coredns.query.class', + type: 'keyword', + }, + 'coredns.query.name': { + category: 'coredns', + description: 'DNS query name ', + name: 'coredns.query.name', + type: 'keyword', + }, + 'coredns.query.type': { + category: 'coredns', + description: 'DNS query type ', + name: 'coredns.query.type', + type: 'keyword', + }, + 'coredns.response.code': { + category: 'coredns', + description: 'DNS response code ', + name: 'coredns.response.code', + type: 'keyword', + }, + 'coredns.response.flags': { + category: 'coredns', + description: 'DNS response flags ', + name: 'coredns.response.flags', + type: 'keyword', + }, + 'coredns.response.size': { + category: 'coredns', + description: 'size of the DNS response ', + name: 'coredns.response.size', + type: 'integer', + format: 'bytes', + }, + 'coredns.dnssec_ok': { + category: 'coredns', + description: 'dnssec flag ', + name: 'coredns.dnssec_ok', + type: 'boolean', + }, + 'crowdstrike.metadata.eventType': { + category: 'crowdstrike', + description: + 'DetectionSummaryEvent, FirewallMatchEvent, IncidentSummaryEvent, RemoteResponseSessionStartEvent, RemoteResponseSessionEndEvent, AuthActivityAuditEvent, or UserActivityAuditEvent ', + name: 'crowdstrike.metadata.eventType', + type: 'keyword', + }, + 'crowdstrike.metadata.eventCreationTime': { + category: 'crowdstrike', + description: 'The time this event occurred on the endpoint in UTC UNIX_MS format. ', + name: 'crowdstrike.metadata.eventCreationTime', + type: 'date', + }, + 'crowdstrike.metadata.offset': { + category: 'crowdstrike', + description: + 'Offset number that tracks the location of the event in stream. This is used to identify unique detection events. ', + name: 'crowdstrike.metadata.offset', + type: 'integer', + }, + 'crowdstrike.metadata.customerIDString': { + category: 'crowdstrike', + description: 'Customer identifier ', + name: 'crowdstrike.metadata.customerIDString', + type: 'keyword', + }, + 'crowdstrike.metadata.version': { + category: 'crowdstrike', + description: 'Schema version ', + name: 'crowdstrike.metadata.version', + type: 'keyword', + }, + 'crowdstrike.event.ProcessStartTime': { + category: 'crowdstrike', + description: 'The process start time in UTC UNIX_MS format. ', + name: 'crowdstrike.event.ProcessStartTime', + type: 'date', + }, + 'crowdstrike.event.ProcessEndTime': { + category: 'crowdstrike', + description: 'The process termination time in UTC UNIX_MS format. ', + name: 'crowdstrike.event.ProcessEndTime', + type: 'date', + }, + 'crowdstrike.event.ProcessId': { + category: 'crowdstrike', + description: 'Process ID related to the detection. ', + name: 'crowdstrike.event.ProcessId', + type: 'integer', + }, + 'crowdstrike.event.ParentProcessId': { + category: 'crowdstrike', + description: 'Parent process ID related to the detection. ', + name: 'crowdstrike.event.ParentProcessId', + type: 'integer', + }, + 'crowdstrike.event.ComputerName': { + category: 'crowdstrike', + description: 'Name of the computer where the detection occurred. ', + name: 'crowdstrike.event.ComputerName', + type: 'keyword', + }, + 'crowdstrike.event.UserName': { + category: 'crowdstrike', + description: 'User name associated with the detection. ', + name: 'crowdstrike.event.UserName', + type: 'keyword', + }, + 'crowdstrike.event.DetectName': { + category: 'crowdstrike', + description: 'Name of the detection. ', + name: 'crowdstrike.event.DetectName', + type: 'keyword', + }, + 'crowdstrike.event.DetectDescription': { + category: 'crowdstrike', + description: 'Description of the detection. ', + name: 'crowdstrike.event.DetectDescription', + type: 'keyword', + }, + 'crowdstrike.event.Severity': { + category: 'crowdstrike', + description: 'Severity score of the detection. ', + name: 'crowdstrike.event.Severity', + type: 'integer', + }, + 'crowdstrike.event.SeverityName': { + category: 'crowdstrike', + description: 'Severity score text. ', + name: 'crowdstrike.event.SeverityName', + type: 'keyword', + }, + 'crowdstrike.event.FileName': { + category: 'crowdstrike', + description: 'File name of the associated process for the detection. ', + name: 'crowdstrike.event.FileName', + type: 'keyword', + }, + 'crowdstrike.event.FilePath': { + category: 'crowdstrike', + description: 'Path of the executable associated with the detection. ', + name: 'crowdstrike.event.FilePath', + type: 'keyword', + }, + 'crowdstrike.event.CommandLine': { + category: 'crowdstrike', + description: 'Executable path with command line arguments. ', + name: 'crowdstrike.event.CommandLine', + type: 'keyword', + }, + 'crowdstrike.event.SHA1String': { + category: 'crowdstrike', + description: 'SHA1 sum of the executable associated with the detection. ', + name: 'crowdstrike.event.SHA1String', + type: 'keyword', + }, + 'crowdstrike.event.SHA256String': { + category: 'crowdstrike', + description: 'SHA256 sum of the executable associated with the detection. ', + name: 'crowdstrike.event.SHA256String', + type: 'keyword', + }, + 'crowdstrike.event.MD5String': { + category: 'crowdstrike', + description: 'MD5 sum of the executable associated with the detection. ', + name: 'crowdstrike.event.MD5String', + type: 'keyword', + }, + 'crowdstrike.event.MachineDomain': { + category: 'crowdstrike', + description: 'Domain for the machine associated with the detection. ', + name: 'crowdstrike.event.MachineDomain', + type: 'keyword', + }, + 'crowdstrike.event.FalconHostLink': { + category: 'crowdstrike', + description: 'URL to view the detection in Falcon. ', + name: 'crowdstrike.event.FalconHostLink', + type: 'keyword', + }, + 'crowdstrike.event.SensorId': { + category: 'crowdstrike', + description: 'Unique ID associated with the Falcon sensor. ', + name: 'crowdstrike.event.SensorId', + type: 'keyword', + }, + 'crowdstrike.event.DetectId': { + category: 'crowdstrike', + description: 'Unique ID associated with the detection. ', + name: 'crowdstrike.event.DetectId', + type: 'keyword', + }, + 'crowdstrike.event.LocalIP': { + category: 'crowdstrike', + description: 'IP address of the host associated with the detection. ', + name: 'crowdstrike.event.LocalIP', + type: 'keyword', + }, + 'crowdstrike.event.MACAddress': { + category: 'crowdstrike', + description: 'MAC address of the host associated with the detection. ', + name: 'crowdstrike.event.MACAddress', + type: 'keyword', + }, + 'crowdstrike.event.Tactic': { + category: 'crowdstrike', + description: 'MITRE tactic category of the detection. ', + name: 'crowdstrike.event.Tactic', + type: 'keyword', + }, + 'crowdstrike.event.Technique': { + category: 'crowdstrike', + description: 'MITRE technique category of the detection. ', + name: 'crowdstrike.event.Technique', + type: 'keyword', + }, + 'crowdstrike.event.Objective': { + category: 'crowdstrike', + description: 'Method of detection. ', + name: 'crowdstrike.event.Objective', + type: 'keyword', + }, + 'crowdstrike.event.PatternDispositionDescription': { + category: 'crowdstrike', + description: 'Action taken by Falcon. ', + name: 'crowdstrike.event.PatternDispositionDescription', + type: 'keyword', + }, + 'crowdstrike.event.PatternDispositionValue': { + category: 'crowdstrike', + description: 'Unique ID associated with action taken. ', + name: 'crowdstrike.event.PatternDispositionValue', + type: 'integer', + }, + 'crowdstrike.event.PatternDispositionFlags': { + category: 'crowdstrike', + description: 'Flags indicating actions taken. ', + name: 'crowdstrike.event.PatternDispositionFlags', + type: 'object', + }, + 'crowdstrike.event.State': { + category: 'crowdstrike', + description: 'Whether the incident summary is open and ongoing or closed. ', + name: 'crowdstrike.event.State', + type: 'keyword', + }, + 'crowdstrike.event.IncidentStartTime': { + category: 'crowdstrike', + description: 'Start time for the incident in UTC UNIX format. ', + name: 'crowdstrike.event.IncidentStartTime', + type: 'date', + }, + 'crowdstrike.event.IncidentEndTime': { + category: 'crowdstrike', + description: 'End time for the incident in UTC UNIX format. ', + name: 'crowdstrike.event.IncidentEndTime', + type: 'date', + }, + 'crowdstrike.event.FineScore': { + category: 'crowdstrike', + description: 'Score for incident. ', + name: 'crowdstrike.event.FineScore', + type: 'float', + }, + 'crowdstrike.event.UserId': { + category: 'crowdstrike', + description: 'Email address or user ID associated with the event. ', + name: 'crowdstrike.event.UserId', + type: 'keyword', + }, + 'crowdstrike.event.UserIp': { + category: 'crowdstrike', + description: 'IP address associated with the user. ', + name: 'crowdstrike.event.UserIp', + type: 'keyword', + }, + 'crowdstrike.event.OperationName': { + category: 'crowdstrike', + description: 'Event subtype. ', + name: 'crowdstrike.event.OperationName', + type: 'keyword', + }, + 'crowdstrike.event.ServiceName': { + category: 'crowdstrike', + description: 'Service associated with this event. ', + name: 'crowdstrike.event.ServiceName', + type: 'keyword', + }, + 'crowdstrike.event.Success': { + category: 'crowdstrike', + description: 'Indicator of whether or not this event was successful. ', + name: 'crowdstrike.event.Success', + type: 'boolean', + }, + 'crowdstrike.event.UTCTimestamp': { + category: 'crowdstrike', + description: 'Timestamp associated with this event in UTC UNIX format. ', + name: 'crowdstrike.event.UTCTimestamp', + type: 'date', + }, + 'crowdstrike.event.AuditKeyValues': { + category: 'crowdstrike', + description: 'Fields that were changed in this event. ', + name: 'crowdstrike.event.AuditKeyValues', + type: 'nested', + }, + 'crowdstrike.event.ExecutablesWritten': { + category: 'crowdstrike', + description: 'Detected executables written to disk by a process. ', + name: 'crowdstrike.event.ExecutablesWritten', + type: 'nested', + }, + 'crowdstrike.event.SessionId': { + category: 'crowdstrike', + description: 'Session ID of the remote response session. ', + name: 'crowdstrike.event.SessionId', + type: 'keyword', + }, + 'crowdstrike.event.HostnameField': { + category: 'crowdstrike', + description: 'Host name of the machine for the remote session. ', + name: 'crowdstrike.event.HostnameField', + type: 'keyword', + }, + 'crowdstrike.event.StartTimestamp': { + category: 'crowdstrike', + description: 'Start time for the remote session in UTC UNIX format. ', + name: 'crowdstrike.event.StartTimestamp', + type: 'date', + }, + 'crowdstrike.event.EndTimestamp': { + category: 'crowdstrike', + description: 'End time for the remote session in UTC UNIX format. ', + name: 'crowdstrike.event.EndTimestamp', + type: 'date', + }, + 'crowdstrike.event.LateralMovement': { + category: 'crowdstrike', + description: 'Lateral movement field for incident. ', + name: 'crowdstrike.event.LateralMovement', + type: 'long', + }, + 'crowdstrike.event.ParentImageFileName': { + category: 'crowdstrike', + description: 'Path to the parent process. ', + name: 'crowdstrike.event.ParentImageFileName', + type: 'keyword', + }, + 'crowdstrike.event.ParentCommandLine': { + category: 'crowdstrike', + description: 'Parent process command line arguments. ', + name: 'crowdstrike.event.ParentCommandLine', + type: 'keyword', + }, + 'crowdstrike.event.GrandparentImageFileName': { + category: 'crowdstrike', + description: 'Path to the grandparent process. ', + name: 'crowdstrike.event.GrandparentImageFileName', + type: 'keyword', + }, + 'crowdstrike.event.GrandparentCommandLine': { + category: 'crowdstrike', + description: 'Grandparent process command line arguments. ', + name: 'crowdstrike.event.GrandparentCommandLine', + type: 'keyword', + }, + 'crowdstrike.event.IOCType': { + category: 'crowdstrike', + description: 'CrowdStrike type for indicator of compromise. ', + name: 'crowdstrike.event.IOCType', + type: 'keyword', + }, + 'crowdstrike.event.IOCValue': { + category: 'crowdstrike', + description: 'CrowdStrike value for indicator of compromise. ', + name: 'crowdstrike.event.IOCValue', + type: 'keyword', + }, + 'crowdstrike.event.CustomerId': { + category: 'crowdstrike', + description: 'Customer identifier. ', + name: 'crowdstrike.event.CustomerId', + type: 'keyword', + }, + 'crowdstrike.event.DeviceId': { + category: 'crowdstrike', + description: 'Device on which the event occurred. ', + name: 'crowdstrike.event.DeviceId', + type: 'keyword', + }, + 'crowdstrike.event.Ipv': { + category: 'crowdstrike', + description: 'Protocol for network request. ', + name: 'crowdstrike.event.Ipv', + type: 'keyword', + }, + 'crowdstrike.event.ConnectionDirection': { + category: 'crowdstrike', + description: 'Direction for network connection. ', + name: 'crowdstrike.event.ConnectionDirection', + type: 'keyword', + }, + 'crowdstrike.event.EventType': { + category: 'crowdstrike', + description: 'CrowdStrike provided event type. ', + name: 'crowdstrike.event.EventType', + type: 'keyword', + }, + 'crowdstrike.event.HostName': { + category: 'crowdstrike', + description: 'Host name of the local machine. ', + name: 'crowdstrike.event.HostName', + type: 'keyword', + }, + 'crowdstrike.event.ICMPCode': { + category: 'crowdstrike', + description: 'RFC2780 ICMP Code field. ', + name: 'crowdstrike.event.ICMPCode', + type: 'keyword', + }, + 'crowdstrike.event.ICMPType': { + category: 'crowdstrike', + description: 'RFC2780 ICMP Type field. ', + name: 'crowdstrike.event.ICMPType', + type: 'keyword', + }, + 'crowdstrike.event.ImageFileName': { + category: 'crowdstrike', + description: 'File name of the associated process for the detection. ', + name: 'crowdstrike.event.ImageFileName', + type: 'keyword', + }, + 'crowdstrike.event.PID': { + category: 'crowdstrike', + description: 'Associated process id for the detection. ', + name: 'crowdstrike.event.PID', + type: 'long', + }, + 'crowdstrike.event.LocalAddress': { + category: 'crowdstrike', + description: 'IP address of local machine. ', + name: 'crowdstrike.event.LocalAddress', + type: 'ip', + }, + 'crowdstrike.event.LocalPort': { + category: 'crowdstrike', + description: 'Port of local machine. ', + name: 'crowdstrike.event.LocalPort', + type: 'long', + }, + 'crowdstrike.event.RemoteAddress': { + category: 'crowdstrike', + description: 'IP address of remote machine. ', + name: 'crowdstrike.event.RemoteAddress', + type: 'ip', + }, + 'crowdstrike.event.RemotePort': { + category: 'crowdstrike', + description: 'Port of remote machine. ', + name: 'crowdstrike.event.RemotePort', + type: 'long', + }, + 'crowdstrike.event.RuleAction': { + category: 'crowdstrike', + description: 'Firewall rule action. ', + name: 'crowdstrike.event.RuleAction', + type: 'keyword', + }, + 'crowdstrike.event.RuleDescription': { + category: 'crowdstrike', + description: 'Firewall rule description. ', + name: 'crowdstrike.event.RuleDescription', + type: 'keyword', + }, + 'crowdstrike.event.RuleFamilyID': { + category: 'crowdstrike', + description: 'Firewall rule family id. ', + name: 'crowdstrike.event.RuleFamilyID', + type: 'keyword', + }, + 'crowdstrike.event.RuleGroupName': { + category: 'crowdstrike', + description: 'Firewall rule group name. ', + name: 'crowdstrike.event.RuleGroupName', + type: 'keyword', + }, + 'crowdstrike.event.RuleName': { + category: 'crowdstrike', + description: 'Firewall rule name. ', + name: 'crowdstrike.event.RuleName', + type: 'keyword', + }, + 'crowdstrike.event.RuleId': { + category: 'crowdstrike', + description: 'Firewall rule id. ', + name: 'crowdstrike.event.RuleId', + type: 'keyword', + }, + 'crowdstrike.event.MatchCount': { + category: 'crowdstrike', + description: 'Number of firewall rule matches. ', + name: 'crowdstrike.event.MatchCount', + type: 'long', + }, + 'crowdstrike.event.MatchCountSinceLastReport': { + category: 'crowdstrike', + description: 'Number of firewall rule matches since the last report. ', + name: 'crowdstrike.event.MatchCountSinceLastReport', + type: 'long', + }, + 'crowdstrike.event.Timestamp': { + category: 'crowdstrike', + description: 'Firewall rule triggered timestamp. ', + name: 'crowdstrike.event.Timestamp', + type: 'date', + }, + 'crowdstrike.event.Flags.Audit': { + category: 'crowdstrike', + description: 'CrowdStrike audit flag. ', + name: 'crowdstrike.event.Flags.Audit', + type: 'boolean', + }, + 'crowdstrike.event.Flags.Log': { + category: 'crowdstrike', + description: 'CrowdStrike log flag. ', + name: 'crowdstrike.event.Flags.Log', + type: 'boolean', + }, + 'crowdstrike.event.Flags.Monitor': { + category: 'crowdstrike', + description: 'CrowdStrike monitor flag. ', + name: 'crowdstrike.event.Flags.Monitor', + type: 'boolean', + }, + 'crowdstrike.event.Protocol': { + category: 'crowdstrike', + description: 'CrowdStrike provided protocol. ', + name: 'crowdstrike.event.Protocol', + type: 'keyword', + }, + 'crowdstrike.event.NetworkProfile': { + category: 'crowdstrike', + description: 'CrowdStrike network profile. ', + name: 'crowdstrike.event.NetworkProfile', + type: 'keyword', + }, + 'crowdstrike.event.PolicyName': { + category: 'crowdstrike', + description: 'CrowdStrike policy name. ', + name: 'crowdstrike.event.PolicyName', + type: 'keyword', + }, + 'crowdstrike.event.PolicyID': { + category: 'crowdstrike', + description: 'CrowdStrike policy id. ', + name: 'crowdstrike.event.PolicyID', + type: 'keyword', + }, + 'crowdstrike.event.Status': { + category: 'crowdstrike', + description: 'CrowdStrike status. ', + name: 'crowdstrike.event.Status', + type: 'keyword', + }, + 'crowdstrike.event.TreeID': { + category: 'crowdstrike', + description: 'CrowdStrike tree id. ', + name: 'crowdstrike.event.TreeID', + type: 'keyword', + }, + 'crowdstrike.event.Commands': { + category: 'crowdstrike', + description: 'Commands run in a remote session. ', + name: 'crowdstrike.event.Commands', + type: 'keyword', + }, + 'envoyproxy.log_type': { + category: 'envoyproxy', + description: 'Envoy log type, normally ACCESS ', + name: 'envoyproxy.log_type', + type: 'keyword', + }, + 'envoyproxy.response_flags': { + category: 'envoyproxy', + description: 'Response flags ', + name: 'envoyproxy.response_flags', + type: 'keyword', + }, + 'envoyproxy.upstream_service_time': { + category: 'envoyproxy', + description: 'Upstream service time in nanoseconds ', + name: 'envoyproxy.upstream_service_time', + type: 'long', + format: 'duration', + }, + 'envoyproxy.request_id': { + category: 'envoyproxy', + description: 'ID of the request ', + name: 'envoyproxy.request_id', + type: 'keyword', + }, + 'envoyproxy.authority': { + category: 'envoyproxy', + description: 'Envoy proxy authority field ', + name: 'envoyproxy.authority', + type: 'keyword', + }, + 'envoyproxy.proxy_type': { + category: 'envoyproxy', + description: 'Envoy proxy type, tcp or http ', + name: 'envoyproxy.proxy_type', + type: 'keyword', + }, + 'fortinet.file.hash.crc32': { + category: 'fortinet', + description: 'CRC32 Hash of file ', + name: 'fortinet.file.hash.crc32', + type: 'keyword', + }, + 'fortinet.firewall.acct_stat': { + category: 'fortinet', + description: 'Accounting state (RADIUS) ', + name: 'fortinet.firewall.acct_stat', + type: 'keyword', + }, + 'fortinet.firewall.acktime': { + category: 'fortinet', + description: 'Alarm Acknowledge Time ', + name: 'fortinet.firewall.acktime', + type: 'keyword', + }, + 'fortinet.firewall.act': { + category: 'fortinet', + description: 'Action ', + name: 'fortinet.firewall.act', + type: 'keyword', + }, + 'fortinet.firewall.action': { + category: 'fortinet', + description: 'Status of the session ', + name: 'fortinet.firewall.action', + type: 'keyword', + }, + 'fortinet.firewall.activity': { + category: 'fortinet', + description: 'HA activity message ', + name: 'fortinet.firewall.activity', + type: 'keyword', + }, + 'fortinet.firewall.addr': { + category: 'fortinet', + description: 'IP Address ', + name: 'fortinet.firewall.addr', + type: 'ip', + }, + 'fortinet.firewall.addr_type': { + category: 'fortinet', + description: 'Address Type ', + name: 'fortinet.firewall.addr_type', + type: 'keyword', + }, + 'fortinet.firewall.addrgrp': { + category: 'fortinet', + description: 'Address Group ', + name: 'fortinet.firewall.addrgrp', + type: 'keyword', + }, + 'fortinet.firewall.adgroup': { + category: 'fortinet', + description: 'AD Group Name ', + name: 'fortinet.firewall.adgroup', + type: 'keyword', + }, + 'fortinet.firewall.admin': { + category: 'fortinet', + description: 'Admin User ', + name: 'fortinet.firewall.admin', + type: 'keyword', + }, + 'fortinet.firewall.age': { + category: 'fortinet', + description: 'Time in seconds - time passed since last seen ', + name: 'fortinet.firewall.age', + type: 'integer', + }, + 'fortinet.firewall.agent': { + category: 'fortinet', + description: 'User agent - eg. agent="Mozilla/5.0" ', + name: 'fortinet.firewall.agent', + type: 'keyword', + }, + 'fortinet.firewall.alarmid': { + category: 'fortinet', + description: 'Alarm ID ', + name: 'fortinet.firewall.alarmid', + type: 'integer', + }, + 'fortinet.firewall.alert': { + category: 'fortinet', + description: 'Alert ', + name: 'fortinet.firewall.alert', + type: 'keyword', + }, + 'fortinet.firewall.analyticscksum': { + category: 'fortinet', + description: 'The checksum of the file submitted for analytics ', + name: 'fortinet.firewall.analyticscksum', + type: 'keyword', + }, + 'fortinet.firewall.analyticssubmit': { + category: 'fortinet', + description: 'The flag for analytics submission ', + name: 'fortinet.firewall.analyticssubmit', + type: 'keyword', + }, + 'fortinet.firewall.ap': { + category: 'fortinet', + description: 'Access Point ', + name: 'fortinet.firewall.ap', + type: 'keyword', + }, + 'fortinet.firewall.app-type': { + category: 'fortinet', + description: 'Address Type ', + name: 'fortinet.firewall.app-type', + type: 'keyword', + }, + 'fortinet.firewall.appact': { + category: 'fortinet', + description: 'The security action from app control ', + name: 'fortinet.firewall.appact', + type: 'keyword', + }, + 'fortinet.firewall.appid': { + category: 'fortinet', + description: 'Application ID ', + name: 'fortinet.firewall.appid', + type: 'integer', + }, + 'fortinet.firewall.applist': { + category: 'fortinet', + description: 'Application Control profile ', + name: 'fortinet.firewall.applist', + type: 'keyword', + }, + 'fortinet.firewall.apprisk': { + category: 'fortinet', + description: 'Application Risk Level ', + name: 'fortinet.firewall.apprisk', + type: 'keyword', + }, + 'fortinet.firewall.apscan': { + category: 'fortinet', + description: 'The name of the AP, which scanned and detected the rogue AP ', + name: 'fortinet.firewall.apscan', + type: 'keyword', + }, + 'fortinet.firewall.apsn': { + category: 'fortinet', + description: 'Access Point ', + name: 'fortinet.firewall.apsn', + type: 'keyword', + }, + 'fortinet.firewall.apstatus': { + category: 'fortinet', + description: 'Access Point status ', + name: 'fortinet.firewall.apstatus', + type: 'keyword', + }, + 'fortinet.firewall.aptype': { + category: 'fortinet', + description: 'Access Point type ', + name: 'fortinet.firewall.aptype', + type: 'keyword', + }, + 'fortinet.firewall.assigned': { + category: 'fortinet', + description: 'Assigned IP Address ', + name: 'fortinet.firewall.assigned', + type: 'ip', + }, + 'fortinet.firewall.assignip': { + category: 'fortinet', + description: 'Assigned IP Address ', + name: 'fortinet.firewall.assignip', + type: 'ip', + }, + 'fortinet.firewall.attachment': { + category: 'fortinet', + description: 'The flag for email attachement ', + name: 'fortinet.firewall.attachment', + type: 'keyword', + }, + 'fortinet.firewall.attack': { + category: 'fortinet', + description: 'Attack Name ', + name: 'fortinet.firewall.attack', + type: 'keyword', + }, + 'fortinet.firewall.attackcontext': { + category: 'fortinet', + description: 'The trigger patterns and the packetdata with base64 encoding ', + name: 'fortinet.firewall.attackcontext', + type: 'keyword', + }, + 'fortinet.firewall.attackcontextid': { + category: 'fortinet', + description: 'Attack context id / total ', + name: 'fortinet.firewall.attackcontextid', + type: 'keyword', + }, + 'fortinet.firewall.attackid': { + category: 'fortinet', + description: 'Attack ID ', + name: 'fortinet.firewall.attackid', + type: 'integer', + }, + 'fortinet.firewall.auditid': { + category: 'fortinet', + description: 'Audit ID ', + name: 'fortinet.firewall.auditid', + type: 'long', + }, + 'fortinet.firewall.auditscore': { + category: 'fortinet', + description: 'The Audit Score ', + name: 'fortinet.firewall.auditscore', + type: 'keyword', + }, + 'fortinet.firewall.audittime': { + category: 'fortinet', + description: 'The time of the audit ', + name: 'fortinet.firewall.audittime', + type: 'long', + }, + 'fortinet.firewall.authgrp': { + category: 'fortinet', + description: 'Authorization Group ', + name: 'fortinet.firewall.authgrp', + type: 'keyword', + }, + 'fortinet.firewall.authid': { + category: 'fortinet', + description: 'Authentication ID ', + name: 'fortinet.firewall.authid', + type: 'keyword', + }, + 'fortinet.firewall.authproto': { + category: 'fortinet', + description: 'The protocol that initiated the authentication ', + name: 'fortinet.firewall.authproto', + type: 'keyword', + }, + 'fortinet.firewall.authserver': { + category: 'fortinet', + description: 'Authentication server ', + name: 'fortinet.firewall.authserver', + type: 'keyword', + }, + 'fortinet.firewall.bandwidth': { + category: 'fortinet', + description: 'Bandwidth ', + name: 'fortinet.firewall.bandwidth', + type: 'keyword', + }, + 'fortinet.firewall.banned_rule': { + category: 'fortinet', + description: 'NAC quarantine Banned Rule Name ', + name: 'fortinet.firewall.banned_rule', + type: 'keyword', + }, + 'fortinet.firewall.banned_src': { + category: 'fortinet', + description: 'NAC quarantine Banned Source IP ', + name: 'fortinet.firewall.banned_src', + type: 'keyword', + }, + 'fortinet.firewall.banword': { + category: 'fortinet', + description: 'Banned word ', + name: 'fortinet.firewall.banword', + type: 'keyword', + }, + 'fortinet.firewall.botnetdomain': { + category: 'fortinet', + description: 'Botnet Domain Name ', + name: 'fortinet.firewall.botnetdomain', + type: 'keyword', + }, + 'fortinet.firewall.botnetip': { + category: 'fortinet', + description: 'Botnet IP Address ', + name: 'fortinet.firewall.botnetip', + type: 'ip', + }, + 'fortinet.firewall.bssid': { + category: 'fortinet', + description: 'Service Set ID ', + name: 'fortinet.firewall.bssid', + type: 'keyword', + }, + 'fortinet.firewall.call_id': { + category: 'fortinet', + description: 'Caller ID ', + name: 'fortinet.firewall.call_id', + type: 'keyword', + }, + 'fortinet.firewall.carrier_ep': { + category: 'fortinet', + description: 'The FortiOS Carrier end-point identification ', + name: 'fortinet.firewall.carrier_ep', + type: 'keyword', + }, + 'fortinet.firewall.cat': { + category: 'fortinet', + description: 'DNS category ID ', + name: 'fortinet.firewall.cat', + type: 'integer', + }, + 'fortinet.firewall.category': { + category: 'fortinet', + description: 'Authentication category ', + name: 'fortinet.firewall.category', + type: 'keyword', + }, + 'fortinet.firewall.cc': { + category: 'fortinet', + description: 'CC Email Address ', + name: 'fortinet.firewall.cc', + type: 'keyword', + }, + 'fortinet.firewall.cdrcontent': { + category: 'fortinet', + description: 'Cdrcontent ', + name: 'fortinet.firewall.cdrcontent', + type: 'keyword', + }, + 'fortinet.firewall.centralnatid': { + category: 'fortinet', + description: 'Central NAT ID ', + name: 'fortinet.firewall.centralnatid', + type: 'integer', + }, + 'fortinet.firewall.cert': { + category: 'fortinet', + description: 'Certificate ', + name: 'fortinet.firewall.cert', + type: 'keyword', + }, + 'fortinet.firewall.cert-type': { + category: 'fortinet', + description: 'Certificate type ', + name: 'fortinet.firewall.cert-type', + type: 'keyword', + }, + 'fortinet.firewall.certhash': { + category: 'fortinet', + description: 'Certificate hash ', + name: 'fortinet.firewall.certhash', + type: 'keyword', + }, + 'fortinet.firewall.cfgattr': { + category: 'fortinet', + description: 'Configuration attribute ', + name: 'fortinet.firewall.cfgattr', + type: 'keyword', + }, + 'fortinet.firewall.cfgobj': { + category: 'fortinet', + description: 'Configuration object ', + name: 'fortinet.firewall.cfgobj', + type: 'keyword', + }, + 'fortinet.firewall.cfgpath': { + category: 'fortinet', + description: 'Configuration path ', + name: 'fortinet.firewall.cfgpath', + type: 'keyword', + }, + 'fortinet.firewall.cfgtid': { + category: 'fortinet', + description: 'Configuration transaction ID ', + name: 'fortinet.firewall.cfgtid', + type: 'keyword', + }, + 'fortinet.firewall.cfgtxpower': { + category: 'fortinet', + description: 'Configuration TX power ', + name: 'fortinet.firewall.cfgtxpower', + type: 'integer', + }, + 'fortinet.firewall.channel': { + category: 'fortinet', + description: 'Wireless Channel ', + name: 'fortinet.firewall.channel', + type: 'integer', + }, + 'fortinet.firewall.channeltype': { + category: 'fortinet', + description: 'SSH channel type ', + name: 'fortinet.firewall.channeltype', + type: 'keyword', + }, + 'fortinet.firewall.chassisid': { + category: 'fortinet', + description: 'Chassis ID ', + name: 'fortinet.firewall.chassisid', + type: 'integer', + }, + 'fortinet.firewall.checksum': { + category: 'fortinet', + description: 'The checksum of the scanned file ', + name: 'fortinet.firewall.checksum', + type: 'keyword', + }, + 'fortinet.firewall.chgheaders': { + category: 'fortinet', + description: 'HTTP Headers ', + name: 'fortinet.firewall.chgheaders', + type: 'keyword', + }, + 'fortinet.firewall.cldobjid': { + category: 'fortinet', + description: 'Connector object ID ', + name: 'fortinet.firewall.cldobjid', + type: 'keyword', + }, + 'fortinet.firewall.client_addr': { + category: 'fortinet', + description: 'Wifi client address ', + name: 'fortinet.firewall.client_addr', + type: 'keyword', + }, + 'fortinet.firewall.cloudaction': { + category: 'fortinet', + description: 'Cloud Action ', + name: 'fortinet.firewall.cloudaction', + type: 'keyword', + }, + 'fortinet.firewall.clouduser': { + category: 'fortinet', + description: 'Cloud User ', + name: 'fortinet.firewall.clouduser', + type: 'keyword', + }, + 'fortinet.firewall.column': { + category: 'fortinet', + description: 'VOIP Column ', + name: 'fortinet.firewall.column', + type: 'integer', + }, + 'fortinet.firewall.command': { + category: 'fortinet', + description: 'CLI Command ', + name: 'fortinet.firewall.command', + type: 'keyword', + }, + 'fortinet.firewall.community': { + category: 'fortinet', + description: 'SNMP Community ', + name: 'fortinet.firewall.community', + type: 'keyword', + }, + 'fortinet.firewall.configcountry': { + category: 'fortinet', + description: 'Configuration country ', + name: 'fortinet.firewall.configcountry', + type: 'keyword', + }, + 'fortinet.firewall.connection_type': { + category: 'fortinet', + description: 'FortiClient Connection Type ', + name: 'fortinet.firewall.connection_type', + type: 'keyword', + }, + 'fortinet.firewall.conserve': { + category: 'fortinet', + description: 'Flag for conserve mode ', + name: 'fortinet.firewall.conserve', + type: 'keyword', + }, + 'fortinet.firewall.constraint': { + category: 'fortinet', + description: 'WAF http protocol restrictions ', + name: 'fortinet.firewall.constraint', + type: 'keyword', + }, + 'fortinet.firewall.contentdisarmed': { + category: 'fortinet', + description: 'Email scanned content ', + name: 'fortinet.firewall.contentdisarmed', + type: 'keyword', + }, + 'fortinet.firewall.contenttype': { + category: 'fortinet', + description: 'Content Type from HTTP header ', + name: 'fortinet.firewall.contenttype', + type: 'keyword', + }, + 'fortinet.firewall.cookies': { + category: 'fortinet', + description: 'VPN Cookie ', + name: 'fortinet.firewall.cookies', + type: 'keyword', + }, + 'fortinet.firewall.count': { + category: 'fortinet', + description: 'Counts of action type ', + name: 'fortinet.firewall.count', + type: 'integer', + }, + 'fortinet.firewall.countapp': { + category: 'fortinet', + description: 'Number of App Ctrl logs associated with the session ', + name: 'fortinet.firewall.countapp', + type: 'integer', + }, + 'fortinet.firewall.countav': { + category: 'fortinet', + description: 'Number of AV logs associated with the session ', + name: 'fortinet.firewall.countav', + type: 'integer', + }, + 'fortinet.firewall.countcifs': { + category: 'fortinet', + description: 'Number of CIFS logs associated with the session ', + name: 'fortinet.firewall.countcifs', + type: 'integer', + }, + 'fortinet.firewall.countdlp': { + category: 'fortinet', + description: 'Number of DLP logs associated with the session ', + name: 'fortinet.firewall.countdlp', + type: 'integer', + }, + 'fortinet.firewall.countdns': { + category: 'fortinet', + description: 'Number of DNS logs associated with the session ', + name: 'fortinet.firewall.countdns', + type: 'integer', + }, + 'fortinet.firewall.countemail': { + category: 'fortinet', + description: 'Number of email logs associated with the session ', + name: 'fortinet.firewall.countemail', + type: 'integer', + }, + 'fortinet.firewall.countff': { + category: 'fortinet', + description: 'Number of ff logs associated with the session ', + name: 'fortinet.firewall.countff', + type: 'integer', + }, + 'fortinet.firewall.countips': { + category: 'fortinet', + description: 'Number of IPS logs associated with the session ', + name: 'fortinet.firewall.countips', + type: 'integer', + }, + 'fortinet.firewall.countssh': { + category: 'fortinet', + description: 'Number of SSH logs associated with the session ', + name: 'fortinet.firewall.countssh', + type: 'integer', + }, + 'fortinet.firewall.countssl': { + category: 'fortinet', + description: 'Number of SSL logs associated with the session ', + name: 'fortinet.firewall.countssl', + type: 'integer', + }, + 'fortinet.firewall.countwaf': { + category: 'fortinet', + description: 'Number of WAF logs associated with the session ', + name: 'fortinet.firewall.countwaf', + type: 'integer', + }, + 'fortinet.firewall.countweb': { + category: 'fortinet', + description: 'Number of Web filter logs associated with the session ', + name: 'fortinet.firewall.countweb', + type: 'integer', + }, + 'fortinet.firewall.cpu': { + category: 'fortinet', + description: 'CPU Usage ', + name: 'fortinet.firewall.cpu', + type: 'integer', + }, + 'fortinet.firewall.craction': { + category: 'fortinet', + description: 'Client Reputation Action ', + name: 'fortinet.firewall.craction', + type: 'integer', + }, + 'fortinet.firewall.criticalcount': { + category: 'fortinet', + description: 'Number of critical ratings ', + name: 'fortinet.firewall.criticalcount', + type: 'integer', + }, + 'fortinet.firewall.crl': { + category: 'fortinet', + description: 'Client Reputation Level ', + name: 'fortinet.firewall.crl', + type: 'keyword', + }, + 'fortinet.firewall.crlevel': { + category: 'fortinet', + description: 'Client Reputation Level ', + name: 'fortinet.firewall.crlevel', + type: 'keyword', + }, + 'fortinet.firewall.crscore': { + category: 'fortinet', + description: 'Some description ', + name: 'fortinet.firewall.crscore', + type: 'integer', + }, + 'fortinet.firewall.cveid': { + category: 'fortinet', + description: 'CVE ID ', + name: 'fortinet.firewall.cveid', + type: 'keyword', + }, + 'fortinet.firewall.daemon': { + category: 'fortinet', + description: 'Daemon name ', + name: 'fortinet.firewall.daemon', + type: 'keyword', + }, + 'fortinet.firewall.datarange': { + category: 'fortinet', + description: 'Data range for reports ', + name: 'fortinet.firewall.datarange', + type: 'keyword', + }, + 'fortinet.firewall.date': { + category: 'fortinet', + description: 'Date ', + name: 'fortinet.firewall.date', + type: 'keyword', + }, + 'fortinet.firewall.ddnsserver': { + category: 'fortinet', + description: 'DDNS server ', + name: 'fortinet.firewall.ddnsserver', + type: 'ip', + }, + 'fortinet.firewall.desc': { + category: 'fortinet', + description: 'Description ', + name: 'fortinet.firewall.desc', + type: 'keyword', + }, + 'fortinet.firewall.detectionmethod': { + category: 'fortinet', + description: 'Detection method ', + name: 'fortinet.firewall.detectionmethod', + type: 'keyword', + }, + 'fortinet.firewall.devcategory': { + category: 'fortinet', + description: 'Device category ', + name: 'fortinet.firewall.devcategory', + type: 'keyword', + }, + 'fortinet.firewall.devintfname': { + category: 'fortinet', + description: 'HA device Interface Name ', + name: 'fortinet.firewall.devintfname', + type: 'keyword', + }, + 'fortinet.firewall.devtype': { + category: 'fortinet', + description: 'Device type ', + name: 'fortinet.firewall.devtype', + type: 'keyword', + }, + 'fortinet.firewall.dhcp_msg': { + category: 'fortinet', + description: 'DHCP Message ', + name: 'fortinet.firewall.dhcp_msg', + type: 'keyword', + }, + 'fortinet.firewall.dintf': { + category: 'fortinet', + description: 'Destination interface ', + name: 'fortinet.firewall.dintf', + type: 'keyword', + }, + 'fortinet.firewall.disk': { + category: 'fortinet', + description: 'Assosciated disk ', + name: 'fortinet.firewall.disk', + type: 'keyword', + }, + 'fortinet.firewall.disklograte': { + category: 'fortinet', + description: 'Disk logging rate ', + name: 'fortinet.firewall.disklograte', + type: 'long', + }, + 'fortinet.firewall.dlpextra': { + category: 'fortinet', + description: 'DLP extra information ', + name: 'fortinet.firewall.dlpextra', + type: 'keyword', + }, + 'fortinet.firewall.docsource': { + category: 'fortinet', + description: 'DLP fingerprint document source ', + name: 'fortinet.firewall.docsource', + type: 'keyword', + }, + 'fortinet.firewall.domainctrlauthstate': { + category: 'fortinet', + description: 'CIFS domain auth state ', + name: 'fortinet.firewall.domainctrlauthstate', + type: 'integer', + }, + 'fortinet.firewall.domainctrlauthtype': { + category: 'fortinet', + description: 'CIFS domain auth type ', + name: 'fortinet.firewall.domainctrlauthtype', + type: 'integer', + }, + 'fortinet.firewall.domainctrldomain': { + category: 'fortinet', + description: 'CIFS domain auth domain ', + name: 'fortinet.firewall.domainctrldomain', + type: 'keyword', + }, + 'fortinet.firewall.domainctrlip': { + category: 'fortinet', + description: 'CIFS Domain IP ', + name: 'fortinet.firewall.domainctrlip', + type: 'ip', + }, + 'fortinet.firewall.domainctrlname': { + category: 'fortinet', + description: 'CIFS Domain name ', + name: 'fortinet.firewall.domainctrlname', + type: 'keyword', + }, + 'fortinet.firewall.domainctrlprotocoltype': { + category: 'fortinet', + description: 'CIFS Domain connection protocol ', + name: 'fortinet.firewall.domainctrlprotocoltype', + type: 'integer', + }, + 'fortinet.firewall.domainctrlusername': { + category: 'fortinet', + description: 'CIFS Domain username ', + name: 'fortinet.firewall.domainctrlusername', + type: 'keyword', + }, + 'fortinet.firewall.domainfilteridx': { + category: 'fortinet', + description: 'Domain filter ID ', + name: 'fortinet.firewall.domainfilteridx', + type: 'integer', + }, + 'fortinet.firewall.domainfilterlist': { + category: 'fortinet', + description: 'Domain filter name ', + name: 'fortinet.firewall.domainfilterlist', + type: 'keyword', + }, + 'fortinet.firewall.ds': { + category: 'fortinet', + description: 'Direction with distribution system ', + name: 'fortinet.firewall.ds', + type: 'keyword', + }, + 'fortinet.firewall.dst_int': { + category: 'fortinet', + description: 'Destination interface ', + name: 'fortinet.firewall.dst_int', + type: 'keyword', + }, + 'fortinet.firewall.dstintfrole': { + category: 'fortinet', + description: 'Destination interface role ', + name: 'fortinet.firewall.dstintfrole', + type: 'keyword', + }, + 'fortinet.firewall.dstcountry': { + category: 'fortinet', + description: 'Destination country ', + name: 'fortinet.firewall.dstcountry', + type: 'keyword', + }, + 'fortinet.firewall.dstdevcategory': { + category: 'fortinet', + description: 'Destination device category ', + name: 'fortinet.firewall.dstdevcategory', + type: 'keyword', + }, + 'fortinet.firewall.dstdevtype': { + category: 'fortinet', + description: 'Destination device type ', + name: 'fortinet.firewall.dstdevtype', + type: 'keyword', + }, + 'fortinet.firewall.dstfamily': { + category: 'fortinet', + description: 'Destination OS family ', + name: 'fortinet.firewall.dstfamily', + type: 'keyword', + }, + 'fortinet.firewall.dsthwvendor': { + category: 'fortinet', + description: 'Destination HW vendor ', + name: 'fortinet.firewall.dsthwvendor', + type: 'keyword', + }, + 'fortinet.firewall.dsthwversion': { + category: 'fortinet', + description: 'Destination HW version ', + name: 'fortinet.firewall.dsthwversion', + type: 'keyword', + }, + 'fortinet.firewall.dstinetsvc': { + category: 'fortinet', + description: 'Destination interface service ', + name: 'fortinet.firewall.dstinetsvc', + type: 'keyword', + }, + 'fortinet.firewall.dstosname': { + category: 'fortinet', + description: 'Destination OS name ', + name: 'fortinet.firewall.dstosname', + type: 'keyword', + }, + 'fortinet.firewall.dstosversion': { + category: 'fortinet', + description: 'Destination OS version ', + name: 'fortinet.firewall.dstosversion', + type: 'keyword', + }, + 'fortinet.firewall.dstserver': { + category: 'fortinet', + description: 'Destination server ', + name: 'fortinet.firewall.dstserver', + type: 'integer', + }, + 'fortinet.firewall.dstssid': { + category: 'fortinet', + description: 'Destination SSID ', + name: 'fortinet.firewall.dstssid', + type: 'keyword', + }, + 'fortinet.firewall.dstswversion': { + category: 'fortinet', + description: 'Destination software version ', + name: 'fortinet.firewall.dstswversion', + type: 'keyword', + }, + 'fortinet.firewall.dstunauthusersource': { + category: 'fortinet', + description: 'Destination unauthenticated source ', + name: 'fortinet.firewall.dstunauthusersource', + type: 'keyword', + }, + 'fortinet.firewall.dstuuid': { + category: 'fortinet', + description: 'UUID of the Destination IP address ', + name: 'fortinet.firewall.dstuuid', + type: 'keyword', + }, + 'fortinet.firewall.duid': { + category: 'fortinet', + description: 'DHCP UID ', + name: 'fortinet.firewall.duid', + type: 'keyword', + }, + 'fortinet.firewall.eapolcnt': { + category: 'fortinet', + description: 'EAPOL packet count ', + name: 'fortinet.firewall.eapolcnt', + type: 'integer', + }, + 'fortinet.firewall.eapoltype': { + category: 'fortinet', + description: 'EAPOL packet type ', + name: 'fortinet.firewall.eapoltype', + type: 'keyword', + }, + 'fortinet.firewall.encrypt': { + category: 'fortinet', + description: 'Whether the packet is encrypted or not ', + name: 'fortinet.firewall.encrypt', + type: 'integer', + }, + 'fortinet.firewall.encryption': { + category: 'fortinet', + description: 'Encryption method ', + name: 'fortinet.firewall.encryption', + type: 'keyword', + }, + 'fortinet.firewall.epoch': { + category: 'fortinet', + description: 'Epoch used for locating file ', + name: 'fortinet.firewall.epoch', + type: 'integer', + }, + 'fortinet.firewall.espauth': { + category: 'fortinet', + description: 'ESP Authentication ', + name: 'fortinet.firewall.espauth', + type: 'keyword', + }, + 'fortinet.firewall.esptransform': { + category: 'fortinet', + description: 'ESP Transform ', + name: 'fortinet.firewall.esptransform', + type: 'keyword', + }, + 'fortinet.firewall.exch': { + category: 'fortinet', + description: 'Mail Exchanges from DNS response answer section ', + name: 'fortinet.firewall.exch', + type: 'keyword', + }, + 'fortinet.firewall.exchange': { + category: 'fortinet', + description: 'Mail Exchanges from DNS response answer section ', + name: 'fortinet.firewall.exchange', + type: 'keyword', + }, + 'fortinet.firewall.expectedsignature': { + category: 'fortinet', + description: 'Expected SSL signature ', + name: 'fortinet.firewall.expectedsignature', + type: 'keyword', + }, + 'fortinet.firewall.expiry': { + category: 'fortinet', + description: 'FortiGuard override expiry timestamp ', + name: 'fortinet.firewall.expiry', + type: 'keyword', + }, + 'fortinet.firewall.fams_pause': { + category: 'fortinet', + description: 'Fortinet Analysis and Management Service Pause ', + name: 'fortinet.firewall.fams_pause', + type: 'integer', + }, + 'fortinet.firewall.fazlograte': { + category: 'fortinet', + description: 'FortiAnalyzer Logging Rate ', + name: 'fortinet.firewall.fazlograte', + type: 'long', + }, + 'fortinet.firewall.fctemssn': { + category: 'fortinet', + description: 'FortiClient Endpoint SSN ', + name: 'fortinet.firewall.fctemssn', + type: 'keyword', + }, + 'fortinet.firewall.fctuid': { + category: 'fortinet', + description: 'FortiClient UID ', + name: 'fortinet.firewall.fctuid', + type: 'keyword', + }, + 'fortinet.firewall.field': { + category: 'fortinet', + description: 'NTP status field ', + name: 'fortinet.firewall.field', + type: 'keyword', + }, + 'fortinet.firewall.filefilter': { + category: 'fortinet', + description: 'The filter used to identify the affected file ', + name: 'fortinet.firewall.filefilter', + type: 'keyword', + }, + 'fortinet.firewall.filehashsrc': { + category: 'fortinet', + description: 'Filehash source ', + name: 'fortinet.firewall.filehashsrc', + type: 'keyword', + }, + 'fortinet.firewall.filtercat': { + category: 'fortinet', + description: 'DLP filter category ', + name: 'fortinet.firewall.filtercat', + type: 'keyword', + }, + 'fortinet.firewall.filteridx': { + category: 'fortinet', + description: 'DLP filter ID ', + name: 'fortinet.firewall.filteridx', + type: 'integer', + }, + 'fortinet.firewall.filtername': { + category: 'fortinet', + description: 'DLP rule name ', + name: 'fortinet.firewall.filtername', + type: 'keyword', + }, + 'fortinet.firewall.filtertype': { + category: 'fortinet', + description: 'DLP filter type ', + name: 'fortinet.firewall.filtertype', + type: 'keyword', + }, + 'fortinet.firewall.fortiguardresp': { + category: 'fortinet', + description: 'Antispam ESP value ', + name: 'fortinet.firewall.fortiguardresp', + type: 'keyword', + }, + 'fortinet.firewall.forwardedfor': { + category: 'fortinet', + description: 'Email address forwarded ', + name: 'fortinet.firewall.forwardedfor', + type: 'keyword', + }, + 'fortinet.firewall.fqdn': { + category: 'fortinet', + description: 'FQDN ', + name: 'fortinet.firewall.fqdn', + type: 'keyword', + }, + 'fortinet.firewall.frametype': { + category: 'fortinet', + description: 'Wireless frametype ', + name: 'fortinet.firewall.frametype', + type: 'keyword', + }, + 'fortinet.firewall.freediskstorage': { + category: 'fortinet', + description: 'Free disk integer ', + name: 'fortinet.firewall.freediskstorage', + type: 'integer', + }, + 'fortinet.firewall.from': { + category: 'fortinet', + description: 'From email address ', + name: 'fortinet.firewall.from', + type: 'keyword', + }, + 'fortinet.firewall.from_vcluster': { + category: 'fortinet', + description: 'Source virtual cluster number ', + name: 'fortinet.firewall.from_vcluster', + type: 'integer', + }, + 'fortinet.firewall.fsaverdict': { + category: 'fortinet', + description: 'FSA verdict ', + name: 'fortinet.firewall.fsaverdict', + type: 'keyword', + }, + 'fortinet.firewall.fwserver_name': { + category: 'fortinet', + description: 'Web proxy server name ', + name: 'fortinet.firewall.fwserver_name', + type: 'keyword', + }, + 'fortinet.firewall.gateway': { + category: 'fortinet', + description: 'Gateway ip address for PPPoE status report ', + name: 'fortinet.firewall.gateway', + type: 'ip', + }, + 'fortinet.firewall.green': { + category: 'fortinet', + description: 'Memory status ', + name: 'fortinet.firewall.green', + type: 'keyword', + }, + 'fortinet.firewall.groupid': { + category: 'fortinet', + description: 'User Group ID ', + name: 'fortinet.firewall.groupid', + type: 'integer', + }, + 'fortinet.firewall.ha-prio': { + category: 'fortinet', + description: 'HA Priority ', + name: 'fortinet.firewall.ha-prio', + type: 'integer', + }, + 'fortinet.firewall.ha_group': { + category: 'fortinet', + description: 'HA Group ', + name: 'fortinet.firewall.ha_group', + type: 'keyword', + }, + 'fortinet.firewall.ha_role': { + category: 'fortinet', + description: 'HA Role ', + name: 'fortinet.firewall.ha_role', + type: 'keyword', + }, + 'fortinet.firewall.handshake': { + category: 'fortinet', + description: 'SSL Handshake ', + name: 'fortinet.firewall.handshake', + type: 'keyword', + }, + 'fortinet.firewall.hash': { + category: 'fortinet', + description: 'Hash value of downloaded file ', + name: 'fortinet.firewall.hash', + type: 'keyword', + }, + 'fortinet.firewall.hbdn_reason': { + category: 'fortinet', + description: 'Heartbeat down reason ', + name: 'fortinet.firewall.hbdn_reason', + type: 'keyword', + }, + 'fortinet.firewall.highcount': { + category: 'fortinet', + description: 'Highcount fabric summary ', + name: 'fortinet.firewall.highcount', + type: 'integer', + }, + 'fortinet.firewall.host': { + category: 'fortinet', + description: 'Hostname ', + name: 'fortinet.firewall.host', + type: 'keyword', + }, + 'fortinet.firewall.iaid': { + category: 'fortinet', + description: 'DHCPv6 id ', + name: 'fortinet.firewall.iaid', + type: 'keyword', + }, + 'fortinet.firewall.icmpcode': { + category: 'fortinet', + description: 'Destination Port of the ICMP message ', + name: 'fortinet.firewall.icmpcode', + type: 'keyword', + }, + 'fortinet.firewall.icmpid': { + category: 'fortinet', + description: 'Source port of the ICMP message ', + name: 'fortinet.firewall.icmpid', + type: 'keyword', + }, + 'fortinet.firewall.icmptype': { + category: 'fortinet', + description: 'The type of ICMP message ', + name: 'fortinet.firewall.icmptype', + type: 'keyword', + }, + 'fortinet.firewall.identifier': { + category: 'fortinet', + description: 'Network traffic identifier ', + name: 'fortinet.firewall.identifier', + type: 'integer', + }, + 'fortinet.firewall.in_spi': { + category: 'fortinet', + description: 'IPSEC inbound SPI ', + name: 'fortinet.firewall.in_spi', + type: 'keyword', + }, + 'fortinet.firewall.incidentserialno': { + category: 'fortinet', + description: 'Incident serial number ', + name: 'fortinet.firewall.incidentserialno', + type: 'integer', + }, + 'fortinet.firewall.infected': { + category: 'fortinet', + description: 'Infected MMS ', + name: 'fortinet.firewall.infected', + type: 'integer', + }, + 'fortinet.firewall.infectedfilelevel': { + category: 'fortinet', + description: 'DLP infected file level ', + name: 'fortinet.firewall.infectedfilelevel', + type: 'integer', + }, + 'fortinet.firewall.informationsource': { + category: 'fortinet', + description: 'Information source ', + name: 'fortinet.firewall.informationsource', + type: 'keyword', + }, + 'fortinet.firewall.init': { + category: 'fortinet', + description: 'IPSEC init stage ', + name: 'fortinet.firewall.init', + type: 'keyword', + }, + 'fortinet.firewall.initiator': { + category: 'fortinet', + description: 'Original login user name for Fortiguard override ', + name: 'fortinet.firewall.initiator', + type: 'keyword', + }, + 'fortinet.firewall.interface': { + category: 'fortinet', + description: 'Related interface ', + name: 'fortinet.firewall.interface', + type: 'keyword', + }, + 'fortinet.firewall.intf': { + category: 'fortinet', + description: 'Related interface ', + name: 'fortinet.firewall.intf', + type: 'keyword', + }, + 'fortinet.firewall.invalidmac': { + category: 'fortinet', + description: 'The MAC address with invalid OUI ', + name: 'fortinet.firewall.invalidmac', + type: 'keyword', + }, + 'fortinet.firewall.ip': { + category: 'fortinet', + description: 'Related IP ', + name: 'fortinet.firewall.ip', + type: 'ip', + }, + 'fortinet.firewall.iptype': { + category: 'fortinet', + description: 'Related IP type ', + name: 'fortinet.firewall.iptype', + type: 'keyword', + }, + 'fortinet.firewall.keyword': { + category: 'fortinet', + description: 'Keyword used for search ', + name: 'fortinet.firewall.keyword', + type: 'keyword', + }, + 'fortinet.firewall.kind': { + category: 'fortinet', + description: 'VOIP kind ', + name: 'fortinet.firewall.kind', + type: 'keyword', + }, + 'fortinet.firewall.lanin': { + category: 'fortinet', + description: 'LAN incoming traffic in bytes ', + name: 'fortinet.firewall.lanin', + type: 'long', + }, + 'fortinet.firewall.lanout': { + category: 'fortinet', + description: 'LAN outbound traffic in bytes ', + name: 'fortinet.firewall.lanout', + type: 'long', + }, + 'fortinet.firewall.lease': { + category: 'fortinet', + description: 'DHCP lease ', + name: 'fortinet.firewall.lease', + type: 'integer', + }, + 'fortinet.firewall.license_limit': { + category: 'fortinet', + description: 'Maximum Number of FortiClients for the License ', + name: 'fortinet.firewall.license_limit', + type: 'keyword', + }, + 'fortinet.firewall.limit': { + category: 'fortinet', + description: 'Virtual Domain Resource Limit ', + name: 'fortinet.firewall.limit', + type: 'integer', + }, + 'fortinet.firewall.line': { + category: 'fortinet', + description: 'VOIP line ', + name: 'fortinet.firewall.line', + type: 'keyword', + }, + 'fortinet.firewall.live': { + category: 'fortinet', + description: 'Time in seconds ', + name: 'fortinet.firewall.live', + type: 'integer', + }, + 'fortinet.firewall.local': { + category: 'fortinet', + description: 'Local IP for a PPPD Connection ', + name: 'fortinet.firewall.local', + type: 'ip', + }, + 'fortinet.firewall.log': { + category: 'fortinet', + description: 'Log message ', + name: 'fortinet.firewall.log', + type: 'keyword', + }, + 'fortinet.firewall.login': { + category: 'fortinet', + description: 'SSH login ', + name: 'fortinet.firewall.login', + type: 'keyword', + }, + 'fortinet.firewall.lowcount': { + category: 'fortinet', + description: 'Fabric lowcount ', + name: 'fortinet.firewall.lowcount', + type: 'integer', + }, + 'fortinet.firewall.mac': { + category: 'fortinet', + description: 'DHCP mac address ', + name: 'fortinet.firewall.mac', + type: 'keyword', + }, + 'fortinet.firewall.malform_data': { + category: 'fortinet', + description: 'VOIP malformed data ', + name: 'fortinet.firewall.malform_data', + type: 'integer', + }, + 'fortinet.firewall.malform_desc': { + category: 'fortinet', + description: 'VOIP malformed data description ', + name: 'fortinet.firewall.malform_desc', + type: 'keyword', + }, + 'fortinet.firewall.manuf': { + category: 'fortinet', + description: 'Manufacturer name ', + name: 'fortinet.firewall.manuf', + type: 'keyword', + }, + 'fortinet.firewall.masterdstmac': { + category: 'fortinet', + description: 'Master mac address for a host with multiple network interfaces ', + name: 'fortinet.firewall.masterdstmac', + type: 'keyword', + }, + 'fortinet.firewall.mastersrcmac': { + category: 'fortinet', + description: 'The master MAC address for a host that has multiple network interfaces ', + name: 'fortinet.firewall.mastersrcmac', + type: 'keyword', + }, + 'fortinet.firewall.mediumcount': { + category: 'fortinet', + description: 'Fabric medium count ', + name: 'fortinet.firewall.mediumcount', + type: 'integer', + }, + 'fortinet.firewall.mem': { + category: 'fortinet', + description: 'Memory usage system statistics ', + name: 'fortinet.firewall.mem', + type: 'keyword', + }, + 'fortinet.firewall.meshmode': { + category: 'fortinet', + description: 'Wireless mesh mode ', + name: 'fortinet.firewall.meshmode', + type: 'keyword', + }, + 'fortinet.firewall.message_type': { + category: 'fortinet', + description: 'VOIP message type ', + name: 'fortinet.firewall.message_type', + type: 'keyword', + }, + 'fortinet.firewall.method': { + category: 'fortinet', + description: 'HTTP method ', + name: 'fortinet.firewall.method', + type: 'keyword', + }, + 'fortinet.firewall.mgmtcnt': { + category: 'fortinet', + description: 'The number of unauthorized client flooding managemet frames ', + name: 'fortinet.firewall.mgmtcnt', + type: 'integer', + }, + 'fortinet.firewall.mode': { + category: 'fortinet', + description: 'IPSEC mode ', + name: 'fortinet.firewall.mode', + type: 'keyword', + }, + 'fortinet.firewall.module': { + category: 'fortinet', + description: 'PCI-DSS module ', + name: 'fortinet.firewall.module', + type: 'keyword', + }, + 'fortinet.firewall.monitor-name': { + category: 'fortinet', + description: 'Health Monitor Name ', + name: 'fortinet.firewall.monitor-name', + type: 'keyword', + }, + 'fortinet.firewall.monitor-type': { + category: 'fortinet', + description: 'Health Monitor Type ', + name: 'fortinet.firewall.monitor-type', + type: 'keyword', + }, + 'fortinet.firewall.mpsk': { + category: 'fortinet', + description: 'Wireless MPSK ', + name: 'fortinet.firewall.mpsk', + type: 'keyword', + }, + 'fortinet.firewall.msgproto': { + category: 'fortinet', + description: 'Message Protocol Number ', + name: 'fortinet.firewall.msgproto', + type: 'keyword', + }, + 'fortinet.firewall.mtu': { + category: 'fortinet', + description: 'Max Transmission Unit Value ', + name: 'fortinet.firewall.mtu', + type: 'integer', + }, + 'fortinet.firewall.name': { + category: 'fortinet', + description: 'Name ', + name: 'fortinet.firewall.name', + type: 'keyword', + }, + 'fortinet.firewall.nat': { + category: 'fortinet', + description: 'NAT IP Address ', + name: 'fortinet.firewall.nat', + type: 'keyword', + }, + 'fortinet.firewall.netid': { + category: 'fortinet', + description: 'Connector NetID ', + name: 'fortinet.firewall.netid', + type: 'keyword', + }, + 'fortinet.firewall.new_status': { + category: 'fortinet', + description: 'New status on user change ', + name: 'fortinet.firewall.new_status', + type: 'keyword', + }, + 'fortinet.firewall.new_value': { + category: 'fortinet', + description: 'New Virtual Domain Name ', + name: 'fortinet.firewall.new_value', + type: 'keyword', + }, + 'fortinet.firewall.newchannel': { + category: 'fortinet', + description: 'New Channel Number ', + name: 'fortinet.firewall.newchannel', + type: 'integer', + }, + 'fortinet.firewall.newchassisid': { + category: 'fortinet', + description: 'New Chassis ID ', + name: 'fortinet.firewall.newchassisid', + type: 'integer', + }, + 'fortinet.firewall.newslot': { + category: 'fortinet', + description: 'New Slot Number ', + name: 'fortinet.firewall.newslot', + type: 'integer', + }, + 'fortinet.firewall.nextstat': { + category: 'fortinet', + description: 'Time interval in seconds for the next statistics. ', + name: 'fortinet.firewall.nextstat', + type: 'integer', + }, + 'fortinet.firewall.nf_type': { + category: 'fortinet', + description: 'Notification Type ', + name: 'fortinet.firewall.nf_type', + type: 'keyword', + }, + 'fortinet.firewall.noise': { + category: 'fortinet', + description: 'Wifi Noise ', + name: 'fortinet.firewall.noise', + type: 'integer', + }, + 'fortinet.firewall.old_status': { + category: 'fortinet', + description: 'Original Status ', + name: 'fortinet.firewall.old_status', + type: 'keyword', + }, + 'fortinet.firewall.old_value': { + category: 'fortinet', + description: 'Original Virtual Domain name ', + name: 'fortinet.firewall.old_value', + type: 'keyword', + }, + 'fortinet.firewall.oldchannel': { + category: 'fortinet', + description: 'Original channel ', + name: 'fortinet.firewall.oldchannel', + type: 'integer', + }, + 'fortinet.firewall.oldchassisid': { + category: 'fortinet', + description: 'Original Chassis Number ', + name: 'fortinet.firewall.oldchassisid', + type: 'integer', + }, + 'fortinet.firewall.oldslot': { + category: 'fortinet', + description: 'Original Slot Number ', + name: 'fortinet.firewall.oldslot', + type: 'integer', + }, + 'fortinet.firewall.oldsn': { + category: 'fortinet', + description: 'Old Serial number ', + name: 'fortinet.firewall.oldsn', + type: 'keyword', + }, + 'fortinet.firewall.oldwprof': { + category: 'fortinet', + description: 'Old Web Filter Profile ', + name: 'fortinet.firewall.oldwprof', + type: 'keyword', + }, + 'fortinet.firewall.onwire': { + category: 'fortinet', + description: 'A flag to indicate if the AP is onwire or not ', + name: 'fortinet.firewall.onwire', + type: 'keyword', + }, + 'fortinet.firewall.opercountry': { + category: 'fortinet', + description: 'Operating Country ', + name: 'fortinet.firewall.opercountry', + type: 'keyword', + }, + 'fortinet.firewall.opertxpower': { + category: 'fortinet', + description: 'Operating TX power ', + name: 'fortinet.firewall.opertxpower', + type: 'integer', + }, + 'fortinet.firewall.osname': { + category: 'fortinet', + description: 'Operating System name ', + name: 'fortinet.firewall.osname', + type: 'keyword', + }, + 'fortinet.firewall.osversion': { + category: 'fortinet', + description: 'Operating System version ', + name: 'fortinet.firewall.osversion', + type: 'keyword', + }, + 'fortinet.firewall.out_spi': { + category: 'fortinet', + description: 'Out SPI ', + name: 'fortinet.firewall.out_spi', + type: 'keyword', + }, + 'fortinet.firewall.outintf': { + category: 'fortinet', + description: 'Out interface ', + name: 'fortinet.firewall.outintf', + type: 'keyword', + }, + 'fortinet.firewall.passedcount': { + category: 'fortinet', + description: 'Fabric passed count ', + name: 'fortinet.firewall.passedcount', + type: 'integer', + }, + 'fortinet.firewall.passwd': { + category: 'fortinet', + description: 'Changed user password information ', + name: 'fortinet.firewall.passwd', + type: 'keyword', + }, + 'fortinet.firewall.path': { + category: 'fortinet', + description: 'Path of looped configuration for security fabric ', + name: 'fortinet.firewall.path', + type: 'keyword', + }, + 'fortinet.firewall.peer': { + category: 'fortinet', + description: 'WAN optimization peer ', + name: 'fortinet.firewall.peer', + type: 'keyword', + }, + 'fortinet.firewall.peer_notif': { + category: 'fortinet', + description: 'VPN peer notification ', + name: 'fortinet.firewall.peer_notif', + type: 'keyword', + }, + 'fortinet.firewall.phase2_name': { + category: 'fortinet', + description: 'VPN phase2 name ', + name: 'fortinet.firewall.phase2_name', + type: 'keyword', + }, + 'fortinet.firewall.phone': { + category: 'fortinet', + description: 'VOIP Phone ', + name: 'fortinet.firewall.phone', + type: 'keyword', + }, + 'fortinet.firewall.pid': { + category: 'fortinet', + description: 'Process ID ', + name: 'fortinet.firewall.pid', + type: 'integer', + }, + 'fortinet.firewall.policytype': { + category: 'fortinet', + description: 'Policy Type ', + name: 'fortinet.firewall.policytype', + type: 'keyword', + }, + 'fortinet.firewall.poolname': { + category: 'fortinet', + description: 'IP Pool name ', + name: 'fortinet.firewall.poolname', + type: 'keyword', + }, + 'fortinet.firewall.port': { + category: 'fortinet', + description: 'Log upload error port ', + name: 'fortinet.firewall.port', + type: 'integer', + }, + 'fortinet.firewall.portbegin': { + category: 'fortinet', + description: 'IP Pool port number to begin ', + name: 'fortinet.firewall.portbegin', + type: 'integer', + }, + 'fortinet.firewall.portend': { + category: 'fortinet', + description: 'IP Pool port number to end ', + name: 'fortinet.firewall.portend', + type: 'integer', + }, + 'fortinet.firewall.probeproto': { + category: 'fortinet', + description: 'Link Monitor Probe Protocol ', + name: 'fortinet.firewall.probeproto', + type: 'keyword', + }, + 'fortinet.firewall.process': { + category: 'fortinet', + description: 'URL Filter process ', + name: 'fortinet.firewall.process', + type: 'keyword', + }, + 'fortinet.firewall.processtime': { + category: 'fortinet', + description: 'Process time for reports ', + name: 'fortinet.firewall.processtime', + type: 'integer', + }, + 'fortinet.firewall.profile': { + category: 'fortinet', + description: 'Profile Name ', + name: 'fortinet.firewall.profile', + type: 'keyword', + }, + 'fortinet.firewall.profile_vd': { + category: 'fortinet', + description: 'Virtual Domain Name ', + name: 'fortinet.firewall.profile_vd', + type: 'keyword', + }, + 'fortinet.firewall.profilegroup': { + category: 'fortinet', + description: 'Profile Group Name ', + name: 'fortinet.firewall.profilegroup', + type: 'keyword', + }, + 'fortinet.firewall.profiletype': { + category: 'fortinet', + description: 'Profile Type ', + name: 'fortinet.firewall.profiletype', + type: 'keyword', + }, + 'fortinet.firewall.qtypeval': { + category: 'fortinet', + description: 'DNS question type value ', + name: 'fortinet.firewall.qtypeval', + type: 'integer', + }, + 'fortinet.firewall.quarskip': { + category: 'fortinet', + description: 'Quarantine skip explanation ', + name: 'fortinet.firewall.quarskip', + type: 'keyword', + }, + 'fortinet.firewall.quotaexceeded': { + category: 'fortinet', + description: 'If quota has been exceeded ', + name: 'fortinet.firewall.quotaexceeded', + type: 'keyword', + }, + 'fortinet.firewall.quotamax': { + category: 'fortinet', + description: 'Maximum quota allowed - in seconds if time-based - in bytes if traffic-based ', + name: 'fortinet.firewall.quotamax', + type: 'long', + }, + 'fortinet.firewall.quotatype': { + category: 'fortinet', + description: 'Quota type ', + name: 'fortinet.firewall.quotatype', + type: 'keyword', + }, + 'fortinet.firewall.quotaused': { + category: 'fortinet', + description: 'Quota used - in seconds if time-based - in bytes if trafficbased) ', + name: 'fortinet.firewall.quotaused', + type: 'long', + }, + 'fortinet.firewall.radioband': { + category: 'fortinet', + description: 'Radio band ', + name: 'fortinet.firewall.radioband', + type: 'keyword', + }, + 'fortinet.firewall.radioid': { + category: 'fortinet', + description: 'Radio ID ', + name: 'fortinet.firewall.radioid', + type: 'integer', + }, + 'fortinet.firewall.radioidclosest': { + category: 'fortinet', + description: 'Radio ID on the AP closest the rogue AP ', + name: 'fortinet.firewall.radioidclosest', + type: 'integer', + }, + 'fortinet.firewall.radioiddetected': { + category: 'fortinet', + description: 'Radio ID on the AP which detected the rogue AP ', + name: 'fortinet.firewall.radioiddetected', + type: 'integer', + }, + 'fortinet.firewall.rate': { + category: 'fortinet', + description: 'Wireless rogue rate value ', + name: 'fortinet.firewall.rate', + type: 'keyword', + }, + 'fortinet.firewall.rawdata': { + category: 'fortinet', + description: 'Raw data value ', + name: 'fortinet.firewall.rawdata', + type: 'keyword', + }, + 'fortinet.firewall.rawdataid': { + category: 'fortinet', + description: 'Raw data ID ', + name: 'fortinet.firewall.rawdataid', + type: 'keyword', + }, + 'fortinet.firewall.rcvddelta': { + category: 'fortinet', + description: 'Received bytes delta ', + name: 'fortinet.firewall.rcvddelta', + type: 'keyword', + }, + 'fortinet.firewall.reason': { + category: 'fortinet', + description: 'Alert reason ', + name: 'fortinet.firewall.reason', + type: 'keyword', + }, + 'fortinet.firewall.received': { + category: 'fortinet', + description: 'Server key exchange received ', + name: 'fortinet.firewall.received', + type: 'integer', + }, + 'fortinet.firewall.receivedsignature': { + category: 'fortinet', + description: 'Server key exchange received signature ', + name: 'fortinet.firewall.receivedsignature', + type: 'keyword', + }, + 'fortinet.firewall.red': { + category: 'fortinet', + description: 'Memory information in red ', + name: 'fortinet.firewall.red', + type: 'keyword', + }, + 'fortinet.firewall.referralurl': { + category: 'fortinet', + description: 'Web filter referralurl ', + name: 'fortinet.firewall.referralurl', + type: 'keyword', + }, + 'fortinet.firewall.remote': { + category: 'fortinet', + description: 'Remote PPP IP address ', + name: 'fortinet.firewall.remote', + type: 'ip', + }, + 'fortinet.firewall.remotewtptime': { + category: 'fortinet', + description: 'Remote Wifi Radius authentication time ', + name: 'fortinet.firewall.remotewtptime', + type: 'keyword', + }, + 'fortinet.firewall.reporttype': { + category: 'fortinet', + description: 'Report type ', + name: 'fortinet.firewall.reporttype', + type: 'keyword', + }, + 'fortinet.firewall.reqtype': { + category: 'fortinet', + description: 'Request type ', + name: 'fortinet.firewall.reqtype', + type: 'keyword', + }, + 'fortinet.firewall.request_name': { + category: 'fortinet', + description: 'VOIP request name ', + name: 'fortinet.firewall.request_name', + type: 'keyword', + }, + 'fortinet.firewall.result': { + category: 'fortinet', + description: 'VPN phase result ', + name: 'fortinet.firewall.result', + type: 'keyword', + }, + 'fortinet.firewall.role': { + category: 'fortinet', + description: 'VPN Phase 2 role ', + name: 'fortinet.firewall.role', + type: 'keyword', + }, + 'fortinet.firewall.rssi': { + category: 'fortinet', + description: 'Received signal strength indicator ', + name: 'fortinet.firewall.rssi', + type: 'integer', + }, + 'fortinet.firewall.rsso_key': { + category: 'fortinet', + description: 'RADIUS SSO attribute value ', + name: 'fortinet.firewall.rsso_key', + type: 'keyword', + }, + 'fortinet.firewall.ruledata': { + category: 'fortinet', + description: 'Rule data ', + name: 'fortinet.firewall.ruledata', + type: 'keyword', + }, + 'fortinet.firewall.ruletype': { + category: 'fortinet', + description: 'Rule type ', + name: 'fortinet.firewall.ruletype', + type: 'keyword', + }, + 'fortinet.firewall.scanned': { + category: 'fortinet', + description: 'Number of Scanned MMSs ', + name: 'fortinet.firewall.scanned', + type: 'integer', + }, + 'fortinet.firewall.scantime': { + category: 'fortinet', + description: 'Scanned time ', + name: 'fortinet.firewall.scantime', + type: 'long', + }, + 'fortinet.firewall.scope': { + category: 'fortinet', + description: 'FortiGuard Override Scope ', + name: 'fortinet.firewall.scope', + type: 'keyword', + }, + 'fortinet.firewall.security': { + category: 'fortinet', + description: 'Wireless rogue security ', + name: 'fortinet.firewall.security', + type: 'keyword', + }, + 'fortinet.firewall.sensitivity': { + category: 'fortinet', + description: 'Sensitivity for document fingerprint ', + name: 'fortinet.firewall.sensitivity', + type: 'keyword', + }, + 'fortinet.firewall.sensor': { + category: 'fortinet', + description: 'NAC Sensor Name ', + name: 'fortinet.firewall.sensor', + type: 'keyword', + }, + 'fortinet.firewall.sentdelta': { + category: 'fortinet', + description: 'Sent bytes delta ', + name: 'fortinet.firewall.sentdelta', + type: 'keyword', + }, + 'fortinet.firewall.seq': { + category: 'fortinet', + description: 'Sequence number ', + name: 'fortinet.firewall.seq', + type: 'keyword', + }, + 'fortinet.firewall.serial': { + category: 'fortinet', + description: 'WAN optimisation serial ', + name: 'fortinet.firewall.serial', + type: 'keyword', + }, + 'fortinet.firewall.serialno': { + category: 'fortinet', + description: 'Serial number ', + name: 'fortinet.firewall.serialno', + type: 'keyword', + }, + 'fortinet.firewall.server': { + category: 'fortinet', + description: 'AD server FQDN or IP ', + name: 'fortinet.firewall.server', + type: 'keyword', + }, + 'fortinet.firewall.session_id': { + category: 'fortinet', + description: 'Session ID ', + name: 'fortinet.firewall.session_id', + type: 'keyword', + }, + 'fortinet.firewall.sessionid': { + category: 'fortinet', + description: 'WAD Session ID ', + name: 'fortinet.firewall.sessionid', + type: 'integer', + }, + 'fortinet.firewall.setuprate': { + category: 'fortinet', + description: 'Session Setup Rate ', + name: 'fortinet.firewall.setuprate', + type: 'long', + }, + 'fortinet.firewall.severity': { + category: 'fortinet', + description: 'Severity ', + name: 'fortinet.firewall.severity', + type: 'keyword', + }, + 'fortinet.firewall.shaperdroprcvdbyte': { + category: 'fortinet', + description: 'Received bytes dropped by shaper ', + name: 'fortinet.firewall.shaperdroprcvdbyte', + type: 'integer', + }, + 'fortinet.firewall.shaperdropsentbyte': { + category: 'fortinet', + description: 'Sent bytes dropped by shaper ', + name: 'fortinet.firewall.shaperdropsentbyte', + type: 'integer', + }, + 'fortinet.firewall.shaperperipdropbyte': { + category: 'fortinet', + description: 'Dropped bytes per IP by shaper ', + name: 'fortinet.firewall.shaperperipdropbyte', + type: 'integer', + }, + 'fortinet.firewall.shaperperipname': { + category: 'fortinet', + description: 'Traffic shaper name (per IP) ', + name: 'fortinet.firewall.shaperperipname', + type: 'keyword', + }, + 'fortinet.firewall.shaperrcvdname': { + category: 'fortinet', + description: 'Traffic shaper name for received traffic ', + name: 'fortinet.firewall.shaperrcvdname', + type: 'keyword', + }, + 'fortinet.firewall.shapersentname': { + category: 'fortinet', + description: 'Traffic shaper name for sent traffic ', + name: 'fortinet.firewall.shapersentname', + type: 'keyword', + }, + 'fortinet.firewall.shapingpolicyid': { + category: 'fortinet', + description: 'Traffic shaper policy ID ', + name: 'fortinet.firewall.shapingpolicyid', + type: 'integer', + }, + 'fortinet.firewall.signal': { + category: 'fortinet', + description: 'Wireless rogue API signal ', + name: 'fortinet.firewall.signal', + type: 'integer', + }, + 'fortinet.firewall.size': { + category: 'fortinet', + description: 'Email size in bytes ', + name: 'fortinet.firewall.size', + type: 'long', + }, + 'fortinet.firewall.slot': { + category: 'fortinet', + description: 'Slot number ', + name: 'fortinet.firewall.slot', + type: 'integer', + }, + 'fortinet.firewall.sn': { + category: 'fortinet', + description: 'Security fabric serial number ', + name: 'fortinet.firewall.sn', + type: 'keyword', + }, + 'fortinet.firewall.snclosest': { + category: 'fortinet', + description: 'SN of the AP closest to the rogue AP ', + name: 'fortinet.firewall.snclosest', + type: 'keyword', + }, + 'fortinet.firewall.sndetected': { + category: 'fortinet', + description: 'SN of the AP which detected the rogue AP ', + name: 'fortinet.firewall.sndetected', + type: 'keyword', + }, + 'fortinet.firewall.snmeshparent': { + category: 'fortinet', + description: 'SN of the mesh parent ', + name: 'fortinet.firewall.snmeshparent', + type: 'keyword', + }, + 'fortinet.firewall.spi': { + category: 'fortinet', + description: 'IPSEC SPI ', + name: 'fortinet.firewall.spi', + type: 'keyword', + }, + 'fortinet.firewall.src_int': { + category: 'fortinet', + description: 'Source interface ', + name: 'fortinet.firewall.src_int', + type: 'keyword', + }, + 'fortinet.firewall.srcintfrole': { + category: 'fortinet', + description: 'Source interface role ', + name: 'fortinet.firewall.srcintfrole', + type: 'keyword', + }, + 'fortinet.firewall.srccountry': { + category: 'fortinet', + description: 'Source country ', + name: 'fortinet.firewall.srccountry', + type: 'keyword', + }, + 'fortinet.firewall.srcfamily': { + category: 'fortinet', + description: 'Source family ', + name: 'fortinet.firewall.srcfamily', + type: 'keyword', + }, + 'fortinet.firewall.srchwvendor': { + category: 'fortinet', + description: 'Source hardware vendor ', + name: 'fortinet.firewall.srchwvendor', + type: 'keyword', + }, + 'fortinet.firewall.srchwversion': { + category: 'fortinet', + description: 'Source hardware version ', + name: 'fortinet.firewall.srchwversion', + type: 'keyword', + }, + 'fortinet.firewall.srcinetsvc': { + category: 'fortinet', + description: 'Source interface service ', + name: 'fortinet.firewall.srcinetsvc', + type: 'keyword', + }, + 'fortinet.firewall.srcname': { + category: 'fortinet', + description: 'Source name ', + name: 'fortinet.firewall.srcname', + type: 'keyword', + }, + 'fortinet.firewall.srcserver': { + category: 'fortinet', + description: 'Source server ', + name: 'fortinet.firewall.srcserver', + type: 'integer', + }, + 'fortinet.firewall.srcssid': { + category: 'fortinet', + description: 'Source SSID ', + name: 'fortinet.firewall.srcssid', + type: 'keyword', + }, + 'fortinet.firewall.srcswversion': { + category: 'fortinet', + description: 'Source software version ', + name: 'fortinet.firewall.srcswversion', + type: 'keyword', + }, + 'fortinet.firewall.srcuuid': { + category: 'fortinet', + description: 'Source UUID ', + name: 'fortinet.firewall.srcuuid', + type: 'keyword', + }, + 'fortinet.firewall.sscname': { + category: 'fortinet', + description: 'SSC name ', + name: 'fortinet.firewall.sscname', + type: 'keyword', + }, + 'fortinet.firewall.ssid': { + category: 'fortinet', + description: 'Base Service Set ID ', + name: 'fortinet.firewall.ssid', + type: 'keyword', + }, + 'fortinet.firewall.sslaction': { + category: 'fortinet', + description: 'SSL Action ', + name: 'fortinet.firewall.sslaction', + type: 'keyword', + }, + 'fortinet.firewall.ssllocal': { + category: 'fortinet', + description: 'WAD SSL local ', + name: 'fortinet.firewall.ssllocal', + type: 'keyword', + }, + 'fortinet.firewall.sslremote': { + category: 'fortinet', + description: 'WAD SSL remote ', + name: 'fortinet.firewall.sslremote', + type: 'keyword', + }, + 'fortinet.firewall.stacount': { + category: 'fortinet', + description: 'Number of stations/clients ', + name: 'fortinet.firewall.stacount', + type: 'integer', + }, + 'fortinet.firewall.stage': { + category: 'fortinet', + description: 'IPSEC stage ', + name: 'fortinet.firewall.stage', + type: 'keyword', + }, + 'fortinet.firewall.stamac': { + category: 'fortinet', + description: '802.1x station mac ', + name: 'fortinet.firewall.stamac', + type: 'keyword', + }, + 'fortinet.firewall.state': { + category: 'fortinet', + description: 'Admin login state ', + name: 'fortinet.firewall.state', + type: 'keyword', + }, + 'fortinet.firewall.status': { + category: 'fortinet', + description: 'Status ', + name: 'fortinet.firewall.status', + type: 'keyword', + }, + 'fortinet.firewall.stitch': { + category: 'fortinet', + description: 'Automation stitch triggered ', + name: 'fortinet.firewall.stitch', + type: 'keyword', + }, + 'fortinet.firewall.subject': { + category: 'fortinet', + description: 'Email subject ', + name: 'fortinet.firewall.subject', + type: 'keyword', + }, + 'fortinet.firewall.submodule': { + category: 'fortinet', + description: 'Configuration Sub-Module Name ', + name: 'fortinet.firewall.submodule', + type: 'keyword', + }, + 'fortinet.firewall.subservice': { + category: 'fortinet', + description: 'AV subservice ', + name: 'fortinet.firewall.subservice', + type: 'keyword', + }, + 'fortinet.firewall.subtype': { + category: 'fortinet', + description: 'Log subtype ', + name: 'fortinet.firewall.subtype', + type: 'keyword', + }, + 'fortinet.firewall.suspicious': { + category: 'fortinet', + description: 'Number of Suspicious MMSs ', + name: 'fortinet.firewall.suspicious', + type: 'integer', + }, + 'fortinet.firewall.switchproto': { + category: 'fortinet', + description: 'Protocol change information ', + name: 'fortinet.firewall.switchproto', + type: 'keyword', + }, + 'fortinet.firewall.sync_status': { + category: 'fortinet', + description: 'The sync status with the master ', + name: 'fortinet.firewall.sync_status', + type: 'keyword', + }, + 'fortinet.firewall.sync_type': { + category: 'fortinet', + description: 'The sync type with the master ', + name: 'fortinet.firewall.sync_type', + type: 'keyword', + }, + 'fortinet.firewall.sysuptime': { + category: 'fortinet', + description: 'System uptime ', + name: 'fortinet.firewall.sysuptime', + type: 'keyword', + }, + 'fortinet.firewall.tamac': { + category: 'fortinet', + description: 'the MAC address of Transmitter, if none, then Receiver ', + name: 'fortinet.firewall.tamac', + type: 'keyword', + }, + 'fortinet.firewall.threattype': { + category: 'fortinet', + description: 'WIDS threat type ', + name: 'fortinet.firewall.threattype', + type: 'keyword', + }, + 'fortinet.firewall.time': { + category: 'fortinet', + description: 'Time of the event ', + name: 'fortinet.firewall.time', + type: 'keyword', + }, + 'fortinet.firewall.to': { + category: 'fortinet', + description: 'Email to field ', + name: 'fortinet.firewall.to', + type: 'keyword', + }, + 'fortinet.firewall.to_vcluster': { + category: 'fortinet', + description: 'destination virtual cluster number ', + name: 'fortinet.firewall.to_vcluster', + type: 'integer', + }, + 'fortinet.firewall.total': { + category: 'fortinet', + description: 'Total memory ', + name: 'fortinet.firewall.total', + type: 'integer', + }, + 'fortinet.firewall.totalsession': { + category: 'fortinet', + description: 'Total Number of Sessions ', + name: 'fortinet.firewall.totalsession', + type: 'integer', + }, + 'fortinet.firewall.trace_id': { + category: 'fortinet', + description: 'Session clash trace ID ', + name: 'fortinet.firewall.trace_id', + type: 'keyword', + }, + 'fortinet.firewall.trandisp': { + category: 'fortinet', + description: 'NAT translation type ', + name: 'fortinet.firewall.trandisp', + type: 'keyword', + }, + 'fortinet.firewall.transid': { + category: 'fortinet', + description: 'HTTP transaction ID ', + name: 'fortinet.firewall.transid', + type: 'integer', + }, + 'fortinet.firewall.translationid': { + category: 'fortinet', + description: 'DNS filter transaltion ID ', + name: 'fortinet.firewall.translationid', + type: 'keyword', + }, + 'fortinet.firewall.trigger': { + category: 'fortinet', + description: 'Automation stitch trigger ', + name: 'fortinet.firewall.trigger', + type: 'keyword', + }, + 'fortinet.firewall.trueclntip': { + category: 'fortinet', + description: 'File filter true client IP ', + name: 'fortinet.firewall.trueclntip', + type: 'ip', + }, + 'fortinet.firewall.tunnelid': { + category: 'fortinet', + description: 'IPSEC tunnel ID ', + name: 'fortinet.firewall.tunnelid', + type: 'integer', + }, + 'fortinet.firewall.tunnelip': { + category: 'fortinet', + description: 'IPSEC tunnel IP ', + name: 'fortinet.firewall.tunnelip', + type: 'ip', + }, + 'fortinet.firewall.tunneltype': { + category: 'fortinet', + description: 'IPSEC tunnel type ', + name: 'fortinet.firewall.tunneltype', + type: 'keyword', + }, + 'fortinet.firewall.type': { + category: 'fortinet', + description: 'Module type ', + name: 'fortinet.firewall.type', + type: 'keyword', + }, + 'fortinet.firewall.ui': { + category: 'fortinet', + description: 'Admin authentication UI type ', + name: 'fortinet.firewall.ui', + type: 'keyword', + }, + 'fortinet.firewall.unauthusersource': { + category: 'fortinet', + description: 'Unauthenticated user source ', + name: 'fortinet.firewall.unauthusersource', + type: 'keyword', + }, + 'fortinet.firewall.unit': { + category: 'fortinet', + description: 'Power supply unit ', + name: 'fortinet.firewall.unit', + type: 'integer', + }, + 'fortinet.firewall.urlfilteridx': { + category: 'fortinet', + description: 'URL filter ID ', + name: 'fortinet.firewall.urlfilteridx', + type: 'integer', + }, + 'fortinet.firewall.urlfilterlist': { + category: 'fortinet', + description: 'URL filter list ', + name: 'fortinet.firewall.urlfilterlist', + type: 'keyword', + }, + 'fortinet.firewall.urlsource': { + category: 'fortinet', + description: 'URL filter source ', + name: 'fortinet.firewall.urlsource', + type: 'keyword', + }, + 'fortinet.firewall.urltype': { + category: 'fortinet', + description: 'URL filter type ', + name: 'fortinet.firewall.urltype', + type: 'keyword', + }, + 'fortinet.firewall.used': { + category: 'fortinet', + description: 'Number of Used IPs ', + name: 'fortinet.firewall.used', + type: 'integer', + }, + 'fortinet.firewall.used_for_type': { + category: 'fortinet', + description: 'Connection for the type ', + name: 'fortinet.firewall.used_for_type', + type: 'integer', + }, + 'fortinet.firewall.utmaction': { + category: 'fortinet', + description: 'Security action performed by UTM ', + name: 'fortinet.firewall.utmaction', + type: 'keyword', + }, + 'fortinet.firewall.vap': { + category: 'fortinet', + description: 'Virtual AP ', + name: 'fortinet.firewall.vap', + type: 'keyword', + }, + 'fortinet.firewall.vapmode': { + category: 'fortinet', + description: 'Virtual AP mode ', + name: 'fortinet.firewall.vapmode', + type: 'keyword', + }, + 'fortinet.firewall.vcluster': { + category: 'fortinet', + description: 'virtual cluster id ', + name: 'fortinet.firewall.vcluster', + type: 'integer', + }, + 'fortinet.firewall.vcluster_member': { + category: 'fortinet', + description: 'Virtual cluster member ', + name: 'fortinet.firewall.vcluster_member', + type: 'integer', + }, + 'fortinet.firewall.vcluster_state': { + category: 'fortinet', + description: 'Virtual cluster state ', + name: 'fortinet.firewall.vcluster_state', + type: 'keyword', + }, + 'fortinet.firewall.vd': { + category: 'fortinet', + description: 'Virtual Domain Name ', + name: 'fortinet.firewall.vd', + type: 'keyword', + }, + 'fortinet.firewall.vdname': { + category: 'fortinet', + description: 'Virtual Domain Name ', + name: 'fortinet.firewall.vdname', + type: 'keyword', + }, + 'fortinet.firewall.vendorurl': { + category: 'fortinet', + description: 'Vulnerability scan vendor name ', + name: 'fortinet.firewall.vendorurl', + type: 'keyword', + }, + 'fortinet.firewall.version': { + category: 'fortinet', + description: 'Version ', + name: 'fortinet.firewall.version', + type: 'keyword', + }, + 'fortinet.firewall.vip': { + category: 'fortinet', + description: 'Virtual IP ', + name: 'fortinet.firewall.vip', + type: 'keyword', + }, + 'fortinet.firewall.virus': { + category: 'fortinet', + description: 'Virus name ', + name: 'fortinet.firewall.virus', + type: 'keyword', + }, + 'fortinet.firewall.virusid': { + category: 'fortinet', + description: 'Virus ID (unique virus identifier) ', + name: 'fortinet.firewall.virusid', + type: 'integer', + }, + 'fortinet.firewall.voip_proto': { + category: 'fortinet', + description: 'VOIP protocol ', + name: 'fortinet.firewall.voip_proto', + type: 'keyword', + }, + 'fortinet.firewall.vpn': { + category: 'fortinet', + description: 'VPN description ', + name: 'fortinet.firewall.vpn', + type: 'keyword', + }, + 'fortinet.firewall.vpntunnel': { + category: 'fortinet', + description: 'IPsec Vpn Tunnel Name ', + name: 'fortinet.firewall.vpntunnel', + type: 'keyword', + }, + 'fortinet.firewall.vpntype': { + category: 'fortinet', + description: 'The type of the VPN tunnel ', + name: 'fortinet.firewall.vpntype', + type: 'keyword', + }, + 'fortinet.firewall.vrf': { + category: 'fortinet', + description: 'VRF number ', + name: 'fortinet.firewall.vrf', + type: 'integer', + }, + 'fortinet.firewall.vulncat': { + category: 'fortinet', + description: 'Vulnerability Category ', + name: 'fortinet.firewall.vulncat', + type: 'keyword', + }, + 'fortinet.firewall.vulnid': { + category: 'fortinet', + description: 'Vulnerability ID ', + name: 'fortinet.firewall.vulnid', + type: 'integer', + }, + 'fortinet.firewall.vulnname': { + category: 'fortinet', + description: 'Vulnerability name ', + name: 'fortinet.firewall.vulnname', + type: 'keyword', + }, + 'fortinet.firewall.vwlid': { + category: 'fortinet', + description: 'VWL ID ', + name: 'fortinet.firewall.vwlid', + type: 'integer', + }, + 'fortinet.firewall.vwlquality': { + category: 'fortinet', + description: 'VWL quality ', + name: 'fortinet.firewall.vwlquality', + type: 'keyword', + }, + 'fortinet.firewall.vwlservice': { + category: 'fortinet', + description: 'VWL service ', + name: 'fortinet.firewall.vwlservice', + type: 'keyword', + }, + 'fortinet.firewall.vwpvlanid': { + category: 'fortinet', + description: 'VWP VLAN ID ', + name: 'fortinet.firewall.vwpvlanid', + type: 'integer', + }, + 'fortinet.firewall.wanin': { + category: 'fortinet', + description: 'WAN incoming traffic in bytes ', + name: 'fortinet.firewall.wanin', + type: 'long', + }, + 'fortinet.firewall.wanoptapptype': { + category: 'fortinet', + description: 'WAN Optimization Application type ', + name: 'fortinet.firewall.wanoptapptype', + type: 'keyword', + }, + 'fortinet.firewall.wanout': { + category: 'fortinet', + description: 'WAN outgoing traffic in bytes ', + name: 'fortinet.firewall.wanout', + type: 'long', + }, + 'fortinet.firewall.weakwepiv': { + category: 'fortinet', + description: 'Weak Wep Initiation Vector ', + name: 'fortinet.firewall.weakwepiv', + type: 'keyword', + }, + 'fortinet.firewall.xauthgroup': { + category: 'fortinet', + description: 'XAuth Group Name ', + name: 'fortinet.firewall.xauthgroup', + type: 'keyword', + }, + 'fortinet.firewall.xauthuser': { + category: 'fortinet', + description: 'XAuth User Name ', + name: 'fortinet.firewall.xauthuser', + type: 'keyword', + }, + 'fortinet.firewall.xid': { + category: 'fortinet', + description: 'Wireless X ID ', + name: 'fortinet.firewall.xid', + type: 'integer', + }, + 'googlecloud.destination.instance.project_id': { + category: 'googlecloud', + description: 'ID of the project containing the VM. ', + name: 'googlecloud.destination.instance.project_id', + type: 'keyword', + }, + 'googlecloud.destination.instance.region': { + category: 'googlecloud', + description: 'Region of the VM. ', + name: 'googlecloud.destination.instance.region', + type: 'keyword', + }, + 'googlecloud.destination.instance.zone': { + category: 'googlecloud', + description: 'Zone of the VM. ', + name: 'googlecloud.destination.instance.zone', + type: 'keyword', + }, + 'googlecloud.destination.vpc.project_id': { + category: 'googlecloud', + description: 'ID of the project containing the VM. ', + name: 'googlecloud.destination.vpc.project_id', + type: 'keyword', + }, + 'googlecloud.destination.vpc.vpc_name': { + category: 'googlecloud', + description: 'VPC on which the VM is operating. ', + name: 'googlecloud.destination.vpc.vpc_name', + type: 'keyword', + }, + 'googlecloud.destination.vpc.subnetwork_name': { + category: 'googlecloud', + description: 'Subnetwork on which the VM is operating. ', + name: 'googlecloud.destination.vpc.subnetwork_name', + type: 'keyword', + }, + 'googlecloud.source.instance.project_id': { + category: 'googlecloud', + description: 'ID of the project containing the VM. ', + name: 'googlecloud.source.instance.project_id', + type: 'keyword', + }, + 'googlecloud.source.instance.region': { + category: 'googlecloud', + description: 'Region of the VM. ', + name: 'googlecloud.source.instance.region', + type: 'keyword', + }, + 'googlecloud.source.instance.zone': { + category: 'googlecloud', + description: 'Zone of the VM. ', + name: 'googlecloud.source.instance.zone', + type: 'keyword', + }, + 'googlecloud.source.vpc.project_id': { + category: 'googlecloud', + description: 'ID of the project containing the VM. ', + name: 'googlecloud.source.vpc.project_id', + type: 'keyword', + }, + 'googlecloud.source.vpc.vpc_name': { + category: 'googlecloud', + description: 'VPC on which the VM is operating. ', + name: 'googlecloud.source.vpc.vpc_name', + type: 'keyword', + }, + 'googlecloud.source.vpc.subnetwork_name': { + category: 'googlecloud', + description: 'Subnetwork on which the VM is operating. ', + name: 'googlecloud.source.vpc.subnetwork_name', + type: 'keyword', + }, + 'googlecloud.audit.type': { + category: 'googlecloud', + description: 'Type property. ', + name: 'googlecloud.audit.type', + type: 'keyword', + }, + 'googlecloud.audit.authentication_info.principal_email': { + category: 'googlecloud', + description: 'The email address of the authenticated user making the request. ', + name: 'googlecloud.audit.authentication_info.principal_email', + type: 'keyword', + }, + 'googlecloud.audit.authentication_info.authority_selector': { + category: 'googlecloud', + description: + 'The authority selector specified by the requestor, if any. It is not guaranteed that the principal was allowed to use this authority. ', + name: 'googlecloud.audit.authentication_info.authority_selector', + type: 'keyword', + }, + 'googlecloud.audit.authorization_info.permission': { + category: 'googlecloud', + description: 'The required IAM permission. ', + name: 'googlecloud.audit.authorization_info.permission', + type: 'keyword', + }, + 'googlecloud.audit.authorization_info.granted': { + category: 'googlecloud', + description: 'Whether or not authorization for resource and permission was granted. ', + name: 'googlecloud.audit.authorization_info.granted', + type: 'boolean', + }, + 'googlecloud.audit.authorization_info.resource_attributes.service': { + category: 'googlecloud', + description: 'The name of the service. ', + name: 'googlecloud.audit.authorization_info.resource_attributes.service', + type: 'keyword', + }, + 'googlecloud.audit.authorization_info.resource_attributes.name': { + category: 'googlecloud', + description: 'The name of the resource. ', + name: 'googlecloud.audit.authorization_info.resource_attributes.name', + type: 'keyword', + }, + 'googlecloud.audit.authorization_info.resource_attributes.type': { + category: 'googlecloud', + description: 'The type of the resource. ', + name: 'googlecloud.audit.authorization_info.resource_attributes.type', + type: 'keyword', + }, + 'googlecloud.audit.method_name': { + category: 'googlecloud', + description: + "The name of the service method or operation. For API calls, this should be the name of the API method. For example, 'google.datastore.v1.Datastore.RunQuery'. ", + name: 'googlecloud.audit.method_name', + type: 'keyword', + }, + 'googlecloud.audit.num_response_items': { + category: 'googlecloud', + description: 'The number of items returned from a List or Query API method, if applicable. ', + name: 'googlecloud.audit.num_response_items', + type: 'long', + }, + 'googlecloud.audit.request.proto_name': { + category: 'googlecloud', + description: 'Type property of the request. ', + name: 'googlecloud.audit.request.proto_name', + type: 'keyword', + }, + 'googlecloud.audit.request.filter': { + category: 'googlecloud', + description: 'Filter of the request. ', + name: 'googlecloud.audit.request.filter', + type: 'keyword', + }, + 'googlecloud.audit.request.name': { + category: 'googlecloud', + description: 'Name of the request. ', + name: 'googlecloud.audit.request.name', + type: 'keyword', + }, + 'googlecloud.audit.request.resource_name': { + category: 'googlecloud', + description: 'Name of the request resource. ', + name: 'googlecloud.audit.request.resource_name', + type: 'keyword', + }, + 'googlecloud.audit.request_metadata.caller_ip': { + category: 'googlecloud', + description: 'The IP address of the caller. ', + name: 'googlecloud.audit.request_metadata.caller_ip', + type: 'ip', + }, + 'googlecloud.audit.request_metadata.caller_supplied_user_agent': { + category: 'googlecloud', + description: + 'The user agent of the caller. This information is not authenticated and should be treated accordingly. ', + name: 'googlecloud.audit.request_metadata.caller_supplied_user_agent', + type: 'keyword', + }, + 'googlecloud.audit.response.proto_name': { + category: 'googlecloud', + description: 'Type property of the response. ', + name: 'googlecloud.audit.response.proto_name', + type: 'keyword', + }, + 'googlecloud.audit.response.details.group': { + category: 'googlecloud', + description: 'The name of the group. ', + name: 'googlecloud.audit.response.details.group', + type: 'keyword', + }, + 'googlecloud.audit.response.details.kind': { + category: 'googlecloud', + description: 'The kind of the response details. ', + name: 'googlecloud.audit.response.details.kind', + type: 'keyword', + }, + 'googlecloud.audit.response.details.name': { + category: 'googlecloud', + description: 'The name of the response details. ', + name: 'googlecloud.audit.response.details.name', + type: 'keyword', + }, + 'googlecloud.audit.response.details.uid': { + category: 'googlecloud', + description: 'The uid of the response details. ', + name: 'googlecloud.audit.response.details.uid', + type: 'keyword', + }, + 'googlecloud.audit.response.status': { + category: 'googlecloud', + description: 'Status of the response. ', + name: 'googlecloud.audit.response.status', + type: 'keyword', + }, + 'googlecloud.audit.resource_name': { + category: 'googlecloud', + description: + "The resource or collection that is the target of the operation. The name is a scheme-less URI, not including the API service name. For example, 'shelves/SHELF_ID/books'. ", + name: 'googlecloud.audit.resource_name', + type: 'keyword', + }, + 'googlecloud.audit.resource_location.current_locations': { + category: 'googlecloud', + description: 'Current locations of the resource. ', + name: 'googlecloud.audit.resource_location.current_locations', + type: 'keyword', + }, + 'googlecloud.audit.service_name': { + category: 'googlecloud', + description: + 'The name of the API service performing the operation. For example, datastore.googleapis.com. ', + name: 'googlecloud.audit.service_name', + type: 'keyword', + }, + 'googlecloud.audit.status.code': { + category: 'googlecloud', + description: 'The status code, which should be an enum value of google.rpc.Code. ', + name: 'googlecloud.audit.status.code', + type: 'integer', + }, + 'googlecloud.audit.status.message': { + category: 'googlecloud', + description: + 'A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client. ', + name: 'googlecloud.audit.status.message', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.priority': { + category: 'googlecloud', + description: 'The priority for the firewall rule.', + name: 'googlecloud.firewall.rule_details.priority', + type: 'long', + }, + 'googlecloud.firewall.rule_details.action': { + category: 'googlecloud', + description: 'Action that the rule performs on match.', + name: 'googlecloud.firewall.rule_details.action', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.direction': { + category: 'googlecloud', + description: 'Direction of traffic that matches this rule.', + name: 'googlecloud.firewall.rule_details.direction', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.reference': { + category: 'googlecloud', + description: 'Reference to the firewall rule.', + name: 'googlecloud.firewall.rule_details.reference', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.source_range': { + category: 'googlecloud', + description: 'List of source ranges that the firewall rule applies to.', + name: 'googlecloud.firewall.rule_details.source_range', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.destination_range': { + category: 'googlecloud', + description: 'List of destination ranges that the firewall applies to.', + name: 'googlecloud.firewall.rule_details.destination_range', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.source_tag': { + category: 'googlecloud', + description: 'List of all the source tags that the firewall rule applies to. ', + name: 'googlecloud.firewall.rule_details.source_tag', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.target_tag': { + category: 'googlecloud', + description: 'List of all the target tags that the firewall rule applies to. ', + name: 'googlecloud.firewall.rule_details.target_tag', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.ip_port_info': { + category: 'googlecloud', + description: 'List of ip protocols and applicable port ranges for rules. ', + name: 'googlecloud.firewall.rule_details.ip_port_info', + type: 'array', + }, + 'googlecloud.firewall.rule_details.source_service_account': { + category: 'googlecloud', + description: 'List of all the source service accounts that the firewall rule applies to. ', + name: 'googlecloud.firewall.rule_details.source_service_account', + type: 'keyword', + }, + 'googlecloud.firewall.rule_details.target_service_account': { + category: 'googlecloud', + description: 'List of all the target service accounts that the firewall rule applies to. ', + name: 'googlecloud.firewall.rule_details.target_service_account', + type: 'keyword', + }, + 'googlecloud.vpcflow.reporter': { + category: 'googlecloud', + description: "The side which reported the flow. Can be either 'SRC' or 'DEST'. ", + name: 'googlecloud.vpcflow.reporter', + type: 'keyword', + }, + 'googlecloud.vpcflow.rtt.ms': { + category: 'googlecloud', + description: + 'Latency as measured (for TCP flows only) during the time interval. This is the time elapsed between sending a SEQ and receiving a corresponding ACK and it contains the network RTT as well as the application related delay. ', + name: 'googlecloud.vpcflow.rtt.ms', + type: 'long', + }, + 'gsuite.actor.type': { + category: 'gsuite', + description: + 'The type of actor. Values can be: *USER*: Another user in the same domain. *EXTERNAL_USER*: A user outside the domain. *KEY*: A non-human actor. ', + name: 'gsuite.actor.type', + type: 'keyword', + }, + 'gsuite.actor.key': { + category: 'gsuite', + description: + 'Only present when `actor.type` is `KEY`. Can be the `consumer_key` of the requestor for OAuth 2LO API requests or an identifier for robot accounts. ', + name: 'gsuite.actor.key', + type: 'keyword', + }, + 'gsuite.event.type': { + category: 'gsuite', + description: + 'The type of GSuite event, mapped from `items[].events[].type` in the original payload. Each fileset can have a different set of values for it, more details can be found at https://developers.google.com/admin-sdk/reports/v1/reference/activities/list ', + example: 'audit#activity', + name: 'gsuite.event.type', + type: 'keyword', + }, + 'gsuite.kind': { + category: 'gsuite', + description: + 'The type of API resource, mapped from `kind` in the original payload. More details can be found at https://developers.google.com/admin-sdk/reports/v1/reference/activities/list ', + example: 'audit#activity', + name: 'gsuite.kind', + type: 'keyword', + }, + 'gsuite.organization.domain': { + category: 'gsuite', + description: "The domain that is affected by the report's event. ", + name: 'gsuite.organization.domain', + type: 'keyword', + }, + 'gsuite.admin.application.edition': { + category: 'gsuite', + description: 'The GSuite edition.', + name: 'gsuite.admin.application.edition', + type: 'keyword', + }, + 'gsuite.admin.application.name': { + category: 'gsuite', + description: "The application's name.", + name: 'gsuite.admin.application.name', + type: 'keyword', + }, + 'gsuite.admin.application.enabled': { + category: 'gsuite', + description: 'The enabled application.', + name: 'gsuite.admin.application.enabled', + type: 'keyword', + }, + 'gsuite.admin.application.licences_order_number': { + category: 'gsuite', + description: 'Order number used to redeem licenses.', + name: 'gsuite.admin.application.licences_order_number', + type: 'keyword', + }, + 'gsuite.admin.application.licences_purchased': { + category: 'gsuite', + description: 'Number of licences purchased.', + name: 'gsuite.admin.application.licences_purchased', + type: 'keyword', + }, + 'gsuite.admin.application.id': { + category: 'gsuite', + description: 'The application ID.', + name: 'gsuite.admin.application.id', + type: 'keyword', + }, + 'gsuite.admin.application.asp_id': { + category: 'gsuite', + description: 'The application specific password ID.', + name: 'gsuite.admin.application.asp_id', + type: 'keyword', + }, + 'gsuite.admin.application.package_id': { + category: 'gsuite', + description: 'The mobile application package ID.', + name: 'gsuite.admin.application.package_id', + type: 'keyword', + }, + 'gsuite.admin.group.email': { + category: 'gsuite', + description: "The group's primary email address.", + name: 'gsuite.admin.group.email', + type: 'keyword', + }, + 'gsuite.admin.new_value': { + category: 'gsuite', + description: 'The new value for the setting.', + name: 'gsuite.admin.new_value', + type: 'keyword', + }, + 'gsuite.admin.old_value': { + category: 'gsuite', + description: 'The old value for the setting.', + name: 'gsuite.admin.old_value', + type: 'keyword', + }, + 'gsuite.admin.org_unit.name': { + category: 'gsuite', + description: 'The organizational unit name.', + name: 'gsuite.admin.org_unit.name', + type: 'keyword', + }, + 'gsuite.admin.org_unit.full': { + category: 'gsuite', + description: 'The org unit full path including the root org unit name.', + name: 'gsuite.admin.org_unit.full', + type: 'keyword', + }, + 'gsuite.admin.setting.name': { + category: 'gsuite', + description: 'The setting name.', + name: 'gsuite.admin.setting.name', + type: 'keyword', + }, + 'gsuite.admin.user_defined_setting.name': { + category: 'gsuite', + description: 'The name of the user-defined setting.', + name: 'gsuite.admin.user_defined_setting.name', + type: 'keyword', + }, + 'gsuite.admin.setting.description': { + category: 'gsuite', + description: 'The setting name.', + name: 'gsuite.admin.setting.description', + type: 'keyword', + }, + 'gsuite.admin.group.priorities': { + category: 'gsuite', + description: 'Group priorities.', + name: 'gsuite.admin.group.priorities', + type: 'keyword', + }, + 'gsuite.admin.domain.alias': { + category: 'gsuite', + description: 'The domain alias.', + name: 'gsuite.admin.domain.alias', + type: 'keyword', + }, + 'gsuite.admin.domain.name': { + category: 'gsuite', + description: 'The primary domain name.', + name: 'gsuite.admin.domain.name', + type: 'keyword', + }, + 'gsuite.admin.domain.secondary_name': { + category: 'gsuite', + description: 'The secondary domain name.', + name: 'gsuite.admin.domain.secondary_name', + type: 'keyword', + }, + 'gsuite.admin.managed_configuration': { + category: 'gsuite', + description: 'The name of the managed configuration.', + name: 'gsuite.admin.managed_configuration', + type: 'keyword', + }, + 'gsuite.admin.non_featured_services_selection': { + category: 'gsuite', + description: + 'Non-featured services selection. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-application-settings#FLASHLIGHT_EDU_NON_FEATURED_SERVICES_SELECTED ', + name: 'gsuite.admin.non_featured_services_selection', + type: 'keyword', + }, + 'gsuite.admin.field': { + category: 'gsuite', + description: 'The name of the field.', + name: 'gsuite.admin.field', + type: 'keyword', + }, + 'gsuite.admin.resource.id': { + category: 'gsuite', + description: 'The name of the resource identifier.', + name: 'gsuite.admin.resource.id', + type: 'keyword', + }, + 'gsuite.admin.user.email': { + category: 'gsuite', + description: "The user's primary email address.", + name: 'gsuite.admin.user.email', + type: 'keyword', + }, + 'gsuite.admin.user.nickname': { + category: 'gsuite', + description: "The user's nickname.", + name: 'gsuite.admin.user.nickname', + type: 'keyword', + }, + 'gsuite.admin.user.birthdate': { + category: 'gsuite', + description: "The user's birth date.", + name: 'gsuite.admin.user.birthdate', + type: 'date', + }, + 'gsuite.admin.gateway.name': { + category: 'gsuite', + description: 'Gateway name. Present on some chat settings.', + name: 'gsuite.admin.gateway.name', + type: 'keyword', + }, + 'gsuite.admin.chrome_os.session_type': { + category: 'gsuite', + description: 'Chrome OS session type.', + name: 'gsuite.admin.chrome_os.session_type', + type: 'keyword', + }, + 'gsuite.admin.device.serial_number': { + category: 'gsuite', + description: 'Device serial number.', + name: 'gsuite.admin.device.serial_number', + type: 'keyword', + }, + 'gsuite.admin.device.id': { + category: 'gsuite', + name: 'gsuite.admin.device.id', + type: 'keyword', + }, + 'gsuite.admin.device.type': { + category: 'gsuite', + description: 'Device type.', + name: 'gsuite.admin.device.type', + type: 'keyword', + }, + 'gsuite.admin.print_server.name': { + category: 'gsuite', + description: 'The name of the print server.', + name: 'gsuite.admin.print_server.name', + type: 'keyword', + }, + 'gsuite.admin.printer.name': { + category: 'gsuite', + description: 'The name of the printer.', + name: 'gsuite.admin.printer.name', + type: 'keyword', + }, + 'gsuite.admin.device.command_details': { + category: 'gsuite', + description: 'Command details.', + name: 'gsuite.admin.device.command_details', + type: 'keyword', + }, + 'gsuite.admin.role.id': { + category: 'gsuite', + description: 'Unique identifier for this role privilege.', + name: 'gsuite.admin.role.id', + type: 'keyword', + }, + 'gsuite.admin.role.name': { + category: 'gsuite', + description: + 'The role name. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-delegated-admin-settings ', + name: 'gsuite.admin.role.name', + type: 'keyword', + }, + 'gsuite.admin.privilege.name': { + category: 'gsuite', + description: 'Privilege name.', + name: 'gsuite.admin.privilege.name', + type: 'keyword', + }, + 'gsuite.admin.service.name': { + category: 'gsuite', + description: 'The service name.', + name: 'gsuite.admin.service.name', + type: 'keyword', + }, + 'gsuite.admin.url.name': { + category: 'gsuite', + description: 'The website name.', + name: 'gsuite.admin.url.name', + type: 'keyword', + }, + 'gsuite.admin.product.name': { + category: 'gsuite', + description: 'The product name.', + name: 'gsuite.admin.product.name', + type: 'keyword', + }, + 'gsuite.admin.product.sku': { + category: 'gsuite', + description: 'The product SKU.', + name: 'gsuite.admin.product.sku', + type: 'keyword', + }, + 'gsuite.admin.bulk_upload.failed': { + category: 'gsuite', + description: 'Number of failed records in bulk upload operation.', + name: 'gsuite.admin.bulk_upload.failed', + type: 'long', + }, + 'gsuite.admin.bulk_upload.total': { + category: 'gsuite', + description: 'Number of total records in bulk upload operation.', + name: 'gsuite.admin.bulk_upload.total', + type: 'long', + }, + 'gsuite.admin.group.allowed_list': { + category: 'gsuite', + description: 'Names of allow-listed groups.', + name: 'gsuite.admin.group.allowed_list', + type: 'keyword', + }, + 'gsuite.admin.email.quarantine_name': { + category: 'gsuite', + description: 'The name of the quarantine.', + name: 'gsuite.admin.email.quarantine_name', + type: 'keyword', + }, + 'gsuite.admin.email.log_search_filter.message_id': { + category: 'gsuite', + description: "The log search filter's email message ID.", + name: 'gsuite.admin.email.log_search_filter.message_id', + type: 'keyword', + }, + 'gsuite.admin.email.log_search_filter.start_date': { + category: 'gsuite', + description: "The log search filter's start date.", + name: 'gsuite.admin.email.log_search_filter.start_date', + type: 'date', + }, + 'gsuite.admin.email.log_search_filter.end_date': { + category: 'gsuite', + description: "The log search filter's ending date.", + name: 'gsuite.admin.email.log_search_filter.end_date', + type: 'date', + }, + 'gsuite.admin.email.log_search_filter.recipient.value': { + category: 'gsuite', + description: "The log search filter's email recipient.", + name: 'gsuite.admin.email.log_search_filter.recipient.value', + type: 'keyword', + }, + 'gsuite.admin.email.log_search_filter.sender.value': { + category: 'gsuite', + description: "The log search filter's email sender.", + name: 'gsuite.admin.email.log_search_filter.sender.value', + type: 'keyword', + }, + 'gsuite.admin.email.log_search_filter.recipient.ip': { + category: 'gsuite', + description: "The log search filter's email recipient's IP address.", + name: 'gsuite.admin.email.log_search_filter.recipient.ip', + type: 'ip', + }, + 'gsuite.admin.email.log_search_filter.sender.ip': { + category: 'gsuite', + description: "The log search filter's email sender's IP address.", + name: 'gsuite.admin.email.log_search_filter.sender.ip', + type: 'ip', + }, + 'gsuite.admin.chrome_licenses.enabled': { + category: 'gsuite', + description: + 'Licences enabled. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-org-settings ', + name: 'gsuite.admin.chrome_licenses.enabled', + type: 'keyword', + }, + 'gsuite.admin.chrome_licenses.allowed': { + category: 'gsuite', + description: + 'Licences enabled. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-org-settings ', + name: 'gsuite.admin.chrome_licenses.allowed', + type: 'keyword', + }, + 'gsuite.admin.oauth2.service.name': { + category: 'gsuite', + description: + 'OAuth2 service name. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-security-settings ', + name: 'gsuite.admin.oauth2.service.name', + type: 'keyword', + }, + 'gsuite.admin.oauth2.application.id': { + category: 'gsuite', + description: 'OAuth2 application ID.', + name: 'gsuite.admin.oauth2.application.id', + type: 'keyword', + }, + 'gsuite.admin.oauth2.application.name': { + category: 'gsuite', + description: 'OAuth2 application name.', + name: 'gsuite.admin.oauth2.application.name', + type: 'keyword', + }, + 'gsuite.admin.oauth2.application.type': { + category: 'gsuite', + description: + 'OAuth2 application type. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-security-settings ', + name: 'gsuite.admin.oauth2.application.type', + type: 'keyword', + }, + 'gsuite.admin.verification_method': { + category: 'gsuite', + description: + 'Related verification method. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-security-settings and https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-domain-settings ', + name: 'gsuite.admin.verification_method', + type: 'keyword', + }, + 'gsuite.admin.alert.name': { + category: 'gsuite', + description: 'The alert name.', + name: 'gsuite.admin.alert.name', + type: 'keyword', + }, + 'gsuite.admin.rule.name': { + category: 'gsuite', + description: 'The rule name.', + name: 'gsuite.admin.rule.name', + type: 'keyword', + }, + 'gsuite.admin.api.client.name': { + category: 'gsuite', + description: 'The API client name.', + name: 'gsuite.admin.api.client.name', + type: 'keyword', + }, + 'gsuite.admin.api.scopes': { + category: 'gsuite', + description: 'The API scopes.', + name: 'gsuite.admin.api.scopes', + type: 'keyword', + }, + 'gsuite.admin.mdm.token': { + category: 'gsuite', + description: 'The MDM vendor enrollment token.', + name: 'gsuite.admin.mdm.token', + type: 'keyword', + }, + 'gsuite.admin.mdm.vendor': { + category: 'gsuite', + description: "The MDM vendor's name.", + name: 'gsuite.admin.mdm.vendor', + type: 'keyword', + }, + 'gsuite.admin.info_type': { + category: 'gsuite', + description: + 'This will be used to state what kind of information was changed. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-domain-settings ', + name: 'gsuite.admin.info_type', + type: 'keyword', + }, + 'gsuite.admin.email_monitor.dest_email': { + category: 'gsuite', + description: 'The destination address of the email monitor.', + name: 'gsuite.admin.email_monitor.dest_email', + type: 'keyword', + }, + 'gsuite.admin.email_monitor.level.chat': { + category: 'gsuite', + description: 'The chat email monitor level.', + name: 'gsuite.admin.email_monitor.level.chat', + type: 'keyword', + }, + 'gsuite.admin.email_monitor.level.draft': { + category: 'gsuite', + description: 'The draft email monitor level.', + name: 'gsuite.admin.email_monitor.level.draft', + type: 'keyword', + }, + 'gsuite.admin.email_monitor.level.incoming': { + category: 'gsuite', + description: 'The incoming email monitor level.', + name: 'gsuite.admin.email_monitor.level.incoming', + type: 'keyword', + }, + 'gsuite.admin.email_monitor.level.outgoing': { + category: 'gsuite', + description: 'The outgoing email monitor level.', + name: 'gsuite.admin.email_monitor.level.outgoing', + type: 'keyword', + }, + 'gsuite.admin.email_dump.include_deleted': { + category: 'gsuite', + description: 'Indicates if deleted emails are included in the export.', + name: 'gsuite.admin.email_dump.include_deleted', + type: 'boolean', + }, + 'gsuite.admin.email_dump.package_content': { + category: 'gsuite', + description: 'The contents of the mailbox package.', + name: 'gsuite.admin.email_dump.package_content', + type: 'keyword', + }, + 'gsuite.admin.email_dump.query': { + category: 'gsuite', + description: 'The search query used for the dump.', + name: 'gsuite.admin.email_dump.query', + type: 'keyword', + }, + 'gsuite.admin.request.id': { + category: 'gsuite', + description: 'The request ID.', + name: 'gsuite.admin.request.id', + type: 'keyword', + }, + 'gsuite.admin.mobile.action.id': { + category: 'gsuite', + description: "The mobile device action's ID.", + name: 'gsuite.admin.mobile.action.id', + type: 'keyword', + }, + 'gsuite.admin.mobile.action.type': { + category: 'gsuite', + description: + "The mobile device action's type. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-mobile-settings ", + name: 'gsuite.admin.mobile.action.type', + type: 'keyword', + }, + 'gsuite.admin.mobile.certificate.name': { + category: 'gsuite', + description: 'The mobile certificate common name.', + name: 'gsuite.admin.mobile.certificate.name', + type: 'keyword', + }, + 'gsuite.admin.mobile.company_owned_devices': { + category: 'gsuite', + description: 'The number of devices a company owns.', + name: 'gsuite.admin.mobile.company_owned_devices', + type: 'long', + }, + 'gsuite.admin.distribution.entity.name': { + category: 'gsuite', + description: + 'The distribution entity value, which can be a group name or an org-unit name. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-mobile-settings ', + name: 'gsuite.admin.distribution.entity.name', + type: 'keyword', + }, + 'gsuite.admin.distribution.entity.type': { + category: 'gsuite', + description: + 'The distribution entity type, which can be a group or an org-unit. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/admin-mobile-settings ', + name: 'gsuite.admin.distribution.entity.type', + type: 'keyword', + }, + 'gsuite.drive.billable': { + category: 'gsuite', + description: 'Whether this activity is billable.', + name: 'gsuite.drive.billable', + type: 'boolean', + }, + 'gsuite.drive.source_folder_id': { + category: 'gsuite', + name: 'gsuite.drive.source_folder_id', + type: 'keyword', + }, + 'gsuite.drive.source_folder_title': { + category: 'gsuite', + name: 'gsuite.drive.source_folder_title', + type: 'keyword', + }, + 'gsuite.drive.destination_folder_id': { + category: 'gsuite', + name: 'gsuite.drive.destination_folder_id', + type: 'keyword', + }, + 'gsuite.drive.destination_folder_title': { + category: 'gsuite', + name: 'gsuite.drive.destination_folder_title', + type: 'keyword', + }, + 'gsuite.drive.file.id': { + category: 'gsuite', + name: 'gsuite.drive.file.id', + type: 'keyword', + }, + 'gsuite.drive.file.type': { + category: 'gsuite', + description: + 'Document Drive type. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/drive ', + name: 'gsuite.drive.file.type', + type: 'keyword', + }, + 'gsuite.drive.originating_app_id': { + category: 'gsuite', + description: 'The Google Cloud Project ID of the application that performed the action. ', + name: 'gsuite.drive.originating_app_id', + type: 'keyword', + }, + 'gsuite.drive.file.owner.email': { + category: 'gsuite', + name: 'gsuite.drive.file.owner.email', + type: 'keyword', + }, + 'gsuite.drive.file.owner.is_shared_drive': { + category: 'gsuite', + description: 'Boolean flag denoting whether owner is a shared drive. ', + name: 'gsuite.drive.file.owner.is_shared_drive', + type: 'boolean', + }, + 'gsuite.drive.primary_event': { + category: 'gsuite', + description: + 'Whether this is a primary event. A single user action in Drive may generate several events. ', + name: 'gsuite.drive.primary_event', + type: 'boolean', + }, + 'gsuite.drive.shared_drive_id': { + category: 'gsuite', + description: + 'The unique identifier of the Team Drive. Only populated for for events relating to a Team Drive or item contained inside a Team Drive. ', + name: 'gsuite.drive.shared_drive_id', + type: 'keyword', + }, + 'gsuite.drive.visibility': { + category: 'gsuite', + description: + 'Visibility of target file. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/drive ', + name: 'gsuite.drive.visibility', + type: 'keyword', + }, + 'gsuite.drive.new_value': { + category: 'gsuite', + description: + 'When a setting or property of the file changes, the new value for it will appear here. ', + name: 'gsuite.drive.new_value', + type: 'keyword', + }, + 'gsuite.drive.old_value': { + category: 'gsuite', + description: + 'When a setting or property of the file changes, the old value for it will appear here. ', + name: 'gsuite.drive.old_value', + type: 'keyword', + }, + 'gsuite.drive.sheets_import_range_recipient_doc': { + category: 'gsuite', + description: 'Doc ID of the recipient of a sheets import range.', + name: 'gsuite.drive.sheets_import_range_recipient_doc', + type: 'keyword', + }, + 'gsuite.drive.old_visibility': { + category: 'gsuite', + description: 'When visibility changes, this holds the old value. ', + name: 'gsuite.drive.old_visibility', + type: 'keyword', + }, + 'gsuite.drive.visibility_change': { + category: 'gsuite', + description: 'When visibility changes, this holds the new overall visibility of the file. ', + name: 'gsuite.drive.visibility_change', + type: 'keyword', + }, + 'gsuite.drive.target_domain': { + category: 'gsuite', + description: + 'The domain for which the acccess scope was changed. This can also be the alias all to indicate the access scope was changed for all domains that have visibility for this document. ', + name: 'gsuite.drive.target_domain', + type: 'keyword', + }, + 'gsuite.drive.added_role': { + category: 'gsuite', + description: + 'Added membership role of a user/group in a Team Drive. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/drive ', + name: 'gsuite.drive.added_role', + type: 'keyword', + }, + 'gsuite.drive.membership_change_type': { + category: 'gsuite', + description: + 'Type of change in Team Drive membership of a user/group. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/drive ', + name: 'gsuite.drive.membership_change_type', + type: 'keyword', + }, + 'gsuite.drive.shared_drive_settings_change_type': { + category: 'gsuite', + description: + 'Type of change in Team Drive settings. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/drive ', + name: 'gsuite.drive.shared_drive_settings_change_type', + type: 'keyword', + }, + 'gsuite.drive.removed_role': { + category: 'gsuite', + description: + 'Removed membership role of a user/group in a Team Drive. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/drive ', + name: 'gsuite.drive.removed_role', + type: 'keyword', + }, + 'gsuite.drive.target': { + category: 'gsuite', + description: 'Target user or group.', + name: 'gsuite.drive.target', + type: 'keyword', + }, + 'gsuite.groups.acl_permission': { + category: 'gsuite', + description: + 'Group permission setting updated. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/groups ', + name: 'gsuite.groups.acl_permission', + type: 'keyword', + }, + 'gsuite.groups.email': { + category: 'gsuite', + description: 'Group email. ', + name: 'gsuite.groups.email', + type: 'keyword', + }, + 'gsuite.groups.member.email': { + category: 'gsuite', + description: 'Member email. ', + name: 'gsuite.groups.member.email', + type: 'keyword', + }, + 'gsuite.groups.member.role': { + category: 'gsuite', + description: + 'Member role. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/groups ', + name: 'gsuite.groups.member.role', + type: 'keyword', + }, + 'gsuite.groups.setting': { + category: 'gsuite', + description: + 'Group setting updated. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/groups ', + name: 'gsuite.groups.setting', + type: 'keyword', + }, + 'gsuite.groups.new_value': { + category: 'gsuite', + description: + 'New value(s) of the group setting. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/groups ', + name: 'gsuite.groups.new_value', + type: 'keyword', + }, + 'gsuite.groups.old_value': { + category: 'gsuite', + description: + 'Old value(s) of the group setting. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/groups', + name: 'gsuite.groups.old_value', + type: 'keyword', + }, + 'gsuite.groups.value': { + category: 'gsuite', + description: + 'Value of the group setting. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/groups ', + name: 'gsuite.groups.value', + type: 'keyword', + }, + 'gsuite.groups.message.id': { + category: 'gsuite', + description: 'SMTP message Id of an email message. Present for moderation events. ', + name: 'gsuite.groups.message.id', + type: 'keyword', + }, + 'gsuite.groups.message.moderation_action': { + category: 'gsuite', + description: 'Message moderation action. Possible values are `approved` and `rejected`. ', + name: 'gsuite.groups.message.moderation_action', + type: 'keyword', + }, + 'gsuite.groups.status': { + category: 'gsuite', + description: + 'A status describing the output of an operation. Possible values are `failed` and `succeeded`. ', + name: 'gsuite.groups.status', + type: 'keyword', + }, + 'gsuite.login.affected_email_address': { + category: 'gsuite', + name: 'gsuite.login.affected_email_address', + type: 'keyword', + }, + 'gsuite.login.challenge_method': { + category: 'gsuite', + description: + 'Login challenge method. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/login. ', + name: 'gsuite.login.challenge_method', + type: 'keyword', + }, + 'gsuite.login.failure_type': { + category: 'gsuite', + description: + 'Login failure type. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/login. ', + name: 'gsuite.login.failure_type', + type: 'keyword', + }, + 'gsuite.login.type': { + category: 'gsuite', + description: + 'Login credentials type. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/login. ', + name: 'gsuite.login.type', + type: 'keyword', + }, + 'gsuite.login.is_second_factor': { + category: 'gsuite', + name: 'gsuite.login.is_second_factor', + type: 'boolean', + }, + 'gsuite.login.is_suspicious': { + category: 'gsuite', + name: 'gsuite.login.is_suspicious', + type: 'boolean', + }, + 'gsuite.saml.application_name': { + category: 'gsuite', + description: 'Saml SP application name. ', + name: 'gsuite.saml.application_name', + type: 'keyword', + }, + 'gsuite.saml.failure_type': { + category: 'gsuite', + description: + 'Login failure type. For a list of possible values refer to https://developers.google.com/admin-sdk/reports/v1/appendix/activity/saml. ', + name: 'gsuite.saml.failure_type', + type: 'keyword', + }, + 'gsuite.saml.initiated_by': { + category: 'gsuite', + description: 'Requester of SAML authentication. ', + name: 'gsuite.saml.initiated_by', + type: 'keyword', + }, + 'gsuite.saml.orgunit_path': { + category: 'gsuite', + description: 'User orgunit. ', + name: 'gsuite.saml.orgunit_path', + type: 'keyword', + }, + 'gsuite.saml.status_code': { + category: 'gsuite', + description: 'SAML status code. ', + name: 'gsuite.saml.status_code', + type: 'long', + }, + 'gsuite.saml.second_level_status_code': { + category: 'gsuite', + description: 'SAML second level status code. ', + name: 'gsuite.saml.second_level_status_code', + type: 'long', + }, + 'ibmmq.errorlog.installation': { + category: 'ibmmq', + description: + 'This is the installation name which can be given at installation time. Each installation of IBM MQ on UNIX, Linux, and Windows, has a unique identifier known as an installation name. The installation name is used to associate things such as queue managers and configuration files with an installation. ', + name: 'ibmmq.errorlog.installation', + type: 'keyword', + }, + 'ibmmq.errorlog.qmgr': { + category: 'ibmmq', + description: + 'Name of the queue manager. Queue managers provide queuing services to applications, and manages the queues that belong to them. ', + name: 'ibmmq.errorlog.qmgr', + type: 'keyword', + }, + 'ibmmq.errorlog.arithinsert': { + category: 'ibmmq', + description: 'Changing content based on error.id', + name: 'ibmmq.errorlog.arithinsert', + type: 'keyword', + }, + 'ibmmq.errorlog.commentinsert': { + category: 'ibmmq', + description: 'Changing content based on error.id', + name: 'ibmmq.errorlog.commentinsert', + type: 'keyword', + }, + 'ibmmq.errorlog.errordescription': { + category: 'ibmmq', + description: 'Please add description', + example: 'Please add example', + name: 'ibmmq.errorlog.errordescription', + type: 'text', + }, + 'ibmmq.errorlog.explanation': { + category: 'ibmmq', + description: 'Explaines the error in more detail', + name: 'ibmmq.errorlog.explanation', + type: 'keyword', + }, + 'ibmmq.errorlog.action': { + category: 'ibmmq', + description: 'Defines what to do when the error occurs', + name: 'ibmmq.errorlog.action', + type: 'keyword', + }, + 'ibmmq.errorlog.code': { + category: 'ibmmq', + description: 'Error code.', + name: 'ibmmq.errorlog.code', + type: 'keyword', + }, + 'iptables.ether_type': { + category: 'iptables', + description: 'Value of the ethernet type field identifying the network layer protocol. ', + name: 'iptables.ether_type', + type: 'long', + }, + 'iptables.flow_label': { + category: 'iptables', + description: 'IPv6 flow label. ', + name: 'iptables.flow_label', + type: 'integer', + }, + 'iptables.fragment_flags': { + category: 'iptables', + description: 'IP fragment flags. A combination of CE, DF and MF. ', + name: 'iptables.fragment_flags', + type: 'keyword', + }, + 'iptables.fragment_offset': { + category: 'iptables', + description: 'Offset of the current IP fragment. ', + name: 'iptables.fragment_offset', + type: 'long', + }, + 'iptables.icmp.code': { + category: 'iptables', + description: 'ICMP code. ', + name: 'iptables.icmp.code', + type: 'long', + }, + 'iptables.icmp.id': { + category: 'iptables', + description: 'ICMP ID. ', + name: 'iptables.icmp.id', + type: 'long', + }, + 'iptables.icmp.parameter': { + category: 'iptables', + description: 'ICMP parameter. ', + name: 'iptables.icmp.parameter', + type: 'long', + }, + 'iptables.icmp.redirect': { + category: 'iptables', + description: 'ICMP redirect address. ', + name: 'iptables.icmp.redirect', + type: 'ip', + }, + 'iptables.icmp.seq': { + category: 'iptables', + description: 'ICMP sequence number. ', + name: 'iptables.icmp.seq', + type: 'long', + }, + 'iptables.icmp.type': { + category: 'iptables', + description: 'ICMP type. ', + name: 'iptables.icmp.type', + type: 'long', + }, + 'iptables.id': { + category: 'iptables', + description: 'Packet identifier. ', + name: 'iptables.id', + type: 'long', + }, + 'iptables.incomplete_bytes': { + category: 'iptables', + description: 'Number of incomplete bytes. ', + name: 'iptables.incomplete_bytes', + type: 'long', + }, + 'iptables.input_device': { + category: 'iptables', + description: 'Device that received the packet. ', + name: 'iptables.input_device', + type: 'keyword', + }, + 'iptables.precedence_bits': { + category: 'iptables', + description: 'IP precedence bits. ', + name: 'iptables.precedence_bits', + type: 'short', + }, + 'iptables.tos': { + category: 'iptables', + description: 'IP Type of Service field. ', + name: 'iptables.tos', + type: 'long', + }, + 'iptables.length': { + category: 'iptables', + description: 'Packet length. ', + name: 'iptables.length', + type: 'long', + }, + 'iptables.output_device': { + category: 'iptables', + description: 'Device that output the packet. ', + name: 'iptables.output_device', + type: 'keyword', + }, + 'iptables.tcp.flags': { + category: 'iptables', + description: 'TCP flags. ', + name: 'iptables.tcp.flags', + type: 'keyword', + }, + 'iptables.tcp.reserved_bits': { + category: 'iptables', + description: 'TCP reserved bits. ', + name: 'iptables.tcp.reserved_bits', + type: 'short', + }, + 'iptables.tcp.seq': { + category: 'iptables', + description: 'TCP sequence number. ', + name: 'iptables.tcp.seq', + type: 'long', + }, + 'iptables.tcp.ack': { + category: 'iptables', + description: 'TCP Acknowledgment number. ', + name: 'iptables.tcp.ack', + type: 'long', + }, + 'iptables.tcp.window': { + category: 'iptables', + description: 'Advertised TCP window size. ', + name: 'iptables.tcp.window', + type: 'long', + }, + 'iptables.ttl': { + category: 'iptables', + description: 'Time To Live field. ', + name: 'iptables.ttl', + type: 'integer', + }, + 'iptables.udp.length': { + category: 'iptables', + description: 'Length of the UDP header and payload. ', + name: 'iptables.udp.length', + type: 'long', + }, + 'iptables.ubiquiti.input_zone': { + category: 'iptables', + description: 'Input zone. ', + name: 'iptables.ubiquiti.input_zone', + type: 'keyword', + }, + 'iptables.ubiquiti.output_zone': { + category: 'iptables', + description: 'Output zone. ', + name: 'iptables.ubiquiti.output_zone', + type: 'keyword', + }, + 'iptables.ubiquiti.rule_number': { + category: 'iptables', + description: 'The rule number within the rule set.', + name: 'iptables.ubiquiti.rule_number', + type: 'keyword', + }, + 'iptables.ubiquiti.rule_set': { + category: 'iptables', + description: 'The rule set name.', + name: 'iptables.ubiquiti.rule_set', + type: 'keyword', + }, + 'microsoft.defender_atp.lastUpdateTime': { + category: 'microsoft', + description: 'The date and time (in UTC) the alert was last updated. ', + name: 'microsoft.defender_atp.lastUpdateTime', + type: 'date', + }, + 'microsoft.defender_atp.resolvedTime': { + category: 'microsoft', + description: "The date and time in which the status of the alert was changed to 'Resolved'. ", + name: 'microsoft.defender_atp.resolvedTime', + type: 'date', + }, + 'microsoft.defender_atp.incidentId': { + category: 'microsoft', + description: 'The Incident ID of the Alert. ', + name: 'microsoft.defender_atp.incidentId', + type: 'keyword', + }, + 'microsoft.defender_atp.investigationId': { + category: 'microsoft', + description: 'The Investigation ID related to the Alert. ', + name: 'microsoft.defender_atp.investigationId', + type: 'keyword', + }, + 'microsoft.defender_atp.investigationState': { + category: 'microsoft', + description: 'The current state of the Investigation. ', + name: 'microsoft.defender_atp.investigationState', + type: 'keyword', + }, + 'microsoft.defender_atp.assignedTo': { + category: 'microsoft', + description: 'Owner of the alert. ', + name: 'microsoft.defender_atp.assignedTo', + type: 'keyword', + }, + 'microsoft.defender_atp.status': { + category: 'microsoft', + description: + "Specifies the current status of the alert. Possible values are: 'Unknown', 'New', 'InProgress' and 'Resolved'. ", + name: 'microsoft.defender_atp.status', + type: 'keyword', + }, + 'microsoft.defender_atp.classification': { + category: 'microsoft', + description: + "Specification of the alert. Possible values are: 'Unknown', 'FalsePositive', 'TruePositive'. ", + name: 'microsoft.defender_atp.classification', + type: 'keyword', + }, + 'microsoft.defender_atp.determination': { + category: 'microsoft', + description: + "Specifies the determination of the alert. Possible values are: 'NotAvailable', 'Apt', 'Malware', 'SecurityPersonnel', 'SecurityTesting', 'UnwantedSoftware', 'Other'. ", + name: 'microsoft.defender_atp.determination', + type: 'keyword', + }, + 'microsoft.defender_atp.threatFamilyName': { + category: 'microsoft', + description: 'Threat family. ', + name: 'microsoft.defender_atp.threatFamilyName', + type: 'keyword', + }, + 'microsoft.defender_atp.rbacGroupName': { + category: 'microsoft', + description: 'User group related to the alert ', + name: 'microsoft.defender_atp.rbacGroupName', + type: 'keyword', + }, + 'microsoft.defender_atp.evidence.domainName': { + category: 'microsoft', + description: 'Domain name related to the alert ', + name: 'microsoft.defender_atp.evidence.domainName', + type: 'keyword', + }, + 'microsoft.defender_atp.evidence.ipAddress': { + category: 'microsoft', + description: 'IP address involved in the alert ', + name: 'microsoft.defender_atp.evidence.ipAddress', + type: 'ip', + }, + 'microsoft.defender_atp.evidence.aadUserId': { + category: 'microsoft', + description: 'ID of the user involved in the alert ', + name: 'microsoft.defender_atp.evidence.aadUserId', + type: 'keyword', + }, + 'microsoft.defender_atp.evidence.accountName': { + category: 'microsoft', + description: 'Username of the user involved in the alert ', + name: 'microsoft.defender_atp.evidence.accountName', + type: 'keyword', + }, + 'microsoft.defender_atp.evidence.entityType': { + category: 'microsoft', + description: 'The type of evidence ', + name: 'microsoft.defender_atp.evidence.entityType', + type: 'keyword', + }, + 'microsoft.defender_atp.evidence.userPrincipalName': { + category: 'microsoft', + description: 'Principal name of the user involved in the alert ', + name: 'microsoft.defender_atp.evidence.userPrincipalName', + type: 'keyword', + }, + 'misp.attack_pattern.id': { + category: 'misp', + description: 'Identifier of the threat indicator. ', + name: 'misp.attack_pattern.id', + type: 'keyword', + }, + 'misp.attack_pattern.name': { + category: 'misp', + description: 'Name of the attack pattern. ', + name: 'misp.attack_pattern.name', + type: 'keyword', + }, + 'misp.attack_pattern.description': { + category: 'misp', + description: 'Description of the attack pattern. ', + name: 'misp.attack_pattern.description', + type: 'text', + }, + 'misp.attack_pattern.kill_chain_phases': { + category: 'misp', + description: 'The kill chain phase(s) to which this attack pattern corresponds. ', + name: 'misp.attack_pattern.kill_chain_phases', + type: 'keyword', + }, + 'misp.campaign.id': { + category: 'misp', + description: 'Identifier of the campaign. ', + name: 'misp.campaign.id', + type: 'keyword', + }, + 'misp.campaign.name': { + category: 'misp', + description: 'Name of the campaign. ', + name: 'misp.campaign.name', + type: 'keyword', + }, + 'misp.campaign.description': { + category: 'misp', + description: 'Description of the campaign. ', + name: 'misp.campaign.description', + type: 'text', + }, + 'misp.campaign.aliases': { + category: 'misp', + description: 'Alternative names used to identify this campaign. ', + name: 'misp.campaign.aliases', + type: 'text', + }, + 'misp.campaign.first_seen': { + category: 'misp', + description: 'The time that this Campaign was first seen, in RFC3339 format. ', + name: 'misp.campaign.first_seen', + type: 'date', + }, + 'misp.campaign.last_seen': { + category: 'misp', + description: 'The time that this Campaign was last seen, in RFC3339 format. ', + name: 'misp.campaign.last_seen', + type: 'date', + }, + 'misp.campaign.objective': { + category: 'misp', + description: + "This field defines the Campaign's primary goal, objective, desired outcome, or intended effect. ", + name: 'misp.campaign.objective', + type: 'keyword', + }, + 'misp.course_of_action.id': { + category: 'misp', + description: 'Identifier of the Course of Action. ', + name: 'misp.course_of_action.id', + type: 'keyword', + }, + 'misp.course_of_action.name': { + category: 'misp', + description: 'The name used to identify the Course of Action. ', + name: 'misp.course_of_action.name', + type: 'keyword', + }, + 'misp.course_of_action.description': { + category: 'misp', + description: 'Description of the Course of Action. ', + name: 'misp.course_of_action.description', + type: 'text', + }, + 'misp.identity.id': { + category: 'misp', + description: 'Identifier of the Identity. ', + name: 'misp.identity.id', + type: 'keyword', + }, + 'misp.identity.name': { + category: 'misp', + description: 'The name used to identify the Identity. ', + name: 'misp.identity.name', + type: 'keyword', + }, + 'misp.identity.description': { + category: 'misp', + description: 'Description of the Identity. ', + name: 'misp.identity.description', + type: 'text', + }, + 'misp.identity.identity_class': { + category: 'misp', + description: + 'The type of entity that this Identity describes, e.g., an individual or organization. Open Vocab - identity-class-ov ', + name: 'misp.identity.identity_class', + type: 'keyword', + }, + 'misp.identity.labels': { + category: 'misp', + description: 'The list of roles that this Identity performs. ', + example: 'CEO\n', + name: 'misp.identity.labels', + type: 'keyword', + }, + 'misp.identity.sectors': { + category: 'misp', + description: + 'The list of sectors that this Identity belongs to. Open Vocab - industry-sector-ov ', + name: 'misp.identity.sectors', + type: 'keyword', + }, + 'misp.identity.contact_information': { + category: 'misp', + description: 'The contact information (e-mail, phone number, etc.) for this Identity. ', + name: 'misp.identity.contact_information', + type: 'text', + }, + 'misp.intrusion_set.id': { + category: 'misp', + description: 'Identifier of the Intrusion Set. ', + name: 'misp.intrusion_set.id', + type: 'keyword', + }, + 'misp.intrusion_set.name': { + category: 'misp', + description: 'The name used to identify the Intrusion Set. ', + name: 'misp.intrusion_set.name', + type: 'keyword', + }, + 'misp.intrusion_set.description': { + category: 'misp', + description: 'Description of the Intrusion Set. ', + name: 'misp.intrusion_set.description', + type: 'text', + }, + 'misp.intrusion_set.aliases': { + category: 'misp', + description: 'Alternative names used to identify the Intrusion Set. ', + name: 'misp.intrusion_set.aliases', + type: 'text', + }, + 'misp.intrusion_set.first_seen': { + category: 'misp', + description: 'The time that this Intrusion Set was first seen, in RFC3339 format. ', + name: 'misp.intrusion_set.first_seen', + type: 'date', + }, + 'misp.intrusion_set.last_seen': { + category: 'misp', + description: 'The time that this Intrusion Set was last seen, in RFC3339 format. ', + name: 'misp.intrusion_set.last_seen', + type: 'date', + }, + 'misp.intrusion_set.goals': { + category: 'misp', + description: 'The high level goals of this Intrusion Set, namely, what are they trying to do. ', + name: 'misp.intrusion_set.goals', + type: 'text', + }, + 'misp.intrusion_set.resource_level': { + category: 'misp', + description: + 'This defines the organizational level at which this Intrusion Set typically works. Open Vocab - attack-resource-level-ov ', + name: 'misp.intrusion_set.resource_level', + type: 'text', + }, + 'misp.intrusion_set.primary_motivation': { + category: 'misp', + description: + 'The primary reason, motivation, or purpose behind this Intrusion Set. Open Vocab - attack-motivation-ov ', + name: 'misp.intrusion_set.primary_motivation', + type: 'text', + }, + 'misp.intrusion_set.secondary_motivations': { + category: 'misp', + description: + 'The secondary reasons, motivations, or purposes behind this Intrusion Set. Open Vocab - attack-motivation-ov ', + name: 'misp.intrusion_set.secondary_motivations', + type: 'text', + }, + 'misp.malware.id': { + category: 'misp', + description: 'Identifier of the Malware. ', + name: 'misp.malware.id', + type: 'keyword', + }, + 'misp.malware.name': { + category: 'misp', + description: 'The name used to identify the Malware. ', + name: 'misp.malware.name', + type: 'keyword', + }, + 'misp.malware.description': { + category: 'misp', + description: 'Description of the Malware. ', + name: 'misp.malware.description', + type: 'text', + }, + 'misp.malware.labels': { + category: 'misp', + description: + 'The type of malware being described. Open Vocab - malware-label-ov. adware,backdoor,bot,ddos,dropper,exploit-kit,keylogger,ransomware, remote-access-trojan,resource-exploitation,rogue-security-software,rootkit, screen-capture,spyware,trojan,virus,worm ', + name: 'misp.malware.labels', + type: 'keyword', + }, + 'misp.malware.kill_chain_phases': { + category: 'misp', + description: 'The list of kill chain phases for which this Malware instance can be used. ', + name: 'misp.malware.kill_chain_phases', + type: 'keyword', + format: 'string', + }, + 'misp.note.id': { + category: 'misp', + description: 'Identifier of the Note. ', + name: 'misp.note.id', + type: 'keyword', + }, + 'misp.note.summary': { + category: 'misp', + description: 'A brief description used as a summary of the Note. ', + name: 'misp.note.summary', + type: 'keyword', + }, + 'misp.note.description': { + category: 'misp', + description: 'The content of the Note. ', + name: 'misp.note.description', + type: 'text', + }, + 'misp.note.authors': { + category: 'misp', + description: 'The name of the author(s) of this Note. ', + name: 'misp.note.authors', + type: 'keyword', + }, + 'misp.note.object_refs': { + category: 'misp', + description: 'The STIX Objects (SDOs and SROs) that the note is being applied to. ', + name: 'misp.note.object_refs', + type: 'keyword', + }, + 'misp.threat_indicator.labels': { + category: 'misp', + description: 'list of type open-vocab that specifies the type of indicator. ', + example: 'Domain Watchlist\n', + name: 'misp.threat_indicator.labels', + type: 'keyword', + }, + 'misp.threat_indicator.id': { + category: 'misp', + description: 'Identifier of the threat indicator. ', + name: 'misp.threat_indicator.id', + type: 'keyword', + }, + 'misp.threat_indicator.version': { + category: 'misp', + description: 'Version of the threat indicator. ', + name: 'misp.threat_indicator.version', + type: 'keyword', + }, + 'misp.threat_indicator.type': { + category: 'misp', + description: 'Type of the threat indicator. ', + name: 'misp.threat_indicator.type', + type: 'keyword', + }, + 'misp.threat_indicator.description': { + category: 'misp', + description: 'Description of the threat indicator. ', + name: 'misp.threat_indicator.description', + type: 'text', + }, + 'misp.threat_indicator.feed': { + category: 'misp', + description: 'Name of the threat feed. ', + name: 'misp.threat_indicator.feed', + type: 'text', + }, + 'misp.threat_indicator.valid_from': { + category: 'misp', + description: + 'The time from which this Indicator should be considered valuable intelligence, in RFC3339 format. ', + name: 'misp.threat_indicator.valid_from', + type: 'date', + }, + 'misp.threat_indicator.valid_until': { + category: 'misp', + description: + 'The time at which this Indicator should no longer be considered valuable intelligence. If the valid_until property is omitted, then there is no constraint on the latest time for which the indicator should be used, in RFC3339 format. ', + name: 'misp.threat_indicator.valid_until', + type: 'date', + }, + 'misp.threat_indicator.severity': { + category: 'misp', + description: 'Threat severity to which this indicator corresponds. ', + example: 'high', + name: 'misp.threat_indicator.severity', + type: 'keyword', + format: 'string', + }, + 'misp.threat_indicator.confidence': { + category: 'misp', + description: 'Confidence level to which this indicator corresponds. ', + example: 'high', + name: 'misp.threat_indicator.confidence', + type: 'keyword', + }, + 'misp.threat_indicator.kill_chain_phases': { + category: 'misp', + description: 'The kill chain phase(s) to which this indicator corresponds. ', + name: 'misp.threat_indicator.kill_chain_phases', + type: 'keyword', + format: 'string', + }, + 'misp.threat_indicator.mitre_tactic': { + category: 'misp', + description: 'MITRE tactics to which this indicator corresponds. ', + example: 'Initial Access', + name: 'misp.threat_indicator.mitre_tactic', + type: 'keyword', + format: 'string', + }, + 'misp.threat_indicator.mitre_technique': { + category: 'misp', + description: 'MITRE techniques to which this indicator corresponds. ', + example: 'Drive-by Compromise', + name: 'misp.threat_indicator.mitre_technique', + type: 'keyword', + format: 'string', + }, + 'misp.threat_indicator.attack_pattern': { + category: 'misp', + description: + 'The attack_pattern for this indicator is a STIX Pattern as specified in STIX Version 2.0 Part 5 - STIX Patterning. ', + example: "[destination:ip = '91.219.29.188/32']\n", + name: 'misp.threat_indicator.attack_pattern', + type: 'keyword', + }, + 'misp.threat_indicator.attack_pattern_kql': { + category: 'misp', + description: + 'The attack_pattern for this indicator is KQL query that matches the attack_pattern specified in the STIX Pattern format. ', + example: 'destination.ip: "91.219.29.188/32"\n', + name: 'misp.threat_indicator.attack_pattern_kql', + type: 'keyword', + }, + 'misp.threat_indicator.negate': { + category: 'misp', + description: 'When set to true, it specifies the absence of the attack_pattern. ', + name: 'misp.threat_indicator.negate', + type: 'boolean', + }, + 'misp.threat_indicator.intrusion_set': { + category: 'misp', + description: 'Name of the intrusion set if known. ', + name: 'misp.threat_indicator.intrusion_set', + type: 'keyword', + }, + 'misp.threat_indicator.campaign': { + category: 'misp', + description: 'Name of the attack campaign if known. ', + name: 'misp.threat_indicator.campaign', + type: 'keyword', + }, + 'misp.threat_indicator.threat_actor': { + category: 'misp', + description: 'Name of the threat actor if known. ', + name: 'misp.threat_indicator.threat_actor', + type: 'keyword', + }, + 'misp.observed_data.id': { + category: 'misp', + description: 'Identifier of the Observed Data. ', + name: 'misp.observed_data.id', + type: 'keyword', + }, + 'misp.observed_data.first_observed': { + category: 'misp', + description: 'The beginning of the time window that the data was observed, in RFC3339 format. ', + name: 'misp.observed_data.first_observed', + type: 'date', + }, + 'misp.observed_data.last_observed': { + category: 'misp', + description: 'The end of the time window that the data was observed, in RFC3339 format. ', + name: 'misp.observed_data.last_observed', + type: 'date', + }, + 'misp.observed_data.number_observed': { + category: 'misp', + description: + 'The number of times the data represented in the objects property was observed. This MUST be an integer between 1 and 999,999,999 inclusive. ', + name: 'misp.observed_data.number_observed', + type: 'integer', + }, + 'misp.observed_data.objects': { + category: 'misp', + description: + 'A dictionary of Cyber Observable Objects that describes the single fact that was observed. ', + name: 'misp.observed_data.objects', + type: 'keyword', + }, + 'misp.report.id': { + category: 'misp', + description: 'Identifier of the Report. ', + name: 'misp.report.id', + type: 'keyword', + }, + 'misp.report.labels': { + category: 'misp', + description: + 'This field is an Open Vocabulary that specifies the primary subject of this report. Open Vocab - report-label-ov. threat-report,attack-pattern,campaign,identity,indicator,malware,observed-data,threat-actor,tool,vulnerability ', + name: 'misp.report.labels', + type: 'keyword', + }, + 'misp.report.name': { + category: 'misp', + description: 'The name used to identify the Report. ', + name: 'misp.report.name', + type: 'keyword', + }, + 'misp.report.description': { + category: 'misp', + description: 'A description that provides more details and context about Report. ', + name: 'misp.report.description', + type: 'text', + }, + 'misp.report.published': { + category: 'misp', + description: + 'The date that this report object was officially published by the creator of this report, in RFC3339 format. ', + name: 'misp.report.published', + type: 'date', + }, + 'misp.report.object_refs': { + category: 'misp', + description: 'Specifies the STIX Objects that are referred to by this Report. ', + name: 'misp.report.object_refs', + type: 'text', + }, + 'misp.threat_actor.id': { + category: 'misp', + description: 'Identifier of the Threat Actor. ', + name: 'misp.threat_actor.id', + type: 'keyword', + }, + 'misp.threat_actor.labels': { + category: 'misp', + description: + 'This field specifies the type of threat actor. Open Vocab - threat-actor-label-ov. activist,competitor,crime-syndicate,criminal,hacker,insider-accidental,insider-disgruntled,nation-state,sensationalist,spy,terrorist ', + name: 'misp.threat_actor.labels', + type: 'keyword', + }, + 'misp.threat_actor.name': { + category: 'misp', + description: 'The name used to identify this Threat Actor or Threat Actor group. ', + name: 'misp.threat_actor.name', + type: 'keyword', + }, + 'misp.threat_actor.description': { + category: 'misp', + description: 'A description that provides more details and context about the Threat Actor. ', + name: 'misp.threat_actor.description', + type: 'text', + }, + 'misp.threat_actor.aliases': { + category: 'misp', + description: 'A list of other names that this Threat Actor is believed to use. ', + name: 'misp.threat_actor.aliases', + type: 'text', + }, + 'misp.threat_actor.roles': { + category: 'misp', + description: + 'This is a list of roles the Threat Actor plays. Open Vocab - threat-actor-role-ov. agent,director,independent,sponsor,infrastructure-operator,infrastructure-architect,malware-author ', + name: 'misp.threat_actor.roles', + type: 'text', + }, + 'misp.threat_actor.goals': { + category: 'misp', + description: 'The high level goals of this Threat Actor, namely, what are they trying to do. ', + name: 'misp.threat_actor.goals', + type: 'text', + }, + 'misp.threat_actor.sophistication': { + category: 'misp', + description: + 'The skill, specific knowledge, special training, or expertise a Threat Actor must have to perform the attack. Open Vocab - threat-actor-sophistication-ov. none,minimal,intermediate,advanced,strategic,expert,innovator ', + name: 'misp.threat_actor.sophistication', + type: 'text', + }, + 'misp.threat_actor.resource_level': { + category: 'misp', + description: + 'This defines the organizational level at which this Threat Actor typically works. Open Vocab - attack-resource-level-ov. individual,club,contest,team,organization,government ', + name: 'misp.threat_actor.resource_level', + type: 'text', + }, + 'misp.threat_actor.primary_motivation': { + category: 'misp', + description: + 'The primary reason, motivation, or purpose behind this Threat Actor. Open Vocab - attack-motivation-ov. accidental,coercion,dominance,ideology,notoriety,organizational-gain,personal-gain,personal-satisfaction,revenge,unpredictable ', + name: 'misp.threat_actor.primary_motivation', + type: 'text', + }, + 'misp.threat_actor.secondary_motivations': { + category: 'misp', + description: + 'The secondary reasons, motivations, or purposes behind this Threat Actor. Open Vocab - attack-motivation-ov. accidental,coercion,dominance,ideology,notoriety,organizational-gain,personal-gain,personal-satisfaction,revenge,unpredictable ', + name: 'misp.threat_actor.secondary_motivations', + type: 'text', + }, + 'misp.threat_actor.personal_motivations': { + category: 'misp', + description: + 'The personal reasons, motivations, or purposes of the Threat Actor regardless of organizational goals. Open Vocab - attack-motivation-ov. accidental,coercion,dominance,ideology,notoriety,organizational-gain,personal-gain,personal-satisfaction,revenge,unpredictable ', + name: 'misp.threat_actor.personal_motivations', + type: 'text', + }, + 'misp.tool.id': { + category: 'misp', + description: 'Identifier of the Tool. ', + name: 'misp.tool.id', + type: 'keyword', + }, + 'misp.tool.labels': { + category: 'misp', + description: + 'The kind(s) of tool(s) being described. Open Vocab - tool-label-ov. denial-of-service,exploitation,information-gathering,network-capture,credential-exploitation,remote-access,vulnerability-scanning ', + name: 'misp.tool.labels', + type: 'keyword', + }, + 'misp.tool.name': { + category: 'misp', + description: 'The name used to identify the Tool. ', + name: 'misp.tool.name', + type: 'keyword', + }, + 'misp.tool.description': { + category: 'misp', + description: 'A description that provides more details and context about the Tool. ', + name: 'misp.tool.description', + type: 'text', + }, + 'misp.tool.tool_version': { + category: 'misp', + description: 'The version identifier associated with the Tool. ', + name: 'misp.tool.tool_version', + type: 'keyword', + }, + 'misp.tool.kill_chain_phases': { + category: 'misp', + description: 'The list of kill chain phases for which this Tool instance can be used. ', + name: 'misp.tool.kill_chain_phases', + type: 'text', + }, + 'misp.vulnerability.id': { + category: 'misp', + description: 'Identifier of the Vulnerability. ', + name: 'misp.vulnerability.id', + type: 'keyword', + }, + 'misp.vulnerability.name': { + category: 'misp', + description: 'The name used to identify the Vulnerability. ', + name: 'misp.vulnerability.name', + type: 'keyword', + }, + 'misp.vulnerability.description': { + category: 'misp', + description: 'A description that provides more details and context about the Vulnerability. ', + name: 'misp.vulnerability.description', + type: 'text', + }, + 'mssql.log.origin': { + category: 'mssql', + description: 'Origin of the message, usually the server but it can also be a recovery process', + name: 'mssql.log.origin', + type: 'keyword', + }, + 'o365.audit.Actor.ID': { + category: 'o365', + name: 'o365.audit.Actor.ID', + type: 'keyword', + }, + 'o365.audit.Actor.Type': { + category: 'o365', + name: 'o365.audit.Actor.Type', + type: 'keyword', + }, + 'o365.audit.ActorContextId': { + category: 'o365', + name: 'o365.audit.ActorContextId', + type: 'keyword', + }, + 'o365.audit.ActorIpAddress': { + category: 'o365', + name: 'o365.audit.ActorIpAddress', + type: 'keyword', + }, + 'o365.audit.ActorUserId': { + category: 'o365', + name: 'o365.audit.ActorUserId', + type: 'keyword', + }, + 'o365.audit.ActorYammerUserId': { + category: 'o365', + name: 'o365.audit.ActorYammerUserId', + type: 'keyword', + }, + 'o365.audit.AlertEntityId': { + category: 'o365', + name: 'o365.audit.AlertEntityId', + type: 'keyword', + }, + 'o365.audit.AlertId': { + category: 'o365', + name: 'o365.audit.AlertId', + type: 'keyword', + }, + 'o365.audit.AlertLinks': { + category: 'o365', + name: 'o365.audit.AlertLinks', + type: 'array', + }, + 'o365.audit.AlertType': { + category: 'o365', + name: 'o365.audit.AlertType', + type: 'keyword', + }, + 'o365.audit.AppId': { + category: 'o365', + name: 'o365.audit.AppId', + type: 'keyword', + }, + 'o365.audit.ApplicationDisplayName': { + category: 'o365', + name: 'o365.audit.ApplicationDisplayName', + type: 'keyword', + }, + 'o365.audit.ApplicationId': { + category: 'o365', + name: 'o365.audit.ApplicationId', + type: 'keyword', + }, + 'o365.audit.AzureActiveDirectoryEventType': { + category: 'o365', + name: 'o365.audit.AzureActiveDirectoryEventType', + type: 'keyword', + }, + 'o365.audit.ExchangeMetaData.*': { + category: 'o365', + name: 'o365.audit.ExchangeMetaData.*', + type: 'object', + }, + 'o365.audit.Category': { + category: 'o365', + name: 'o365.audit.Category', + type: 'keyword', + }, + 'o365.audit.ClientAppId': { + category: 'o365', + name: 'o365.audit.ClientAppId', + type: 'keyword', + }, + 'o365.audit.ClientInfoString': { + category: 'o365', + name: 'o365.audit.ClientInfoString', + type: 'keyword', + }, + 'o365.audit.ClientIP': { + category: 'o365', + name: 'o365.audit.ClientIP', + type: 'keyword', + }, + 'o365.audit.ClientIPAddress': { + category: 'o365', + name: 'o365.audit.ClientIPAddress', + type: 'keyword', + }, + 'o365.audit.Comments': { + category: 'o365', + name: 'o365.audit.Comments', + type: 'text', + }, + 'o365.audit.CorrelationId': { + category: 'o365', + name: 'o365.audit.CorrelationId', + type: 'keyword', + }, + 'o365.audit.CreationTime': { + category: 'o365', + name: 'o365.audit.CreationTime', + type: 'keyword', + }, + 'o365.audit.CustomUniqueId': { + category: 'o365', + name: 'o365.audit.CustomUniqueId', + type: 'keyword', + }, + 'o365.audit.Data': { + category: 'o365', + name: 'o365.audit.Data', + type: 'keyword', + }, + 'o365.audit.DataType': { + category: 'o365', + name: 'o365.audit.DataType', + type: 'keyword', + }, + 'o365.audit.EntityType': { + category: 'o365', + name: 'o365.audit.EntityType', + type: 'keyword', + }, + 'o365.audit.EventData': { + category: 'o365', + name: 'o365.audit.EventData', + type: 'keyword', + }, + 'o365.audit.EventSource': { + category: 'o365', + name: 'o365.audit.EventSource', + type: 'keyword', + }, + 'o365.audit.ExceptionInfo.*': { + category: 'o365', + name: 'o365.audit.ExceptionInfo.*', + type: 'object', + }, + 'o365.audit.ExtendedProperties.*': { + category: 'o365', + name: 'o365.audit.ExtendedProperties.*', + type: 'object', + }, + 'o365.audit.ExternalAccess': { + category: 'o365', + name: 'o365.audit.ExternalAccess', + type: 'keyword', + }, + 'o365.audit.GroupName': { + category: 'o365', + name: 'o365.audit.GroupName', + type: 'keyword', + }, + 'o365.audit.Id': { + category: 'o365', + name: 'o365.audit.Id', + type: 'keyword', + }, + 'o365.audit.ImplicitShare': { + category: 'o365', + name: 'o365.audit.ImplicitShare', + type: 'keyword', + }, + 'o365.audit.IncidentId': { + category: 'o365', + name: 'o365.audit.IncidentId', + type: 'keyword', + }, + 'o365.audit.InternalLogonType': { + category: 'o365', + name: 'o365.audit.InternalLogonType', + type: 'keyword', + }, + 'o365.audit.InterSystemsId': { + category: 'o365', + name: 'o365.audit.InterSystemsId', + type: 'keyword', + }, + 'o365.audit.IntraSystemId': { + category: 'o365', + name: 'o365.audit.IntraSystemId', + type: 'keyword', + }, + 'o365.audit.Item.*': { + category: 'o365', + name: 'o365.audit.Item.*', + type: 'object', + }, + 'o365.audit.Item.*.*': { + category: 'o365', + name: 'o365.audit.Item.*.*', + type: 'object', + }, + 'o365.audit.ItemName': { + category: 'o365', + name: 'o365.audit.ItemName', + type: 'keyword', + }, + 'o365.audit.ItemType': { + category: 'o365', + name: 'o365.audit.ItemType', + type: 'keyword', + }, + 'o365.audit.ListId': { + category: 'o365', + name: 'o365.audit.ListId', + type: 'keyword', + }, + 'o365.audit.ListItemUniqueId': { + category: 'o365', + name: 'o365.audit.ListItemUniqueId', + type: 'keyword', + }, + 'o365.audit.LogonError': { + category: 'o365', + name: 'o365.audit.LogonError', + type: 'keyword', + }, + 'o365.audit.LogonType': { + category: 'o365', + name: 'o365.audit.LogonType', + type: 'keyword', + }, + 'o365.audit.LogonUserSid': { + category: 'o365', + name: 'o365.audit.LogonUserSid', + type: 'keyword', + }, + 'o365.audit.MailboxGuid': { + category: 'o365', + name: 'o365.audit.MailboxGuid', + type: 'keyword', + }, + 'o365.audit.MailboxOwnerMasterAccountSid': { + category: 'o365', + name: 'o365.audit.MailboxOwnerMasterAccountSid', + type: 'keyword', + }, + 'o365.audit.MailboxOwnerSid': { + category: 'o365', + name: 'o365.audit.MailboxOwnerSid', + type: 'keyword', + }, + 'o365.audit.MailboxOwnerUPN': { + category: 'o365', + name: 'o365.audit.MailboxOwnerUPN', + type: 'keyword', + }, + 'o365.audit.Members': { + category: 'o365', + name: 'o365.audit.Members', + type: 'array', + }, + 'o365.audit.Members.*': { + category: 'o365', + name: 'o365.audit.Members.*', + type: 'object', + }, + 'o365.audit.ModifiedProperties.*.*': { + category: 'o365', + name: 'o365.audit.ModifiedProperties.*.*', + type: 'object', + }, + 'o365.audit.Name': { + category: 'o365', + name: 'o365.audit.Name', + type: 'keyword', + }, + 'o365.audit.ObjectId': { + category: 'o365', + name: 'o365.audit.ObjectId', + type: 'keyword', + }, + 'o365.audit.Operation': { + category: 'o365', + name: 'o365.audit.Operation', + type: 'keyword', + }, + 'o365.audit.OrganizationId': { + category: 'o365', + name: 'o365.audit.OrganizationId', + type: 'keyword', + }, + 'o365.audit.OrganizationName': { + category: 'o365', + name: 'o365.audit.OrganizationName', + type: 'keyword', + }, + 'o365.audit.OriginatingServer': { + category: 'o365', + name: 'o365.audit.OriginatingServer', + type: 'keyword', + }, + 'o365.audit.Parameters.*': { + category: 'o365', + name: 'o365.audit.Parameters.*', + type: 'object', + }, + 'o365.audit.PolicyDetails': { + category: 'o365', + name: 'o365.audit.PolicyDetails', + type: 'array', + }, + 'o365.audit.PolicyId': { + category: 'o365', + name: 'o365.audit.PolicyId', + type: 'keyword', + }, + 'o365.audit.RecordType': { + category: 'o365', + name: 'o365.audit.RecordType', + type: 'keyword', + }, + 'o365.audit.ResultStatus': { + category: 'o365', + name: 'o365.audit.ResultStatus', + type: 'keyword', + }, + 'o365.audit.SensitiveInfoDetectionIsIncluded': { + category: 'o365', + name: 'o365.audit.SensitiveInfoDetectionIsIncluded', + type: 'keyword', + }, + 'o365.audit.SharePointMetaData.*': { + category: 'o365', + name: 'o365.audit.SharePointMetaData.*', + type: 'object', + }, + 'o365.audit.SessionId': { + category: 'o365', + name: 'o365.audit.SessionId', + type: 'keyword', + }, + 'o365.audit.Severity': { + category: 'o365', + name: 'o365.audit.Severity', + type: 'keyword', + }, + 'o365.audit.Site': { + category: 'o365', + name: 'o365.audit.Site', + type: 'keyword', + }, + 'o365.audit.SiteUrl': { + category: 'o365', + name: 'o365.audit.SiteUrl', + type: 'keyword', + }, + 'o365.audit.Source': { + category: 'o365', + name: 'o365.audit.Source', + type: 'keyword', + }, + 'o365.audit.SourceFileExtension': { + category: 'o365', + name: 'o365.audit.SourceFileExtension', + type: 'keyword', + }, + 'o365.audit.SourceFileName': { + category: 'o365', + name: 'o365.audit.SourceFileName', + type: 'keyword', + }, + 'o365.audit.SourceRelativeUrl': { + category: 'o365', + name: 'o365.audit.SourceRelativeUrl', + type: 'keyword', + }, + 'o365.audit.Status': { + category: 'o365', + name: 'o365.audit.Status', + type: 'keyword', + }, + 'o365.audit.SupportTicketId': { + category: 'o365', + name: 'o365.audit.SupportTicketId', + type: 'keyword', + }, + 'o365.audit.Target.ID': { + category: 'o365', + name: 'o365.audit.Target.ID', + type: 'keyword', + }, + 'o365.audit.Target.Type': { + category: 'o365', + name: 'o365.audit.Target.Type', + type: 'keyword', + }, + 'o365.audit.TargetContextId': { + category: 'o365', + name: 'o365.audit.TargetContextId', + type: 'keyword', + }, + 'o365.audit.TargetUserOrGroupName': { + category: 'o365', + name: 'o365.audit.TargetUserOrGroupName', + type: 'keyword', + }, + 'o365.audit.TargetUserOrGroupType': { + category: 'o365', + name: 'o365.audit.TargetUserOrGroupType', + type: 'keyword', + }, + 'o365.audit.TeamName': { + category: 'o365', + name: 'o365.audit.TeamName', + type: 'keyword', + }, + 'o365.audit.TeamGuid': { + category: 'o365', + name: 'o365.audit.TeamGuid', + type: 'keyword', + }, + 'o365.audit.UniqueSharingId': { + category: 'o365', + name: 'o365.audit.UniqueSharingId', + type: 'keyword', + }, + 'o365.audit.UserAgent': { + category: 'o365', + name: 'o365.audit.UserAgent', + type: 'keyword', + }, + 'o365.audit.UserId': { + category: 'o365', + name: 'o365.audit.UserId', + type: 'keyword', + }, + 'o365.audit.UserKey': { + category: 'o365', + name: 'o365.audit.UserKey', + type: 'keyword', + }, + 'o365.audit.UserType': { + category: 'o365', + name: 'o365.audit.UserType', + type: 'keyword', + }, + 'o365.audit.Version': { + category: 'o365', + name: 'o365.audit.Version', + type: 'keyword', + }, + 'o365.audit.WebId': { + category: 'o365', + name: 'o365.audit.WebId', + type: 'keyword', + }, + 'o365.audit.Workload': { + category: 'o365', + name: 'o365.audit.Workload', + type: 'keyword', + }, + 'o365.audit.YammerNetworkId': { + category: 'o365', + name: 'o365.audit.YammerNetworkId', + type: 'keyword', + }, + 'okta.uuid': { + category: 'okta', + description: 'The unique identifier of the Okta LogEvent. ', + name: 'okta.uuid', + type: 'keyword', + }, + 'okta.event_type': { + category: 'okta', + description: 'The type of the LogEvent. ', + name: 'okta.event_type', + type: 'keyword', + }, + 'okta.version': { + category: 'okta', + description: 'The version of the LogEvent. ', + name: 'okta.version', + type: 'keyword', + }, + 'okta.severity': { + category: 'okta', + description: 'The severity of the LogEvent. Must be one of DEBUG, INFO, WARN, or ERROR. ', + name: 'okta.severity', + type: 'keyword', + }, + 'okta.display_message': { + category: 'okta', + description: 'The display message of the LogEvent. ', + name: 'okta.display_message', + type: 'keyword', + }, + 'okta.actor.id': { + category: 'okta', + description: 'Identifier of the actor. ', + name: 'okta.actor.id', + type: 'keyword', + }, + 'okta.actor.type': { + category: 'okta', + description: 'Type of the actor. ', + name: 'okta.actor.type', + type: 'keyword', + }, + 'okta.actor.alternate_id': { + category: 'okta', + description: 'Alternate identifier of the actor. ', + name: 'okta.actor.alternate_id', + type: 'keyword', + }, + 'okta.actor.display_name': { + category: 'okta', + description: 'Display name of the actor. ', + name: 'okta.actor.display_name', + type: 'keyword', + }, + 'okta.client.ip': { + category: 'okta', + description: 'The IP address of the client. ', + name: 'okta.client.ip', + type: 'ip', + }, + 'okta.client.user_agent.raw_user_agent': { + category: 'okta', + description: 'The raw informaton of the user agent. ', + name: 'okta.client.user_agent.raw_user_agent', + type: 'keyword', + }, + 'okta.client.user_agent.os': { + category: 'okta', + description: 'The OS informaton. ', + name: 'okta.client.user_agent.os', + type: 'keyword', + }, + 'okta.client.user_agent.browser': { + category: 'okta', + description: 'The browser informaton of the client. ', + name: 'okta.client.user_agent.browser', + type: 'keyword', + }, + 'okta.client.zone': { + category: 'okta', + description: 'The zone information of the client. ', + name: 'okta.client.zone', + type: 'keyword', + }, + 'okta.client.device': { + category: 'okta', + description: 'The information of the client device. ', + name: 'okta.client.device', + type: 'keyword', + }, + 'okta.client.id': { + category: 'okta', + description: 'The identifier of the client. ', + name: 'okta.client.id', + type: 'keyword', + }, + 'okta.outcome.reason': { + category: 'okta', + description: 'The reason of the outcome. ', + name: 'okta.outcome.reason', + type: 'keyword', + }, + 'okta.outcome.result': { + category: 'okta', + description: + 'The result of the outcome. Must be one of: SUCCESS, FAILURE, SKIPPED, ALLOW, DENY, CHALLENGE, UNKNOWN. ', + name: 'okta.outcome.result', + type: 'keyword', + }, + 'okta.target.id': { + category: 'okta', + description: 'Identifier of the actor. ', + name: 'okta.target.id', + type: 'keyword', + }, + 'okta.target.type': { + category: 'okta', + description: 'Type of the actor. ', + name: 'okta.target.type', + type: 'keyword', + }, + 'okta.target.alternate_id': { + category: 'okta', + description: 'Alternate identifier of the actor. ', + name: 'okta.target.alternate_id', + type: 'keyword', + }, + 'okta.target.display_name': { + category: 'okta', + description: 'Display name of the actor. ', + name: 'okta.target.display_name', + type: 'keyword', + }, + 'okta.transaction.id': { + category: 'okta', + description: 'Identifier of the transaction. ', + name: 'okta.transaction.id', + type: 'keyword', + }, + 'okta.transaction.type': { + category: 'okta', + description: 'The type of transaction. Must be one of "WEB", "JOB". ', + name: 'okta.transaction.type', + type: 'keyword', + }, + 'okta.debug_context.debug_data.device_fingerprint': { + category: 'okta', + description: 'The fingerprint of the device. ', + name: 'okta.debug_context.debug_data.device_fingerprint', + type: 'keyword', + }, + 'okta.debug_context.debug_data.request_id': { + category: 'okta', + description: 'The identifier of the request. ', + name: 'okta.debug_context.debug_data.request_id', + type: 'keyword', + }, + 'okta.debug_context.debug_data.request_uri': { + category: 'okta', + description: 'The request URI. ', + name: 'okta.debug_context.debug_data.request_uri', + type: 'keyword', + }, + 'okta.debug_context.debug_data.threat_suspected': { + category: 'okta', + description: 'Threat suspected. ', + name: 'okta.debug_context.debug_data.threat_suspected', + type: 'keyword', + }, + 'okta.debug_context.debug_data.url': { + category: 'okta', + description: 'The URL. ', + name: 'okta.debug_context.debug_data.url', + type: 'keyword', + }, + 'okta.authentication_context.authentication_provider': { + category: 'okta', + description: + 'The information about the authentication provider. Must be one of OKTA_AUTHENTICATION_PROVIDER, ACTIVE_DIRECTORY, LDAP, FEDERATION, SOCIAL, FACTOR_PROVIDER. ', + name: 'okta.authentication_context.authentication_provider', + type: 'keyword', + }, + 'okta.authentication_context.authentication_step': { + category: 'okta', + description: 'The authentication step. ', + name: 'okta.authentication_context.authentication_step', + type: 'integer', + }, + 'okta.authentication_context.credential_provider': { + category: 'okta', + description: + 'The information about credential provider. Must be one of OKTA_CREDENTIAL_PROVIDER, RSA, SYMANTEC, GOOGLE, DUO, YUBIKEY. ', + name: 'okta.authentication_context.credential_provider', + type: 'keyword', + }, + 'okta.authentication_context.credential_type': { + category: 'okta', + description: + 'The information about credential type. Must be one of OTP, SMS, PASSWORD, ASSERTION, IWA, EMAIL, OAUTH2, JWT, CERTIFICATE, PRE_SHARED_SYMMETRIC_KEY, OKTA_CLIENT_SESSION, DEVICE_UDID. ', + name: 'okta.authentication_context.credential_type', + type: 'keyword', + }, + 'okta.authentication_context.issuer.id': { + category: 'okta', + description: 'The identifier of the issuer. ', + name: 'okta.authentication_context.issuer.id', + type: 'keyword', + }, + 'okta.authentication_context.issuer.type': { + category: 'okta', + description: 'The type of the issuer. ', + name: 'okta.authentication_context.issuer.type', + type: 'keyword', + }, + 'okta.authentication_context.external_session_id': { + category: 'okta', + description: 'The session identifer of the external session if any. ', + name: 'okta.authentication_context.external_session_id', + type: 'keyword', + }, + 'okta.authentication_context.interface': { + category: 'okta', + description: 'The interface used. e.g., Outlook, Office365, wsTrust ', + name: 'okta.authentication_context.interface', + type: 'keyword', + }, + 'okta.security_context.as.number': { + category: 'okta', + description: 'The AS number. ', + name: 'okta.security_context.as.number', + type: 'integer', + }, + 'okta.security_context.as.organization.name': { + category: 'okta', + description: 'The organization name. ', + name: 'okta.security_context.as.organization.name', + type: 'keyword', + }, + 'okta.security_context.isp': { + category: 'okta', + description: 'The Internet Service Provider. ', + name: 'okta.security_context.isp', + type: 'keyword', + }, + 'okta.security_context.domain': { + category: 'okta', + description: 'The domain name. ', + name: 'okta.security_context.domain', + type: 'keyword', + }, + 'okta.security_context.is_proxy': { + category: 'okta', + description: 'Whether it is a proxy or not. ', + name: 'okta.security_context.is_proxy', + type: 'boolean', + }, + 'okta.request.ip_chain.ip': { + category: 'okta', + description: 'IP address. ', + name: 'okta.request.ip_chain.ip', + type: 'ip', + }, + 'okta.request.ip_chain.version': { + category: 'okta', + description: 'IP version. Must be one of V4, V6. ', + name: 'okta.request.ip_chain.version', + type: 'keyword', + }, + 'okta.request.ip_chain.source': { + category: 'okta', + description: 'Source information. ', + name: 'okta.request.ip_chain.source', + type: 'keyword', + }, + 'okta.request.ip_chain.geographical_context.city': { + category: 'okta', + description: 'The city.', + name: 'okta.request.ip_chain.geographical_context.city', + type: 'keyword', + }, + 'okta.request.ip_chain.geographical_context.state': { + category: 'okta', + description: 'The state.', + name: 'okta.request.ip_chain.geographical_context.state', + type: 'keyword', + }, + 'okta.request.ip_chain.geographical_context.postal_code': { + category: 'okta', + description: 'The postal code.', + name: 'okta.request.ip_chain.geographical_context.postal_code', + type: 'keyword', + }, + 'okta.request.ip_chain.geographical_context.country': { + category: 'okta', + description: 'The country.', + name: 'okta.request.ip_chain.geographical_context.country', + type: 'keyword', + }, + 'okta.request.ip_chain.geographical_context.geolocation': { + category: 'okta', + description: 'Geolocation information. ', + name: 'okta.request.ip_chain.geographical_context.geolocation', + type: 'geo_point', + }, + 'panw.panos.ruleset': { + category: 'panw', + description: 'Name of the rule that matched this session. ', + name: 'panw.panos.ruleset', + type: 'keyword', + }, + 'panw.panos.source.zone': { + category: 'panw', + description: 'Source zone for this session. ', + name: 'panw.panos.source.zone', + type: 'keyword', + }, + 'panw.panos.source.interface': { + category: 'panw', + description: 'Source interface for this session. ', + name: 'panw.panos.source.interface', + type: 'keyword', + }, + 'panw.panos.source.nat.ip': { + category: 'panw', + description: 'Post-NAT source IP. ', + name: 'panw.panos.source.nat.ip', + type: 'ip', + }, + 'panw.panos.source.nat.port': { + category: 'panw', + description: 'Post-NAT source port. ', + name: 'panw.panos.source.nat.port', + type: 'long', + }, + 'panw.panos.destination.zone': { + category: 'panw', + description: 'Destination zone for this session. ', + name: 'panw.panos.destination.zone', + type: 'keyword', + }, + 'panw.panos.destination.interface': { + category: 'panw', + description: 'Destination interface for this session. ', + name: 'panw.panos.destination.interface', + type: 'keyword', + }, + 'panw.panos.destination.nat.ip': { + category: 'panw', + description: 'Post-NAT destination IP. ', + name: 'panw.panos.destination.nat.ip', + type: 'ip', + }, + 'panw.panos.destination.nat.port': { + category: 'panw', + description: 'Post-NAT destination port. ', + name: 'panw.panos.destination.nat.port', + type: 'long', + }, + 'panw.panos.network.pcap_id': { + category: 'panw', + description: 'Packet capture ID for a threat. ', + name: 'panw.panos.network.pcap_id', + type: 'keyword', + }, + 'panw.panos.network.nat.community_id': { + category: 'panw', + description: 'Community ID flow-hash for the NAT 5-tuple. ', + name: 'panw.panos.network.nat.community_id', + type: 'keyword', + }, + 'panw.panos.file.hash': { + category: 'panw', + description: 'Binary hash for a threat file sent to be analyzed by the WildFire service. ', + name: 'panw.panos.file.hash', + type: 'keyword', + }, + 'panw.panos.url.category': { + category: 'panw', + description: + "For threat URLs, it's the URL category. For WildFire, the verdict on the file and is either 'malicious', 'grayware', or 'benign'. ", + name: 'panw.panos.url.category', + type: 'keyword', + }, + 'panw.panos.flow_id': { + category: 'panw', + description: 'Internal numeric identifier for each session. ', + name: 'panw.panos.flow_id', + type: 'keyword', + }, + 'panw.panos.sequence_number': { + category: 'panw', + description: + 'Log entry identifier that is incremented sequentially. Unique for each log type. ', + name: 'panw.panos.sequence_number', + type: 'long', + }, + 'panw.panos.threat.resource': { + category: 'panw', + description: 'URL or file name for a threat. ', + name: 'panw.panos.threat.resource', + type: 'keyword', + }, + 'panw.panos.threat.id': { + category: 'panw', + description: 'Palo Alto Networks identifier for the threat. ', + name: 'panw.panos.threat.id', + type: 'keyword', + }, + 'panw.panos.threat.name': { + category: 'panw', + description: 'Palo Alto Networks name for the threat. ', + name: 'panw.panos.threat.name', + type: 'keyword', + }, + 'panw.panos.action': { + category: 'panw', + description: 'Action taken for the session.', + name: 'panw.panos.action', + type: 'keyword', + }, + 'rabbitmq.log.pid': { + category: 'rabbitmq', + description: 'The Erlang process id', + example: '<0.222.0>', + name: 'rabbitmq.log.pid', + type: 'keyword', + }, + 'sophos.xg.device': { + category: 'sophos', + description: 'device ', + name: 'sophos.xg.device', + type: 'keyword', + }, + 'sophos.xg.date': { + category: 'sophos', + description: 'Date (yyyy-mm-dd) when the event occurred ', + name: 'sophos.xg.date', + type: 'date', + }, + 'sophos.xg.timezone': { + category: 'sophos', + description: 'Time (hh:mm:ss) when the event occurred ', + name: 'sophos.xg.timezone', + type: 'keyword', + }, + 'sophos.xg.device_name': { + category: 'sophos', + description: 'Model number of the device ', + name: 'sophos.xg.device_name', + type: 'keyword', + }, + 'sophos.xg.device_id': { + category: 'sophos', + description: 'Serial number of the device ', + name: 'sophos.xg.device_id', + type: 'keyword', + }, + 'sophos.xg.log_id': { + category: 'sophos', + description: 'Unique 12 characters code (0101011) ', + name: 'sophos.xg.log_id', + type: 'keyword', + }, + 'sophos.xg.log_type': { + category: 'sophos', + description: 'Type of event e.g. firewall event ', + name: 'sophos.xg.log_type', + type: 'keyword', + }, + 'sophos.xg.log_component': { + category: 'sophos', + description: 'Component responsible for logging e.g. Firewall rule ', + name: 'sophos.xg.log_component', + type: 'keyword', + }, + 'sophos.xg.log_subtype': { + category: 'sophos', + description: 'Sub type of event ', + name: 'sophos.xg.log_subtype', + type: 'keyword', + }, + 'sophos.xg.hb_health': { + category: 'sophos', + description: 'Heartbeat status ', + name: 'sophos.xg.hb_health', + type: 'keyword', + }, + 'sophos.xg.priority': { + category: 'sophos', + description: 'Severity level of traffic ', + name: 'sophos.xg.priority', + type: 'keyword', + }, + 'sophos.xg.status': { + category: 'sophos', + description: 'Ultimate status of traffic – Allowed or Denied ', + name: 'sophos.xg.status', + type: 'keyword', + }, + 'sophos.xg.duration': { + category: 'sophos', + description: 'Durability of traffic (seconds) ', + name: 'sophos.xg.duration', + type: 'long', + }, + 'sophos.xg.fw_rule_id': { + category: 'sophos', + description: 'Firewall Rule ID which is applied on the traffic ', + name: 'sophos.xg.fw_rule_id', + type: 'integer', + }, + 'sophos.xg.user_name': { + category: 'sophos', + description: 'user_name ', + name: 'sophos.xg.user_name', + type: 'keyword', + }, + 'sophos.xg.user_group': { + category: 'sophos', + description: 'Group name to which the user belongs ', + name: 'sophos.xg.user_group', + type: 'keyword', + }, + 'sophos.xg.iap': { + category: 'sophos', + description: 'Internet Access policy ID applied on the traffic ', + name: 'sophos.xg.iap', + type: 'keyword', + }, + 'sophos.xg.ips_policy_id': { + category: 'sophos', + description: 'IPS policy ID applied on the traffic ', + name: 'sophos.xg.ips_policy_id', + type: 'integer', + }, + 'sophos.xg.policy_type': { + category: 'sophos', + description: 'Policy type applied to the traffic ', + name: 'sophos.xg.policy_type', + type: 'keyword', + }, + 'sophos.xg.appfilter_policy_id': { + category: 'sophos', + description: 'Application Filter policy applied on the traffic ', + name: 'sophos.xg.appfilter_policy_id', + type: 'integer', + }, + 'sophos.xg.application_filter_policy': { + category: 'sophos', + description: 'Application Filter policy applied on the traffic ', + name: 'sophos.xg.application_filter_policy', + type: 'integer', + }, + 'sophos.xg.application': { + category: 'sophos', + description: 'Application name ', + name: 'sophos.xg.application', + type: 'keyword', + }, + 'sophos.xg.application_name': { + category: 'sophos', + description: 'Application name ', + name: 'sophos.xg.application_name', + type: 'keyword', + }, + 'sophos.xg.application_risk': { + category: 'sophos', + description: 'Risk level assigned to the application ', + name: 'sophos.xg.application_risk', + type: 'keyword', + }, + 'sophos.xg.application_technology': { + category: 'sophos', + description: 'Technology of the application ', + name: 'sophos.xg.application_technology', + type: 'keyword', + }, + 'sophos.xg.application_category': { + category: 'sophos', + description: 'Application is resolved by signature or synchronized application ', + name: 'sophos.xg.application_category', + type: 'keyword', + }, + 'sophos.xg.appresolvedby': { + category: 'sophos', + description: 'Technology of the application ', + name: 'sophos.xg.appresolvedby', + type: 'keyword', + }, + 'sophos.xg.app_is_cloud': { + category: 'sophos', + description: 'Application is Cloud ', + name: 'sophos.xg.app_is_cloud', + type: 'keyword', + }, + 'sophos.xg.in_interface': { + category: 'sophos', + description: 'Interface for incoming traffic, e.g., Port A ', + name: 'sophos.xg.in_interface', + type: 'keyword', + }, + 'sophos.xg.out_interface': { + category: 'sophos', + description: 'Interface for outgoing traffic, e.g., Port B ', + name: 'sophos.xg.out_interface', + type: 'keyword', + }, + 'sophos.xg.src_ip': { + category: 'sophos', + description: 'Original source IP address of traffic ', + name: 'sophos.xg.src_ip', + type: 'ip', + }, + 'sophos.xg.src_mac': { + category: 'sophos', + description: 'Original source MAC address of traffic ', + name: 'sophos.xg.src_mac', + type: 'keyword', + }, + 'sophos.xg.src_country_code': { + category: 'sophos', + description: 'Code of the country to which the source IP belongs ', + name: 'sophos.xg.src_country_code', + type: 'keyword', + }, + 'sophos.xg.dst_ip': { + category: 'sophos', + description: 'Original destination IP address of traffic ', + name: 'sophos.xg.dst_ip', + type: 'ip', + }, + 'sophos.xg.dst_country_code': { + category: 'sophos', + description: 'Code of the country to which the destination IP belongs ', + name: 'sophos.xg.dst_country_code', + type: 'keyword', + }, + 'sophos.xg.protocol': { + category: 'sophos', + description: 'Protocol number of traffic ', + name: 'sophos.xg.protocol', + type: 'keyword', + }, + 'sophos.xg.src_port': { + category: 'sophos', + description: 'Original source port of TCP and UDP traffic ', + name: 'sophos.xg.src_port', + type: 'integer', + }, + 'sophos.xg.dst_port': { + category: 'sophos', + description: 'Original destination port of TCP and UDP traffic ', + name: 'sophos.xg.dst_port', + type: 'integer', + }, + 'sophos.xg.icmp_type': { + category: 'sophos', + description: 'ICMP type of ICMP traffic ', + name: 'sophos.xg.icmp_type', + type: 'keyword', + }, + 'sophos.xg.icmp_code': { + category: 'sophos', + description: 'ICMP code of ICMP traffic ', + name: 'sophos.xg.icmp_code', + type: 'keyword', + }, + 'sophos.xg.sent_pkts': { + category: 'sophos', + description: 'Total number of packets sent ', + name: 'sophos.xg.sent_pkts', + type: 'long', + }, + 'sophos.xg.received_pkts': { + category: 'sophos', + description: 'Total number of packets received ', + name: 'sophos.xg.received_pkts', + type: 'long', + }, + 'sophos.xg.sent_bytes': { + category: 'sophos', + description: 'Total number of bytes sent ', + name: 'sophos.xg.sent_bytes', + type: 'long', + }, + 'sophos.xg.recv_bytes': { + category: 'sophos', + description: 'Total number of bytes received ', + name: 'sophos.xg.recv_bytes', + type: 'long', + }, + 'sophos.xg.trans_src_ ip': { + category: 'sophos', + description: 'Translated source IP address for outgoing traffic ', + name: 'sophos.xg.trans_src_ ip', + type: 'ip', + }, + 'sophos.xg.trans_src_port': { + category: 'sophos', + description: 'Translated source port for outgoing traffic ', + name: 'sophos.xg.trans_src_port', + type: 'integer', + }, + 'sophos.xg.trans_dst_ip': { + category: 'sophos', + description: 'Translated destination IP address for outgoing traffic ', + name: 'sophos.xg.trans_dst_ip', + type: 'ip', + }, + 'sophos.xg.trans_dst_port': { + category: 'sophos', + description: 'Translated destination port for outgoing traffic ', + name: 'sophos.xg.trans_dst_port', + type: 'integer', + }, + 'sophos.xg.srczonetype': { + category: 'sophos', + description: 'Type of source zone, e.g., LAN ', + name: 'sophos.xg.srczonetype', + type: 'keyword', + }, + 'sophos.xg.srczone': { + category: 'sophos', + description: 'Name of source zone ', + name: 'sophos.xg.srczone', + type: 'keyword', + }, + 'sophos.xg.dstzonetype': { + category: 'sophos', + description: 'Type of destination zone, e.g., WAN ', + name: 'sophos.xg.dstzonetype', + type: 'keyword', + }, + 'sophos.xg.dstzone': { + category: 'sophos', + description: 'Name of destination zone ', + name: 'sophos.xg.dstzone', + type: 'keyword', + }, + 'sophos.xg.dir_disp': { + category: 'sophos', + description: 'TPacket direction. Possible values:“org”, “reply”, “” ', + name: 'sophos.xg.dir_disp', + type: 'keyword', + }, + 'sophos.xg.connevent': { + category: 'sophos', + description: 'Event on which this log is generated ', + name: 'sophos.xg.connevent', + type: 'keyword', + }, + 'sophos.xg.conn_id': { + category: 'sophos', + description: 'Unique identifier of connection ', + name: 'sophos.xg.conn_id', + type: 'integer', + }, + 'sophos.xg.vconn_id': { + category: 'sophos', + description: 'Connection ID of the master connection ', + name: 'sophos.xg.vconn_id', + type: 'integer', + }, + 'sophos.xg.idp_policy_id': { + category: 'sophos', + description: 'IPS policy ID which is applied on the traffic ', + name: 'sophos.xg.idp_policy_id', + type: 'integer', + }, + 'sophos.xg.idp_policy_name': { + category: 'sophos', + description: 'IPS policy name i.e. IPS policy name which is applied on the traffic ', + name: 'sophos.xg.idp_policy_name', + type: 'keyword', + }, + 'sophos.xg.signature_id': { + category: 'sophos', + description: 'Signature ID ', + name: 'sophos.xg.signature_id', + type: 'keyword', + }, + 'sophos.xg.signature_msg': { + category: 'sophos', + description: 'Signature messsage ', + name: 'sophos.xg.signature_msg', + type: 'keyword', + }, + 'sophos.xg.classification': { + category: 'sophos', + description: 'Signature classification ', + name: 'sophos.xg.classification', + type: 'keyword', + }, + 'sophos.xg.rule_priority': { + category: 'sophos', + description: 'Priority of IPS policy ', + name: 'sophos.xg.rule_priority', + type: 'keyword', + }, + 'sophos.xg.platform': { + category: 'sophos', + description: 'Platform of the traffic. ', + name: 'sophos.xg.platform', + type: 'keyword', + }, + 'sophos.xg.category': { + category: 'sophos', + description: 'IPS signature category. ', + name: 'sophos.xg.category', + type: 'keyword', + }, + 'sophos.xg.target': { + category: 'sophos', + description: 'Platform of the traffic. ', + name: 'sophos.xg.target', + type: 'keyword', + }, + 'sophos.xg.eventid': { + category: 'sophos', + description: 'ATP Evenet ID ', + name: 'sophos.xg.eventid', + type: 'keyword', + }, + 'sophos.xg.ep_uuid': { + category: 'sophos', + description: 'Endpoint UUID ', + name: 'sophos.xg.ep_uuid', + type: 'keyword', + }, + 'sophos.xg.threatname': { + category: 'sophos', + description: 'ATP threatname ', + name: 'sophos.xg.threatname', + type: 'keyword', + }, + 'sophos.xg.sourceip': { + category: 'sophos', + description: 'Original source IP address of traffic ', + name: 'sophos.xg.sourceip', + type: 'ip', + }, + 'sophos.xg.destinationip': { + category: 'sophos', + description: 'Original destination IP address of traffic ', + name: 'sophos.xg.destinationip', + type: 'ip', + }, + 'sophos.xg.login_user': { + category: 'sophos', + description: 'ATP login user ', + name: 'sophos.xg.login_user', + type: 'keyword', + }, + 'sophos.xg.eventtype': { + category: 'sophos', + description: 'ATP event type ', + name: 'sophos.xg.eventtype', + type: 'keyword', + }, + 'sophos.xg.execution_path': { + category: 'sophos', + description: 'ATP execution path ', + name: 'sophos.xg.execution_path', + type: 'keyword', + }, + 'sophos.xg.av_policy_name': { + category: 'sophos', + description: 'Malware scanning policy name which is applied on the traffic ', + name: 'sophos.xg.av_policy_name', + type: 'keyword', + }, + 'sophos.xg.from_email_address': { + category: 'sophos', + description: 'Sender email address ', + name: 'sophos.xg.from_email_address', + type: 'keyword', + }, + 'sophos.xg.to_email_address': { + category: 'sophos', + description: 'Receipeint email address ', + name: 'sophos.xg.to_email_address', + type: 'keyword', + }, + 'sophos.xg.subject': { + category: 'sophos', + description: 'Email subject ', + name: 'sophos.xg.subject', + type: 'keyword', + }, + 'sophos.xg.mailsize': { + category: 'sophos', + description: 'mailsize ', + name: 'sophos.xg.mailsize', + type: 'integer', + }, + 'sophos.xg.virus': { + category: 'sophos', + description: 'virus name ', + name: 'sophos.xg.virus', + type: 'keyword', + }, + 'sophos.xg.FTP_url': { + category: 'sophos', + description: 'FTP URL from which virus was downloaded ', + name: 'sophos.xg.FTP_url', + type: 'keyword', + }, + 'sophos.xg.FTP_direction': { + category: 'sophos', + description: 'Direction of FTP transfer: Upload or Download ', + name: 'sophos.xg.FTP_direction', + type: 'keyword', + }, + 'sophos.xg.filesize': { + category: 'sophos', + description: 'Size of the file that contained virus ', + name: 'sophos.xg.filesize', + type: 'integer', + }, + 'sophos.xg.filepath': { + category: 'sophos', + description: 'Path of the file containing virus ', + name: 'sophos.xg.filepath', + type: 'keyword', + }, + 'sophos.xg.filename': { + category: 'sophos', + description: 'File name associated with the event ', + name: 'sophos.xg.filename', + type: 'keyword', + }, + 'sophos.xg.ftpcommand': { + category: 'sophos', + description: 'FTP command used when virus was found ', + name: 'sophos.xg.ftpcommand', + type: 'keyword', + }, + 'sophos.xg.url': { + category: 'sophos', + description: 'URL from which virus was downloaded ', + name: 'sophos.xg.url', + type: 'keyword', + }, + 'sophos.xg.domainname': { + category: 'sophos', + description: 'Domain from which virus was downloaded ', + name: 'sophos.xg.domainname', + type: 'keyword', + }, + 'sophos.xg.quarantine': { + category: 'sophos', + description: 'Path and filename of the file quarantined ', + name: 'sophos.xg.quarantine', + type: 'keyword', + }, + 'sophos.xg.src_domainname': { + category: 'sophos', + description: 'Sender domain name ', + name: 'sophos.xg.src_domainname', + type: 'keyword', + }, + 'sophos.xg.dst_domainname': { + category: 'sophos', + description: 'Receiver domain name ', + name: 'sophos.xg.dst_domainname', + type: 'keyword', + }, + 'sophos.xg.reason': { + category: 'sophos', + description: 'Reason why the record was detected as spam/malicious ', + name: 'sophos.xg.reason', + type: 'keyword', + }, + 'sophos.xg.referer': { + category: 'sophos', + description: 'Referer ', + name: 'sophos.xg.referer', + type: 'keyword', + }, + 'sophos.xg.spamaction': { + category: 'sophos', + description: 'Spam Action ', + name: 'sophos.xg.spamaction', + type: 'keyword', + }, + 'sophos.xg.mailid': { + category: 'sophos', + description: 'mailid ', + name: 'sophos.xg.mailid', + type: 'keyword', + }, + 'sophos.xg.quarantine_reason': { + category: 'sophos', + description: 'Quarantine reason ', + name: 'sophos.xg.quarantine_reason', + type: 'keyword', + }, + 'sophos.xg.status_code': { + category: 'sophos', + description: 'Status code ', + name: 'sophos.xg.status_code', + type: 'keyword', + }, + 'sophos.xg.override_token': { + category: 'sophos', + description: 'Override token ', + name: 'sophos.xg.override_token', + type: 'keyword', + }, + 'sophos.xg.con_id': { + category: 'sophos', + description: 'Unique identifier of connection ', + name: 'sophos.xg.con_id', + type: 'integer', + }, + 'sophos.xg.override_authorizer': { + category: 'sophos', + description: 'Override authorizer ', + name: 'sophos.xg.override_authorizer', + type: 'keyword', + }, + 'sophos.xg.transactionid': { + category: 'sophos', + description: 'Transaction ID of the AV scan. ', + name: 'sophos.xg.transactionid', + type: 'keyword', + }, + 'sophos.xg.upload_file_type': { + category: 'sophos', + description: 'Upload file type ', + name: 'sophos.xg.upload_file_type', + type: 'keyword', + }, + 'sophos.xg.upload_file_name': { + category: 'sophos', + description: 'Upload file name ', + name: 'sophos.xg.upload_file_name', + type: 'keyword', + }, + 'sophos.xg.httpresponsecode': { + category: 'sophos', + description: 'code of HTTP response ', + name: 'sophos.xg.httpresponsecode', + type: 'long', + }, + 'sophos.xg.user_gp': { + category: 'sophos', + description: 'Group name to which the user belongs. ', + name: 'sophos.xg.user_gp', + type: 'keyword', + }, + 'sophos.xg.category_type': { + category: 'sophos', + description: 'Type of category under which website falls ', + name: 'sophos.xg.category_type', + type: 'keyword', + }, + 'sophos.xg.download_file_type': { + category: 'sophos', + description: 'Download file type ', + name: 'sophos.xg.download_file_type', + type: 'keyword', + }, + 'sophos.xg.exceptions': { + category: 'sophos', + description: 'List of the checks excluded by web exceptions. ', + name: 'sophos.xg.exceptions', + type: 'keyword', + }, + 'sophos.xg.contenttype': { + category: 'sophos', + description: 'Type of the content ', + name: 'sophos.xg.contenttype', + type: 'keyword', + }, + 'sophos.xg.override_name': { + category: 'sophos', + description: 'Override name ', + name: 'sophos.xg.override_name', + type: 'keyword', + }, + 'sophos.xg.activityname': { + category: 'sophos', + description: 'Web policy activity that matched and caused the policy result. ', + name: 'sophos.xg.activityname', + type: 'keyword', + }, + 'sophos.xg.download_file_name': { + category: 'sophos', + description: 'Download file name ', + name: 'sophos.xg.download_file_name', + type: 'keyword', + }, + 'sophos.xg.sha1sum': { + category: 'sophos', + description: 'SHA1 checksum of the item being analyzed ', + name: 'sophos.xg.sha1sum', + type: 'keyword', + }, + 'sophos.xg.message_id': { + category: 'sophos', + description: 'Message ID ', + name: 'sophos.xg.message_id', + type: 'keyword', + }, + 'sophos.xg.connid': { + category: 'sophos', + description: 'Connection ID ', + name: 'sophos.xg.connid', + type: 'keyword', + }, + 'sophos.xg.message': { + category: 'sophos', + description: 'Message ', + name: 'sophos.xg.message', + type: 'keyword', + }, + 'sophos.xg.email_subject': { + category: 'sophos', + description: 'Email Subject ', + name: 'sophos.xg.email_subject', + type: 'keyword', + }, + 'sophos.xg.file_path': { + category: 'sophos', + description: 'File path ', + name: 'sophos.xg.file_path', + type: 'keyword', + }, + 'sophos.xg.dstdomain': { + category: 'sophos', + description: 'Destination Domain ', + name: 'sophos.xg.dstdomain', + type: 'keyword', + }, + 'sophos.xg.file_size': { + category: 'sophos', + description: 'File Size ', + name: 'sophos.xg.file_size', + type: 'integer', + }, + 'sophos.xg.transaction_id': { + category: 'sophos', + description: 'Transaction ID ', + name: 'sophos.xg.transaction_id', + type: 'keyword', + }, + 'sophos.xg.website': { + category: 'sophos', + description: 'Website ', + name: 'sophos.xg.website', + type: 'keyword', + }, + 'sophos.xg.file_name': { + category: 'sophos', + description: 'Filename ', + name: 'sophos.xg.file_name', + type: 'keyword', + }, + 'sophos.xg.context_prefix': { + category: 'sophos', + description: 'Content Prefix ', + name: 'sophos.xg.context_prefix', + type: 'keyword', + }, + 'sophos.xg.site_category': { + category: 'sophos', + description: 'Site Category ', + name: 'sophos.xg.site_category', + type: 'keyword', + }, + 'sophos.xg.context_suffix': { + category: 'sophos', + description: 'Context Suffix ', + name: 'sophos.xg.context_suffix', + type: 'keyword', + }, + 'sophos.xg.dictionary_name': { + category: 'sophos', + description: 'Dictionary Name ', + name: 'sophos.xg.dictionary_name', + type: 'keyword', + }, + 'sophos.xg.action': { + category: 'sophos', + description: 'Event Action ', + name: 'sophos.xg.action', + type: 'keyword', + }, + 'sophos.xg.user': { + category: 'sophos', + description: 'User ', + name: 'sophos.xg.user', + type: 'keyword', + }, + 'sophos.xg.context_match': { + category: 'sophos', + description: 'Context Match ', + name: 'sophos.xg.context_match', + type: 'keyword', + }, + 'sophos.xg.direction': { + category: 'sophos', + description: 'Direction ', + name: 'sophos.xg.direction', + type: 'keyword', + }, + 'sophos.xg.auth_client': { + category: 'sophos', + description: 'Auth Client ', + name: 'sophos.xg.auth_client', + type: 'keyword', + }, + 'sophos.xg.auth_mechanism': { + category: 'sophos', + description: 'Auth mechanism ', + name: 'sophos.xg.auth_mechanism', + type: 'keyword', + }, + 'sophos.xg.connectionname': { + category: 'sophos', + description: 'Connectionname ', + name: 'sophos.xg.connectionname', + type: 'keyword', + }, + 'sophos.xg.remotenetwork': { + category: 'sophos', + description: 'remotenetwork ', + name: 'sophos.xg.remotenetwork', + type: 'keyword', + }, + 'sophos.xg.localgateway': { + category: 'sophos', + description: 'Localgateway ', + name: 'sophos.xg.localgateway', + type: 'keyword', + }, + 'sophos.xg.localnetwork': { + category: 'sophos', + description: 'Localnetwork ', + name: 'sophos.xg.localnetwork', + type: 'keyword', + }, + 'sophos.xg.connectiontype': { + category: 'sophos', + description: 'Connectiontype ', + name: 'sophos.xg.connectiontype', + type: 'keyword', + }, + 'sophos.xg.oldversion': { + category: 'sophos', + description: 'Oldversion ', + name: 'sophos.xg.oldversion', + type: 'keyword', + }, + 'sophos.xg.newversion': { + category: 'sophos', + description: 'Newversion ', + name: 'sophos.xg.newversion', + type: 'keyword', + }, + 'sophos.xg.ipaddress': { + category: 'sophos', + description: 'Ipaddress ', + name: 'sophos.xg.ipaddress', + type: 'keyword', + }, + 'sophos.xg.client_physical_address': { + category: 'sophos', + description: 'Client physical address ', + name: 'sophos.xg.client_physical_address', + type: 'keyword', + }, + 'sophos.xg.client_host_name': { + category: 'sophos', + description: 'Client host name ', + name: 'sophos.xg.client_host_name', + type: 'keyword', + }, + 'sophos.xg.raw_data': { + category: 'sophos', + description: 'Raw data ', + name: 'sophos.xg.raw_data', + type: 'keyword', + }, + 'sophos.xg.Mode': { + category: 'sophos', + description: 'Mode ', + name: 'sophos.xg.Mode', + type: 'keyword', + }, + 'sophos.xg.sessionid': { + category: 'sophos', + description: 'Sessionid ', + name: 'sophos.xg.sessionid', + type: 'keyword', + }, + 'sophos.xg.starttime': { + category: 'sophos', + description: 'Starttime ', + name: 'sophos.xg.starttime', + type: 'date', + }, + 'sophos.xg.remote_ip': { + category: 'sophos', + description: 'Remote IP ', + name: 'sophos.xg.remote_ip', + type: 'ip', + }, + 'sophos.xg.timestamp': { + category: 'sophos', + description: 'timestamp ', + name: 'sophos.xg.timestamp', + type: 'date', + }, + 'sophos.xg.SysLog_SERVER_NAME': { + category: 'sophos', + description: 'SysLog SERVER NAME ', + name: 'sophos.xg.SysLog_SERVER_NAME', + type: 'keyword', + }, + 'sophos.xg.backup_mode': { + category: 'sophos', + description: 'Backup mode ', + name: 'sophos.xg.backup_mode', + type: 'keyword', + }, + 'sophos.xg.source': { + category: 'sophos', + description: 'Source ', + name: 'sophos.xg.source', + type: 'keyword', + }, + 'sophos.xg.server': { + category: 'sophos', + description: 'Server ', + name: 'sophos.xg.server', + type: 'keyword', + }, + 'sophos.xg.host': { + category: 'sophos', + description: 'Host ', + name: 'sophos.xg.host', + type: 'keyword', + }, + 'sophos.xg.responsetime': { + category: 'sophos', + description: 'Responsetime ', + name: 'sophos.xg.responsetime', + type: 'long', + }, + 'sophos.xg.cookie': { + category: 'sophos', + description: 'cookie ', + name: 'sophos.xg.cookie', + type: 'keyword', + }, + 'sophos.xg.querystring': { + category: 'sophos', + description: 'querystring ', + name: 'sophos.xg.querystring', + type: 'keyword', + }, + 'sophos.xg.extra': { + category: 'sophos', + description: 'extra ', + name: 'sophos.xg.extra', + type: 'keyword', + }, + 'sophos.xg.PHPSESSID': { + category: 'sophos', + description: 'PHPSESSID ', + name: 'sophos.xg.PHPSESSID', + type: 'keyword', + }, + 'sophos.xg.start_time': { + category: 'sophos', + description: 'Start time ', + name: 'sophos.xg.start_time', + type: 'date', + }, + 'sophos.xg.eventtime': { + category: 'sophos', + description: 'Event time ', + name: 'sophos.xg.eventtime', + type: 'date', + }, + 'sophos.xg.red_id': { + category: 'sophos', + description: 'RED ID ', + name: 'sophos.xg.red_id', + type: 'keyword', + }, + 'sophos.xg.branch_name': { + category: 'sophos', + description: 'Branch Name ', + name: 'sophos.xg.branch_name', + type: 'keyword', + }, + 'sophos.xg.updatedip': { + category: 'sophos', + description: 'updatedip ', + name: 'sophos.xg.updatedip', + type: 'ip', + }, + 'sophos.xg.idle_cpu': { + category: 'sophos', + description: 'idle ## ', + name: 'sophos.xg.idle_cpu', + type: 'float', + }, + 'sophos.xg.system_cpu': { + category: 'sophos', + description: 'system ', + name: 'sophos.xg.system_cpu', + type: 'float', + }, + 'sophos.xg.user_cpu': { + category: 'sophos', + description: 'system ', + name: 'sophos.xg.user_cpu', + type: 'float', + }, + 'sophos.xg.used': { + category: 'sophos', + description: 'used ', + name: 'sophos.xg.used', + type: 'integer', + }, + 'sophos.xg.unit': { + category: 'sophos', + description: 'unit ', + name: 'sophos.xg.unit', + type: 'keyword', + }, + 'sophos.xg.total_memory': { + category: 'sophos', + description: 'Total Memory ', + name: 'sophos.xg.total_memory', + type: 'integer', + }, + 'sophos.xg.free': { + category: 'sophos', + description: 'free ', + name: 'sophos.xg.free', + type: 'integer', + }, + 'sophos.xg.transmittederrors': { + category: 'sophos', + description: 'transmitted errors ', + name: 'sophos.xg.transmittederrors', + type: 'keyword', + }, + 'sophos.xg.receivederrors': { + category: 'sophos', + description: 'received errors ', + name: 'sophos.xg.receivederrors', + type: 'keyword', + }, + 'sophos.xg.receivedkbits': { + category: 'sophos', + description: 'received kbits ', + name: 'sophos.xg.receivedkbits', + type: 'long', + }, + 'sophos.xg.transmittedkbits': { + category: 'sophos', + description: 'transmitted kbits ', + name: 'sophos.xg.transmittedkbits', + type: 'long', + }, + 'sophos.xg.transmitteddrops': { + category: 'sophos', + description: 'transmitted drops ', + name: 'sophos.xg.transmitteddrops', + type: 'long', + }, + 'sophos.xg.receiveddrops': { + category: 'sophos', + description: 'received drops ', + name: 'sophos.xg.receiveddrops', + type: 'long', + }, + 'sophos.xg.collisions': { + category: 'sophos', + description: 'collisions ', + name: 'sophos.xg.collisions', + type: 'long', + }, + 'sophos.xg.interface': { + category: 'sophos', + description: 'interface ', + name: 'sophos.xg.interface', + type: 'keyword', + }, + 'sophos.xg.Configuration': { + category: 'sophos', + description: 'Configuration ', + name: 'sophos.xg.Configuration', + type: 'float', + }, + 'sophos.xg.Reports': { + category: 'sophos', + description: 'Reports ', + name: 'sophos.xg.Reports', + type: 'float', + }, + 'sophos.xg.Signature': { + category: 'sophos', + description: 'Signature ', + name: 'sophos.xg.Signature', + type: 'float', + }, + 'sophos.xg.Temp': { + category: 'sophos', + description: 'Temp ', + name: 'sophos.xg.Temp', + type: 'float', + }, + 'sophos.xg.users': { + category: 'sophos', + description: 'users ', + name: 'sophos.xg.users', + type: 'keyword', + }, + 'sophos.xg.ssid': { + category: 'sophos', + description: 'ssid ', + name: 'sophos.xg.ssid', + type: 'keyword', + }, + 'sophos.xg.ap': { + category: 'sophos', + description: 'ap ', + name: 'sophos.xg.ap', + type: 'keyword', + }, + 'sophos.xg.clients_conn_ssid': { + category: 'sophos', + description: 'clients connection ssid ', + name: 'sophos.xg.clients_conn_ssid', + type: 'keyword', + }, + 'suricata.eve.event_type': { + category: 'suricata', + name: 'suricata.eve.event_type', + type: 'keyword', + }, + 'suricata.eve.app_proto_orig': { + category: 'suricata', + name: 'suricata.eve.app_proto_orig', + type: 'keyword', + }, + 'suricata.eve.tcp.tcp_flags': { + category: 'suricata', + name: 'suricata.eve.tcp.tcp_flags', + type: 'keyword', + }, + 'suricata.eve.tcp.psh': { + category: 'suricata', + name: 'suricata.eve.tcp.psh', + type: 'boolean', + }, + 'suricata.eve.tcp.tcp_flags_tc': { + category: 'suricata', + name: 'suricata.eve.tcp.tcp_flags_tc', + type: 'keyword', + }, + 'suricata.eve.tcp.ack': { + category: 'suricata', + name: 'suricata.eve.tcp.ack', + type: 'boolean', + }, + 'suricata.eve.tcp.syn': { + category: 'suricata', + name: 'suricata.eve.tcp.syn', + type: 'boolean', + }, + 'suricata.eve.tcp.state': { + category: 'suricata', + name: 'suricata.eve.tcp.state', + type: 'keyword', + }, + 'suricata.eve.tcp.tcp_flags_ts': { + category: 'suricata', + name: 'suricata.eve.tcp.tcp_flags_ts', + type: 'keyword', + }, + 'suricata.eve.tcp.rst': { + category: 'suricata', + name: 'suricata.eve.tcp.rst', + type: 'boolean', + }, + 'suricata.eve.tcp.fin': { + category: 'suricata', + name: 'suricata.eve.tcp.fin', + type: 'boolean', + }, + 'suricata.eve.fileinfo.sha1': { + category: 'suricata', + name: 'suricata.eve.fileinfo.sha1', + type: 'keyword', + }, + 'suricata.eve.fileinfo.filename': { + category: 'suricata', + name: 'suricata.eve.fileinfo.filename', + type: 'alias', + }, + 'suricata.eve.fileinfo.tx_id': { + category: 'suricata', + name: 'suricata.eve.fileinfo.tx_id', + type: 'long', + }, + 'suricata.eve.fileinfo.state': { + category: 'suricata', + name: 'suricata.eve.fileinfo.state', + type: 'keyword', + }, + 'suricata.eve.fileinfo.stored': { + category: 'suricata', + name: 'suricata.eve.fileinfo.stored', + type: 'boolean', + }, + 'suricata.eve.fileinfo.gaps': { + category: 'suricata', + name: 'suricata.eve.fileinfo.gaps', + type: 'boolean', + }, + 'suricata.eve.fileinfo.sha256': { + category: 'suricata', + name: 'suricata.eve.fileinfo.sha256', + type: 'keyword', + }, + 'suricata.eve.fileinfo.md5': { + category: 'suricata', + name: 'suricata.eve.fileinfo.md5', + type: 'keyword', + }, + 'suricata.eve.fileinfo.size': { + category: 'suricata', + name: 'suricata.eve.fileinfo.size', + type: 'alias', + }, + 'suricata.eve.icmp_type': { + category: 'suricata', + name: 'suricata.eve.icmp_type', + type: 'long', + }, + 'suricata.eve.dest_port': { + category: 'suricata', + name: 'suricata.eve.dest_port', + type: 'alias', + }, + 'suricata.eve.src_port': { + category: 'suricata', + name: 'suricata.eve.src_port', + type: 'alias', + }, + 'suricata.eve.proto': { + category: 'suricata', + name: 'suricata.eve.proto', + type: 'alias', + }, + 'suricata.eve.pcap_cnt': { + category: 'suricata', + name: 'suricata.eve.pcap_cnt', + type: 'long', + }, + 'suricata.eve.src_ip': { + category: 'suricata', + name: 'suricata.eve.src_ip', + type: 'alias', + }, + 'suricata.eve.dns.type': { + category: 'suricata', + name: 'suricata.eve.dns.type', + type: 'keyword', + }, + 'suricata.eve.dns.rrtype': { + category: 'suricata', + name: 'suricata.eve.dns.rrtype', + type: 'keyword', + }, + 'suricata.eve.dns.rrname': { + category: 'suricata', + name: 'suricata.eve.dns.rrname', + type: 'keyword', + }, + 'suricata.eve.dns.rdata': { + category: 'suricata', + name: 'suricata.eve.dns.rdata', + type: 'keyword', + }, + 'suricata.eve.dns.tx_id': { + category: 'suricata', + name: 'suricata.eve.dns.tx_id', + type: 'long', + }, + 'suricata.eve.dns.ttl': { + category: 'suricata', + name: 'suricata.eve.dns.ttl', + type: 'long', + }, + 'suricata.eve.dns.rcode': { + category: 'suricata', + name: 'suricata.eve.dns.rcode', + type: 'keyword', + }, + 'suricata.eve.dns.id': { + category: 'suricata', + name: 'suricata.eve.dns.id', + type: 'long', + }, + 'suricata.eve.flow_id': { + category: 'suricata', + name: 'suricata.eve.flow_id', + type: 'keyword', + }, + 'suricata.eve.email.status': { + category: 'suricata', + name: 'suricata.eve.email.status', + type: 'keyword', + }, + 'suricata.eve.dest_ip': { + category: 'suricata', + name: 'suricata.eve.dest_ip', + type: 'alias', + }, + 'suricata.eve.icmp_code': { + category: 'suricata', + name: 'suricata.eve.icmp_code', + type: 'long', + }, + 'suricata.eve.http.status': { + category: 'suricata', + name: 'suricata.eve.http.status', + type: 'alias', + }, + 'suricata.eve.http.redirect': { + category: 'suricata', + name: 'suricata.eve.http.redirect', + type: 'keyword', + }, + 'suricata.eve.http.http_user_agent': { + category: 'suricata', + name: 'suricata.eve.http.http_user_agent', + type: 'alias', + }, + 'suricata.eve.http.protocol': { + category: 'suricata', + name: 'suricata.eve.http.protocol', + type: 'keyword', + }, + 'suricata.eve.http.http_refer': { + category: 'suricata', + name: 'suricata.eve.http.http_refer', + type: 'alias', + }, + 'suricata.eve.http.url': { + category: 'suricata', + name: 'suricata.eve.http.url', + type: 'alias', + }, + 'suricata.eve.http.hostname': { + category: 'suricata', + name: 'suricata.eve.http.hostname', + type: 'alias', + }, + 'suricata.eve.http.length': { + category: 'suricata', + name: 'suricata.eve.http.length', + type: 'alias', + }, + 'suricata.eve.http.http_method': { + category: 'suricata', + name: 'suricata.eve.http.http_method', + type: 'alias', + }, + 'suricata.eve.http.http_content_type': { + category: 'suricata', + name: 'suricata.eve.http.http_content_type', + type: 'keyword', + }, + 'suricata.eve.timestamp': { + category: 'suricata', + name: 'suricata.eve.timestamp', + type: 'alias', + }, + 'suricata.eve.in_iface': { + category: 'suricata', + name: 'suricata.eve.in_iface', + type: 'keyword', + }, + 'suricata.eve.alert.category': { + category: 'suricata', + name: 'suricata.eve.alert.category', + type: 'keyword', + }, + 'suricata.eve.alert.severity': { + category: 'suricata', + name: 'suricata.eve.alert.severity', + type: 'alias', + }, + 'suricata.eve.alert.rev': { + category: 'suricata', + name: 'suricata.eve.alert.rev', + type: 'long', + }, + 'suricata.eve.alert.gid': { + category: 'suricata', + name: 'suricata.eve.alert.gid', + type: 'long', + }, + 'suricata.eve.alert.signature': { + category: 'suricata', + name: 'suricata.eve.alert.signature', + type: 'keyword', + }, + 'suricata.eve.alert.action': { + category: 'suricata', + name: 'suricata.eve.alert.action', + type: 'alias', + }, + 'suricata.eve.alert.signature_id': { + category: 'suricata', + name: 'suricata.eve.alert.signature_id', + type: 'long', + }, + 'suricata.eve.ssh.client.proto_version': { + category: 'suricata', + name: 'suricata.eve.ssh.client.proto_version', + type: 'keyword', + }, + 'suricata.eve.ssh.client.software_version': { + category: 'suricata', + name: 'suricata.eve.ssh.client.software_version', + type: 'keyword', + }, + 'suricata.eve.ssh.server.proto_version': { + category: 'suricata', + name: 'suricata.eve.ssh.server.proto_version', + type: 'keyword', + }, + 'suricata.eve.ssh.server.software_version': { + category: 'suricata', + name: 'suricata.eve.ssh.server.software_version', + type: 'keyword', + }, + 'suricata.eve.stats.capture.kernel_packets': { + category: 'suricata', + name: 'suricata.eve.stats.capture.kernel_packets', + type: 'long', + }, + 'suricata.eve.stats.capture.kernel_drops': { + category: 'suricata', + name: 'suricata.eve.stats.capture.kernel_drops', + type: 'long', + }, + 'suricata.eve.stats.capture.kernel_ifdrops': { + category: 'suricata', + name: 'suricata.eve.stats.capture.kernel_ifdrops', + type: 'long', + }, + 'suricata.eve.stats.uptime': { + category: 'suricata', + name: 'suricata.eve.stats.uptime', + type: 'long', + }, + 'suricata.eve.stats.detect.alert': { + category: 'suricata', + name: 'suricata.eve.stats.detect.alert', + type: 'long', + }, + 'suricata.eve.stats.http.memcap': { + category: 'suricata', + name: 'suricata.eve.stats.http.memcap', + type: 'long', + }, + 'suricata.eve.stats.http.memuse': { + category: 'suricata', + name: 'suricata.eve.stats.http.memuse', + type: 'long', + }, + 'suricata.eve.stats.file_store.open_files': { + category: 'suricata', + name: 'suricata.eve.stats.file_store.open_files', + type: 'long', + }, + 'suricata.eve.stats.defrag.max_frag_hits': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.max_frag_hits', + type: 'long', + }, + 'suricata.eve.stats.defrag.ipv4.timeouts': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.ipv4.timeouts', + type: 'long', + }, + 'suricata.eve.stats.defrag.ipv4.fragments': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.ipv4.fragments', + type: 'long', + }, + 'suricata.eve.stats.defrag.ipv4.reassembled': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.ipv4.reassembled', + type: 'long', + }, + 'suricata.eve.stats.defrag.ipv6.timeouts': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.ipv6.timeouts', + type: 'long', + }, + 'suricata.eve.stats.defrag.ipv6.fragments': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.ipv6.fragments', + type: 'long', + }, + 'suricata.eve.stats.defrag.ipv6.reassembled': { + category: 'suricata', + name: 'suricata.eve.stats.defrag.ipv6.reassembled', + type: 'long', + }, + 'suricata.eve.stats.flow.tcp_reuse': { + category: 'suricata', + name: 'suricata.eve.stats.flow.tcp_reuse', + type: 'long', + }, + 'suricata.eve.stats.flow.udp': { + category: 'suricata', + name: 'suricata.eve.stats.flow.udp', + type: 'long', + }, + 'suricata.eve.stats.flow.memcap': { + category: 'suricata', + name: 'suricata.eve.stats.flow.memcap', + type: 'long', + }, + 'suricata.eve.stats.flow.emerg_mode_entered': { + category: 'suricata', + name: 'suricata.eve.stats.flow.emerg_mode_entered', + type: 'long', + }, + 'suricata.eve.stats.flow.emerg_mode_over': { + category: 'suricata', + name: 'suricata.eve.stats.flow.emerg_mode_over', + type: 'long', + }, + 'suricata.eve.stats.flow.tcp': { + category: 'suricata', + name: 'suricata.eve.stats.flow.tcp', + type: 'long', + }, + 'suricata.eve.stats.flow.icmpv6': { + category: 'suricata', + name: 'suricata.eve.stats.flow.icmpv6', + type: 'long', + }, + 'suricata.eve.stats.flow.icmpv4': { + category: 'suricata', + name: 'suricata.eve.stats.flow.icmpv4', + type: 'long', + }, + 'suricata.eve.stats.flow.spare': { + category: 'suricata', + name: 'suricata.eve.stats.flow.spare', + type: 'long', + }, + 'suricata.eve.stats.flow.memuse': { + category: 'suricata', + name: 'suricata.eve.stats.flow.memuse', + type: 'long', + }, + 'suricata.eve.stats.tcp.pseudo_failed': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.pseudo_failed', + type: 'long', + }, + 'suricata.eve.stats.tcp.ssn_memcap_drop': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.ssn_memcap_drop', + type: 'long', + }, + 'suricata.eve.stats.tcp.insert_data_overlap_fail': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.insert_data_overlap_fail', + type: 'long', + }, + 'suricata.eve.stats.tcp.sessions': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.sessions', + type: 'long', + }, + 'suricata.eve.stats.tcp.pseudo': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.pseudo', + type: 'long', + }, + 'suricata.eve.stats.tcp.synack': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.synack', + type: 'long', + }, + 'suricata.eve.stats.tcp.insert_data_normal_fail': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.insert_data_normal_fail', + type: 'long', + }, + 'suricata.eve.stats.tcp.syn': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.syn', + type: 'long', + }, + 'suricata.eve.stats.tcp.memuse': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.memuse', + type: 'long', + }, + 'suricata.eve.stats.tcp.invalid_checksum': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.invalid_checksum', + type: 'long', + }, + 'suricata.eve.stats.tcp.segment_memcap_drop': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.segment_memcap_drop', + type: 'long', + }, + 'suricata.eve.stats.tcp.overlap': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.overlap', + type: 'long', + }, + 'suricata.eve.stats.tcp.insert_list_fail': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.insert_list_fail', + type: 'long', + }, + 'suricata.eve.stats.tcp.rst': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.rst', + type: 'long', + }, + 'suricata.eve.stats.tcp.stream_depth_reached': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.stream_depth_reached', + type: 'long', + }, + 'suricata.eve.stats.tcp.reassembly_memuse': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.reassembly_memuse', + type: 'long', + }, + 'suricata.eve.stats.tcp.reassembly_gap': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.reassembly_gap', + type: 'long', + }, + 'suricata.eve.stats.tcp.overlap_diff_data': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.overlap_diff_data', + type: 'long', + }, + 'suricata.eve.stats.tcp.no_flow': { + category: 'suricata', + name: 'suricata.eve.stats.tcp.no_flow', + type: 'long', + }, + 'suricata.eve.stats.decoder.avg_pkt_size': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.avg_pkt_size', + type: 'long', + }, + 'suricata.eve.stats.decoder.bytes': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.bytes', + type: 'long', + }, + 'suricata.eve.stats.decoder.tcp': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.tcp', + type: 'long', + }, + 'suricata.eve.stats.decoder.raw': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.raw', + type: 'long', + }, + 'suricata.eve.stats.decoder.ppp': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ppp', + type: 'long', + }, + 'suricata.eve.stats.decoder.vlan_qinq': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.vlan_qinq', + type: 'long', + }, + 'suricata.eve.stats.decoder.null': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.null', + type: 'long', + }, + 'suricata.eve.stats.decoder.ltnull.unsupported_type': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ltnull.unsupported_type', + type: 'long', + }, + 'suricata.eve.stats.decoder.ltnull.pkt_too_small': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ltnull.pkt_too_small', + type: 'long', + }, + 'suricata.eve.stats.decoder.invalid': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.invalid', + type: 'long', + }, + 'suricata.eve.stats.decoder.gre': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.gre', + type: 'long', + }, + 'suricata.eve.stats.decoder.ipv4': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ipv4', + type: 'long', + }, + 'suricata.eve.stats.decoder.ipv6': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ipv6', + type: 'long', + }, + 'suricata.eve.stats.decoder.pkts': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.pkts', + type: 'long', + }, + 'suricata.eve.stats.decoder.ipv6_in_ipv6': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ipv6_in_ipv6', + type: 'long', + }, + 'suricata.eve.stats.decoder.ipraw.invalid_ip_version': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ipraw.invalid_ip_version', + type: 'long', + }, + 'suricata.eve.stats.decoder.pppoe': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.pppoe', + type: 'long', + }, + 'suricata.eve.stats.decoder.udp': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.udp', + type: 'long', + }, + 'suricata.eve.stats.decoder.dce.pkt_too_small': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.dce.pkt_too_small', + type: 'long', + }, + 'suricata.eve.stats.decoder.vlan': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.vlan', + type: 'long', + }, + 'suricata.eve.stats.decoder.sctp': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.sctp', + type: 'long', + }, + 'suricata.eve.stats.decoder.max_pkt_size': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.max_pkt_size', + type: 'long', + }, + 'suricata.eve.stats.decoder.teredo': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.teredo', + type: 'long', + }, + 'suricata.eve.stats.decoder.mpls': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.mpls', + type: 'long', + }, + 'suricata.eve.stats.decoder.sll': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.sll', + type: 'long', + }, + 'suricata.eve.stats.decoder.icmpv6': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.icmpv6', + type: 'long', + }, + 'suricata.eve.stats.decoder.icmpv4': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.icmpv4', + type: 'long', + }, + 'suricata.eve.stats.decoder.erspan': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.erspan', + type: 'long', + }, + 'suricata.eve.stats.decoder.ethernet': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ethernet', + type: 'long', + }, + 'suricata.eve.stats.decoder.ipv4_in_ipv6': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ipv4_in_ipv6', + type: 'long', + }, + 'suricata.eve.stats.decoder.ieee8021ah': { + category: 'suricata', + name: 'suricata.eve.stats.decoder.ieee8021ah', + type: 'long', + }, + 'suricata.eve.stats.dns.memcap_global': { + category: 'suricata', + name: 'suricata.eve.stats.dns.memcap_global', + type: 'long', + }, + 'suricata.eve.stats.dns.memcap_state': { + category: 'suricata', + name: 'suricata.eve.stats.dns.memcap_state', + type: 'long', + }, + 'suricata.eve.stats.dns.memuse': { + category: 'suricata', + name: 'suricata.eve.stats.dns.memuse', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.rows_busy': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.rows_busy', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.flows_timeout': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.flows_timeout', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.flows_notimeout': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.flows_notimeout', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.rows_skipped': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.rows_skipped', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.closed_pruned': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.closed_pruned', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.new_pruned': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.new_pruned', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.flows_removed': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.flows_removed', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.bypassed_pruned': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.bypassed_pruned', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.est_pruned': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.est_pruned', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.flows_timeout_inuse': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.flows_timeout_inuse', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.flows_checked': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.flows_checked', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.rows_maxlen': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.rows_maxlen', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.rows_checked': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.rows_checked', + type: 'long', + }, + 'suricata.eve.stats.flow_mgr.rows_empty': { + category: 'suricata', + name: 'suricata.eve.stats.flow_mgr.rows_empty', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.tls': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.tls', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.ftp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.ftp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.http': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.http', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.failed_udp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.failed_udp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.dns_udp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.dns_udp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.dns_tcp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.dns_tcp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.smtp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.smtp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.failed_tcp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.failed_tcp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.msn': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.msn', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.ssh': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.ssh', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.imap': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.imap', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.dcerpc_udp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.dcerpc_udp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.dcerpc_tcp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.dcerpc_tcp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.flow.smb': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.flow.smb', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.tls': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.tls', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.ftp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.ftp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.http': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.http', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.dns_udp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.dns_udp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.dns_tcp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.dns_tcp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.smtp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.smtp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.ssh': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.ssh', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.dcerpc_udp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.dcerpc_udp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.dcerpc_tcp': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.dcerpc_tcp', + type: 'long', + }, + 'suricata.eve.stats.app_layer.tx.smb': { + category: 'suricata', + name: 'suricata.eve.stats.app_layer.tx.smb', + type: 'long', + }, + 'suricata.eve.tls.notbefore': { + category: 'suricata', + name: 'suricata.eve.tls.notbefore', + type: 'date', + }, + 'suricata.eve.tls.issuerdn': { + category: 'suricata', + name: 'suricata.eve.tls.issuerdn', + type: 'keyword', + }, + 'suricata.eve.tls.sni': { + category: 'suricata', + name: 'suricata.eve.tls.sni', + type: 'keyword', + }, + 'suricata.eve.tls.version': { + category: 'suricata', + name: 'suricata.eve.tls.version', + type: 'keyword', + }, + 'suricata.eve.tls.session_resumed': { + category: 'suricata', + name: 'suricata.eve.tls.session_resumed', + type: 'boolean', + }, + 'suricata.eve.tls.fingerprint': { + category: 'suricata', + name: 'suricata.eve.tls.fingerprint', + type: 'keyword', + }, + 'suricata.eve.tls.serial': { + category: 'suricata', + name: 'suricata.eve.tls.serial', + type: 'keyword', + }, + 'suricata.eve.tls.notafter': { + category: 'suricata', + name: 'suricata.eve.tls.notafter', + type: 'date', + }, + 'suricata.eve.tls.subject': { + category: 'suricata', + name: 'suricata.eve.tls.subject', + type: 'keyword', + }, + 'suricata.eve.tls.ja3s.string': { + category: 'suricata', + name: 'suricata.eve.tls.ja3s.string', + type: 'keyword', + }, + 'suricata.eve.tls.ja3s.hash': { + category: 'suricata', + name: 'suricata.eve.tls.ja3s.hash', + type: 'keyword', + }, + 'suricata.eve.tls.ja3.string': { + category: 'suricata', + name: 'suricata.eve.tls.ja3.string', + type: 'keyword', + }, + 'suricata.eve.tls.ja3.hash': { + category: 'suricata', + name: 'suricata.eve.tls.ja3.hash', + type: 'keyword', + }, + 'suricata.eve.app_proto_ts': { + category: 'suricata', + name: 'suricata.eve.app_proto_ts', + type: 'keyword', + }, + 'suricata.eve.flow.bytes_toclient': { + category: 'suricata', + name: 'suricata.eve.flow.bytes_toclient', + type: 'alias', + }, + 'suricata.eve.flow.start': { + category: 'suricata', + name: 'suricata.eve.flow.start', + type: 'alias', + }, + 'suricata.eve.flow.pkts_toclient': { + category: 'suricata', + name: 'suricata.eve.flow.pkts_toclient', + type: 'alias', + }, + 'suricata.eve.flow.age': { + category: 'suricata', + name: 'suricata.eve.flow.age', + type: 'long', + }, + 'suricata.eve.flow.state': { + category: 'suricata', + name: 'suricata.eve.flow.state', + type: 'keyword', + }, + 'suricata.eve.flow.bytes_toserver': { + category: 'suricata', + name: 'suricata.eve.flow.bytes_toserver', + type: 'alias', + }, + 'suricata.eve.flow.reason': { + category: 'suricata', + name: 'suricata.eve.flow.reason', + type: 'keyword', + }, + 'suricata.eve.flow.pkts_toserver': { + category: 'suricata', + name: 'suricata.eve.flow.pkts_toserver', + type: 'alias', + }, + 'suricata.eve.flow.end': { + category: 'suricata', + name: 'suricata.eve.flow.end', + type: 'date', + }, + 'suricata.eve.flow.alerted': { + category: 'suricata', + name: 'suricata.eve.flow.alerted', + type: 'boolean', + }, + 'suricata.eve.app_proto': { + category: 'suricata', + name: 'suricata.eve.app_proto', + type: 'alias', + }, + 'suricata.eve.tx_id': { + category: 'suricata', + name: 'suricata.eve.tx_id', + type: 'long', + }, + 'suricata.eve.app_proto_tc': { + category: 'suricata', + name: 'suricata.eve.app_proto_tc', + type: 'keyword', + }, + 'suricata.eve.smtp.rcpt_to': { + category: 'suricata', + name: 'suricata.eve.smtp.rcpt_to', + type: 'keyword', + }, + 'suricata.eve.smtp.mail_from': { + category: 'suricata', + name: 'suricata.eve.smtp.mail_from', + type: 'keyword', + }, + 'suricata.eve.smtp.helo': { + category: 'suricata', + name: 'suricata.eve.smtp.helo', + type: 'keyword', + }, + 'suricata.eve.app_proto_expected': { + category: 'suricata', + name: 'suricata.eve.app_proto_expected', + type: 'keyword', + }, + 'suricata.eve.flags': { + category: 'suricata', + name: 'suricata.eve.flags', + type: 'group', + }, + 'zeek.session_id': { + category: 'zeek', + description: 'A unique identifier of the session ', + name: 'zeek.session_id', + type: 'keyword', + }, + 'zeek.capture_loss.ts_delta': { + category: 'zeek', + description: 'The time delay between this measurement and the last. ', + name: 'zeek.capture_loss.ts_delta', + type: 'integer', + }, + 'zeek.capture_loss.peer': { + category: 'zeek', + description: + 'In the event that there are multiple Bro instances logging to the same host, this distinguishes each peer with its individual name. ', + name: 'zeek.capture_loss.peer', + type: 'keyword', + }, + 'zeek.capture_loss.gaps': { + category: 'zeek', + description: 'Number of missed ACKs from the previous measurement interval. ', + name: 'zeek.capture_loss.gaps', + type: 'integer', + }, + 'zeek.capture_loss.acks': { + category: 'zeek', + description: 'Total number of ACKs seen in the previous measurement interval. ', + name: 'zeek.capture_loss.acks', + type: 'integer', + }, + 'zeek.capture_loss.percent_lost': { + category: 'zeek', + description: "Percentage of ACKs seen where the data being ACKed wasn't seen. ", + name: 'zeek.capture_loss.percent_lost', + type: 'double', + }, + 'zeek.connection.local_orig': { + category: 'zeek', + description: 'Indicates whether the session is originated locally. ', + name: 'zeek.connection.local_orig', + type: 'boolean', + }, + 'zeek.connection.local_resp': { + category: 'zeek', + description: 'Indicates whether the session is responded locally. ', + name: 'zeek.connection.local_resp', + type: 'boolean', + }, + 'zeek.connection.missed_bytes': { + category: 'zeek', + description: 'Missed bytes for the session. ', + name: 'zeek.connection.missed_bytes', + type: 'long', + }, + 'zeek.connection.state': { + category: 'zeek', + description: 'Code indicating the state of the session. ', + name: 'zeek.connection.state', + type: 'keyword', + }, + 'zeek.connection.state_message': { + category: 'zeek', + description: 'The state of the session. ', + name: 'zeek.connection.state_message', + type: 'keyword', + }, + 'zeek.connection.icmp.type': { + category: 'zeek', + description: 'ICMP message type. ', + name: 'zeek.connection.icmp.type', + type: 'integer', + }, + 'zeek.connection.icmp.code': { + category: 'zeek', + description: 'ICMP message code. ', + name: 'zeek.connection.icmp.code', + type: 'integer', + }, + 'zeek.connection.history': { + category: 'zeek', + description: 'Flags indicating the history of the session. ', + name: 'zeek.connection.history', + type: 'keyword', + }, + 'zeek.connection.vlan': { + category: 'zeek', + description: 'VLAN identifier. ', + name: 'zeek.connection.vlan', + type: 'integer', + }, + 'zeek.connection.inner_vlan': { + category: 'zeek', + description: 'VLAN identifier. ', + name: 'zeek.connection.inner_vlan', + type: 'integer', + }, + 'zeek.dce_rpc.rtt': { + category: 'zeek', + description: + "Round trip time from the request to the response. If either the request or response wasn't seen, this will be null. ", + name: 'zeek.dce_rpc.rtt', + type: 'integer', + }, + 'zeek.dce_rpc.named_pipe': { + category: 'zeek', + description: 'Remote pipe name. ', + name: 'zeek.dce_rpc.named_pipe', + type: 'keyword', + }, + 'zeek.dce_rpc.endpoint': { + category: 'zeek', + description: 'Endpoint name looked up from the uuid. ', + name: 'zeek.dce_rpc.endpoint', + type: 'keyword', + }, + 'zeek.dce_rpc.operation': { + category: 'zeek', + description: 'Operation seen in the call. ', + name: 'zeek.dce_rpc.operation', + type: 'keyword', + }, + 'zeek.dhcp.domain': { + category: 'zeek', + description: 'Domain given by the server in option 15. ', + name: 'zeek.dhcp.domain', + type: 'keyword', + }, + 'zeek.dhcp.duration': { + category: 'zeek', + description: + 'Duration of the DHCP session representing the time from the first message to the last, in seconds. ', + name: 'zeek.dhcp.duration', + type: 'double', + }, + 'zeek.dhcp.hostname': { + category: 'zeek', + description: 'Name given by client in Hostname option 12. ', + name: 'zeek.dhcp.hostname', + type: 'keyword', + }, + 'zeek.dhcp.client_fqdn': { + category: 'zeek', + description: 'FQDN given by client in Client FQDN option 81. ', + name: 'zeek.dhcp.client_fqdn', + type: 'keyword', + }, + 'zeek.dhcp.lease_time': { + category: 'zeek', + description: 'IP address lease interval in seconds. ', + name: 'zeek.dhcp.lease_time', + type: 'integer', + }, + 'zeek.dhcp.address.assigned': { + category: 'zeek', + description: 'IP address assigned by the server. ', + name: 'zeek.dhcp.address.assigned', + type: 'ip', + }, + 'zeek.dhcp.address.client': { + category: 'zeek', + description: + 'IP address of the client. If a transaction is only a client sending INFORM messages then there is no lease information exchanged so this is helpful to know who sent the messages. Getting an address in this field does require that the client sources at least one DHCP message using a non-broadcast address. ', + name: 'zeek.dhcp.address.client', + type: 'ip', + }, + 'zeek.dhcp.address.mac': { + category: 'zeek', + description: "Client's hardware address. ", + name: 'zeek.dhcp.address.mac', + type: 'keyword', + }, + 'zeek.dhcp.address.requested': { + category: 'zeek', + description: 'IP address requested by the client. ', + name: 'zeek.dhcp.address.requested', + type: 'ip', + }, + 'zeek.dhcp.address.server': { + category: 'zeek', + description: 'IP address of the DHCP server. ', + name: 'zeek.dhcp.address.server', + type: 'ip', + }, + 'zeek.dhcp.msg.types': { + category: 'zeek', + description: 'List of DHCP message types seen in this exchange. ', + name: 'zeek.dhcp.msg.types', + type: 'keyword', + }, + 'zeek.dhcp.msg.origin': { + category: 'zeek', + description: + '(present if policy/protocols/dhcp/msg-orig.bro is loaded) The address that originated each message from the msg.types field. ', + name: 'zeek.dhcp.msg.origin', + type: 'ip', + }, + 'zeek.dhcp.msg.client': { + category: 'zeek', + description: + 'Message typically accompanied with a DHCP_DECLINE so the client can tell the server why it rejected an address. ', + name: 'zeek.dhcp.msg.client', + type: 'keyword', + }, + 'zeek.dhcp.msg.server': { + category: 'zeek', + description: + 'Message typically accompanied with a DHCP_NAK to let the client know why it rejected the request. ', + name: 'zeek.dhcp.msg.server', + type: 'keyword', + }, + 'zeek.dhcp.software.client': { + category: 'zeek', + description: + '(present if policy/protocols/dhcp/software.bro is loaded) Software reported by the client in the vendor_class option. ', + name: 'zeek.dhcp.software.client', + type: 'keyword', + }, + 'zeek.dhcp.software.server': { + category: 'zeek', + description: + '(present if policy/protocols/dhcp/software.bro is loaded) Software reported by the client in the vendor_class option. ', + name: 'zeek.dhcp.software.server', + type: 'keyword', + }, + 'zeek.dhcp.id.circuit': { + category: 'zeek', + description: + '(present if policy/protocols/dhcp/sub-opts.bro is loaded) Added by DHCP relay agents which terminate switched or permanent circuits. It encodes an agent-local identifier of the circuit from which a DHCP client-to-server packet was received. Typically it should represent a router or switch interface number. ', + name: 'zeek.dhcp.id.circuit', + type: 'keyword', + }, + 'zeek.dhcp.id.remote_agent': { + category: 'zeek', + description: + '(present if policy/protocols/dhcp/sub-opts.bro is loaded) A globally unique identifier added by relay agents to identify the remote host end of the circuit. ', + name: 'zeek.dhcp.id.remote_agent', + type: 'keyword', + }, + 'zeek.dhcp.id.subscriber': { + category: 'zeek', + description: + "(present if policy/protocols/dhcp/sub-opts.bro is loaded) The subscriber ID is a value independent of the physical network configuration so that a customer's DHCP configuration can be given to them correctly no matter where they are physically connected. ", + name: 'zeek.dhcp.id.subscriber', + type: 'keyword', + }, + 'zeek.dnp3.function.request': { + category: 'zeek', + description: 'The name of the function message in the request. ', + name: 'zeek.dnp3.function.request', + type: 'keyword', + }, + 'zeek.dnp3.function.reply': { + category: 'zeek', + description: 'The name of the function message in the reply. ', + name: 'zeek.dnp3.function.reply', + type: 'keyword', + }, + 'zeek.dnp3.id': { + category: 'zeek', + description: "The response's internal indication number. ", + name: 'zeek.dnp3.id', + type: 'integer', + }, + 'zeek.dns.trans_id': { + category: 'zeek', + description: 'DNS transaction identifier. ', + name: 'zeek.dns.trans_id', + type: 'keyword', + }, + 'zeek.dns.rtt': { + category: 'zeek', + description: 'Round trip time for the query and response. ', + name: 'zeek.dns.rtt', + type: 'double', + }, + 'zeek.dns.query': { + category: 'zeek', + description: 'The domain name that is the subject of the DNS query. ', + name: 'zeek.dns.query', + type: 'keyword', + }, + 'zeek.dns.qclass': { + category: 'zeek', + description: 'The QCLASS value specifying the class of the query. ', + name: 'zeek.dns.qclass', + type: 'long', + }, + 'zeek.dns.qclass_name': { + category: 'zeek', + description: 'A descriptive name for the class of the query. ', + name: 'zeek.dns.qclass_name', + type: 'keyword', + }, + 'zeek.dns.qtype': { + category: 'zeek', + description: 'A QTYPE value specifying the type of the query. ', + name: 'zeek.dns.qtype', + type: 'long', + }, + 'zeek.dns.qtype_name': { + category: 'zeek', + description: 'A descriptive name for the type of the query. ', + name: 'zeek.dns.qtype_name', + type: 'keyword', + }, + 'zeek.dns.rcode': { + category: 'zeek', + description: 'The response code value in DNS response messages. ', + name: 'zeek.dns.rcode', + type: 'long', + }, + 'zeek.dns.rcode_name': { + category: 'zeek', + description: 'A descriptive name for the response code value. ', + name: 'zeek.dns.rcode_name', + type: 'keyword', + }, + 'zeek.dns.AA': { + category: 'zeek', + description: + 'The Authoritative Answer bit for response messages specifies that the responding name server is an authority for the domain name in the question section. ', + name: 'zeek.dns.AA', + type: 'boolean', + }, + 'zeek.dns.TC': { + category: 'zeek', + description: 'The Truncation bit specifies that the message was truncated. ', + name: 'zeek.dns.TC', + type: 'boolean', + }, + 'zeek.dns.RD': { + category: 'zeek', + description: + 'The Recursion Desired bit in a request message indicates that the client wants recursive service for this query. ', + name: 'zeek.dns.RD', + type: 'boolean', + }, + 'zeek.dns.RA': { + category: 'zeek', + description: + 'The Recursion Available bit in a response message indicates that the name server supports recursive queries. ', + name: 'zeek.dns.RA', + type: 'boolean', + }, + 'zeek.dns.answers': { + category: 'zeek', + description: 'The set of resource descriptions in the query answer. ', + name: 'zeek.dns.answers', + type: 'keyword', + }, + 'zeek.dns.TTLs': { + category: 'zeek', + description: 'The caching intervals of the associated RRs described by the answers field. ', + name: 'zeek.dns.TTLs', + type: 'double', + }, + 'zeek.dns.rejected': { + category: 'zeek', + description: 'Indicates whether the DNS query was rejected by the server. ', + name: 'zeek.dns.rejected', + type: 'boolean', + }, + 'zeek.dns.total_answers': { + category: 'zeek', + description: 'The total number of resource records in the reply. ', + name: 'zeek.dns.total_answers', + type: 'integer', + }, + 'zeek.dns.total_replies': { + category: 'zeek', + description: 'The total number of resource records in the reply message. ', + name: 'zeek.dns.total_replies', + type: 'integer', + }, + 'zeek.dns.saw_query': { + category: 'zeek', + description: 'Whether the full DNS query has been seen. ', + name: 'zeek.dns.saw_query', + type: 'boolean', + }, + 'zeek.dns.saw_reply': { + category: 'zeek', + description: 'Whether the full DNS reply has been seen. ', + name: 'zeek.dns.saw_reply', + type: 'boolean', + }, + 'zeek.dpd.analyzer': { + category: 'zeek', + description: 'The analyzer that generated the violation. ', + name: 'zeek.dpd.analyzer', + type: 'keyword', + }, + 'zeek.dpd.failure_reason': { + category: 'zeek', + description: 'The textual reason for the analysis failure. ', + name: 'zeek.dpd.failure_reason', + type: 'keyword', + }, + 'zeek.dpd.packet_segment': { + category: 'zeek', + description: + '(present if policy/frameworks/dpd/packet-segment-logging.bro is loaded) A chunk of the payload that most likely resulted in the protocol violation. ', + name: 'zeek.dpd.packet_segment', + type: 'keyword', + }, + 'zeek.files.fuid': { + category: 'zeek', + description: 'A file unique identifier. ', + name: 'zeek.files.fuid', + type: 'keyword', + }, + 'zeek.files.tx_host': { + category: 'zeek', + description: 'The host that transferred the file. ', + name: 'zeek.files.tx_host', + type: 'ip', + }, + 'zeek.files.rx_host': { + category: 'zeek', + description: 'The host that received the file. ', + name: 'zeek.files.rx_host', + type: 'ip', + }, + 'zeek.files.session_ids': { + category: 'zeek', + description: 'The sessions that have this file. ', + name: 'zeek.files.session_ids', + type: 'keyword', + }, + 'zeek.files.source': { + category: 'zeek', + description: + 'An identification of the source of the file data. E.g. it may be a network protocol over which it was transferred, or a local file path which was read, or some other input source. ', + name: 'zeek.files.source', + type: 'keyword', + }, + 'zeek.files.depth': { + category: 'zeek', + description: + 'A value to represent the depth of this file in relation to its source. In SMTP, it is the depth of the MIME attachment on the message. In HTTP, it is the depth of the request within the TCP connection. ', + name: 'zeek.files.depth', + type: 'long', + }, + 'zeek.files.analyzers': { + category: 'zeek', + description: 'A set of analysis types done during the file analysis. ', + name: 'zeek.files.analyzers', + type: 'keyword', + }, + 'zeek.files.mime_type': { + category: 'zeek', + description: 'Mime type of the file. ', + name: 'zeek.files.mime_type', + type: 'keyword', + }, + 'zeek.files.filename': { + category: 'zeek', + description: 'Name of the file if available. ', + name: 'zeek.files.filename', + type: 'keyword', + }, + 'zeek.files.local_orig': { + category: 'zeek', + description: + 'If the source of this file is a network connection, this field indicates if the data originated from the local network or not. ', + name: 'zeek.files.local_orig', + type: 'boolean', + }, + 'zeek.files.is_orig': { + category: 'zeek', + description: + 'If the source of this file is a network connection, this field indicates if the file is being sent by the originator of the connection or the responder. ', + name: 'zeek.files.is_orig', + type: 'boolean', + }, + 'zeek.files.duration': { + category: 'zeek', + description: 'The duration the file was analyzed for. Not the duration of the session. ', + name: 'zeek.files.duration', + type: 'double', + }, + 'zeek.files.seen_bytes': { + category: 'zeek', + description: 'Number of bytes provided to the file analysis engine for the file. ', + name: 'zeek.files.seen_bytes', + type: 'long', + }, + 'zeek.files.total_bytes': { + category: 'zeek', + description: 'Total number of bytes that are supposed to comprise the full file. ', + name: 'zeek.files.total_bytes', + type: 'long', + }, + 'zeek.files.missing_bytes': { + category: 'zeek', + description: + 'The number of bytes in the file stream that were completely missed during the process of analysis. ', + name: 'zeek.files.missing_bytes', + type: 'long', + }, + 'zeek.files.overflow_bytes': { + category: 'zeek', + description: + "The number of bytes in the file stream that were not delivered to stream file analyzers. This could be overlapping bytes or bytes that couldn't be reassembled. ", + name: 'zeek.files.overflow_bytes', + type: 'long', + }, + 'zeek.files.timedout': { + category: 'zeek', + description: 'Whether the file analysis timed out at least once for the file. ', + name: 'zeek.files.timedout', + type: 'boolean', + }, + 'zeek.files.parent_fuid': { + category: 'zeek', + description: + 'Identifier associated with a container file from which this one was extracted as part of the file analysis. ', + name: 'zeek.files.parent_fuid', + type: 'keyword', + }, + 'zeek.files.md5': { + category: 'zeek', + description: 'An MD5 digest of the file contents. ', + name: 'zeek.files.md5', + type: 'keyword', + }, + 'zeek.files.sha1': { + category: 'zeek', + description: 'A SHA1 digest of the file contents. ', + name: 'zeek.files.sha1', + type: 'keyword', + }, + 'zeek.files.sha256': { + category: 'zeek', + description: 'A SHA256 digest of the file contents. ', + name: 'zeek.files.sha256', + type: 'keyword', + }, + 'zeek.files.extracted': { + category: 'zeek', + description: 'Local filename of extracted file. ', + name: 'zeek.files.extracted', + type: 'keyword', + }, + 'zeek.files.extracted_cutoff': { + category: 'zeek', + description: + 'Indicate whether the file being extracted was cut off hence not extracted completely. ', + name: 'zeek.files.extracted_cutoff', + type: 'boolean', + }, + 'zeek.files.extracted_size': { + category: 'zeek', + description: 'The number of bytes extracted to disk. ', + name: 'zeek.files.extracted_size', + type: 'long', + }, + 'zeek.files.entropy': { + category: 'zeek', + description: 'The information density of the contents of the file. ', + name: 'zeek.files.entropy', + type: 'double', + }, + 'zeek.ftp.user': { + category: 'zeek', + description: 'User name for the current FTP session. ', + name: 'zeek.ftp.user', + type: 'keyword', + }, + 'zeek.ftp.password': { + category: 'zeek', + description: 'Password for the current FTP session if captured. ', + name: 'zeek.ftp.password', + type: 'keyword', + }, + 'zeek.ftp.command': { + category: 'zeek', + description: 'Command given by the client. ', + name: 'zeek.ftp.command', + type: 'keyword', + }, + 'zeek.ftp.arg': { + category: 'zeek', + description: 'Argument for the command if one is given. ', + name: 'zeek.ftp.arg', + type: 'keyword', + }, + 'zeek.ftp.file.size': { + category: 'zeek', + description: 'Size of the file if the command indicates a file transfer. ', + name: 'zeek.ftp.file.size', + type: 'long', + }, + 'zeek.ftp.file.mime_type': { + category: 'zeek', + description: 'Sniffed mime type of file. ', + name: 'zeek.ftp.file.mime_type', + type: 'keyword', + }, + 'zeek.ftp.file.fuid': { + category: 'zeek', + description: '(present if base/protocols/ftp/files.bro is loaded) File unique ID. ', + name: 'zeek.ftp.file.fuid', + type: 'keyword', + }, + 'zeek.ftp.reply.code': { + category: 'zeek', + description: 'Reply code from the server in response to the command. ', + name: 'zeek.ftp.reply.code', + type: 'integer', + }, + 'zeek.ftp.reply.msg': { + category: 'zeek', + description: 'Reply message from the server in response to the command. ', + name: 'zeek.ftp.reply.msg', + type: 'keyword', + }, + 'zeek.ftp.data_channel.passive': { + category: 'zeek', + description: 'Whether PASV mode is toggled for control channel. ', + name: 'zeek.ftp.data_channel.passive', + type: 'boolean', + }, + 'zeek.ftp.data_channel.originating_host': { + category: 'zeek', + description: 'The host that will be initiating the data connection. ', + name: 'zeek.ftp.data_channel.originating_host', + type: 'ip', + }, + 'zeek.ftp.data_channel.response_host': { + category: 'zeek', + description: 'The host that will be accepting the data connection. ', + name: 'zeek.ftp.data_channel.response_host', + type: 'ip', + }, + 'zeek.ftp.data_channel.response_port': { + category: 'zeek', + description: 'The port at which the acceptor is listening for the data connection. ', + name: 'zeek.ftp.data_channel.response_port', + type: 'integer', + }, + 'zeek.ftp.cwd': { + category: 'zeek', + description: + "Current working directory that this session is in. By making the default value '.', we can indicate that unless something more concrete is discovered that the existing but unknown directory is ok to use. ", + name: 'zeek.ftp.cwd', + type: 'keyword', + }, + 'zeek.ftp.cmdarg.cmd': { + category: 'zeek', + description: 'Command. ', + name: 'zeek.ftp.cmdarg.cmd', + type: 'keyword', + }, + 'zeek.ftp.cmdarg.arg': { + category: 'zeek', + description: 'Argument for the command if one was given. ', + name: 'zeek.ftp.cmdarg.arg', + type: 'keyword', + }, + 'zeek.ftp.cmdarg.seq': { + category: 'zeek', + description: 'Counter to track how many commands have been executed. ', + name: 'zeek.ftp.cmdarg.seq', + type: 'integer', + }, + 'zeek.ftp.pending_commands': { + category: 'zeek', + description: + 'Queue for commands that have been sent but not yet responded to are tracked here. ', + name: 'zeek.ftp.pending_commands', + type: 'integer', + }, + 'zeek.ftp.passive': { + category: 'zeek', + description: 'Indicates if the session is in active or passive mode. ', + name: 'zeek.ftp.passive', + type: 'boolean', + }, + 'zeek.ftp.capture_password': { + category: 'zeek', + description: 'Determines if the password will be captured for this request. ', + name: 'zeek.ftp.capture_password', + type: 'boolean', + }, + 'zeek.ftp.last_auth_requested': { + category: 'zeek', + description: + 'present if base/protocols/ftp/gridftp.bro is loaded. Last authentication/security mechanism that was used. ', + name: 'zeek.ftp.last_auth_requested', + type: 'keyword', + }, + 'zeek.http.trans_depth': { + category: 'zeek', + description: + 'Represents the pipelined depth into the connection of this request/response transaction. ', + name: 'zeek.http.trans_depth', + type: 'integer', + }, + 'zeek.http.status_msg': { + category: 'zeek', + description: 'Status message returned by the server. ', + name: 'zeek.http.status_msg', + type: 'keyword', + }, + 'zeek.http.info_code': { + category: 'zeek', + description: 'Last seen 1xx informational reply code returned by the server. ', + name: 'zeek.http.info_code', + type: 'integer', + }, + 'zeek.http.info_msg': { + category: 'zeek', + description: 'Last seen 1xx informational reply message returned by the server. ', + name: 'zeek.http.info_msg', + type: 'keyword', + }, + 'zeek.http.tags': { + category: 'zeek', + description: + 'A set of indicators of various attributes discovered and related to a particular request/response pair. ', + name: 'zeek.http.tags', + type: 'keyword', + }, + 'zeek.http.password': { + category: 'zeek', + description: 'Password if basic-auth is performed for the request. ', + name: 'zeek.http.password', + type: 'keyword', + }, + 'zeek.http.captured_password': { + category: 'zeek', + description: 'Determines if the password will be captured for this request. ', + name: 'zeek.http.captured_password', + type: 'boolean', + }, + 'zeek.http.proxied': { + category: 'zeek', + description: 'All of the headers that may indicate if the HTTP request was proxied. ', + name: 'zeek.http.proxied', + type: 'keyword', + }, + 'zeek.http.range_request': { + category: 'zeek', + description: 'Indicates if this request can assume 206 partial content in response. ', + name: 'zeek.http.range_request', + type: 'boolean', + }, + 'zeek.http.client_header_names': { + category: 'zeek', + description: + 'The vector of HTTP header names sent by the client. No header values are included here, just the header names. ', + name: 'zeek.http.client_header_names', + type: 'keyword', + }, + 'zeek.http.server_header_names': { + category: 'zeek', + description: + 'The vector of HTTP header names sent by the server. No header values are included here, just the header names. ', + name: 'zeek.http.server_header_names', + type: 'keyword', + }, + 'zeek.http.orig_fuids': { + category: 'zeek', + description: 'An ordered vector of file unique IDs from the originator. ', + name: 'zeek.http.orig_fuids', + type: 'keyword', + }, + 'zeek.http.orig_mime_types': { + category: 'zeek', + description: 'An ordered vector of mime types from the originator. ', + name: 'zeek.http.orig_mime_types', + type: 'keyword', + }, + 'zeek.http.orig_filenames': { + category: 'zeek', + description: 'An ordered vector of filenames from the originator. ', + name: 'zeek.http.orig_filenames', + type: 'keyword', + }, + 'zeek.http.resp_fuids': { + category: 'zeek', + description: 'An ordered vector of file unique IDs from the responder. ', + name: 'zeek.http.resp_fuids', + type: 'keyword', + }, + 'zeek.http.resp_mime_types': { + category: 'zeek', + description: 'An ordered vector of mime types from the responder. ', + name: 'zeek.http.resp_mime_types', + type: 'keyword', + }, + 'zeek.http.resp_filenames': { + category: 'zeek', + description: 'An ordered vector of filenames from the responder. ', + name: 'zeek.http.resp_filenames', + type: 'keyword', + }, + 'zeek.http.orig_mime_depth': { + category: 'zeek', + description: 'Current number of MIME entities in the HTTP request message body. ', + name: 'zeek.http.orig_mime_depth', + type: 'integer', + }, + 'zeek.http.resp_mime_depth': { + category: 'zeek', + description: 'Current number of MIME entities in the HTTP response message body. ', + name: 'zeek.http.resp_mime_depth', + type: 'integer', + }, + 'zeek.intel.seen.indicator': { + category: 'zeek', + description: 'The intelligence indicator. ', + name: 'zeek.intel.seen.indicator', + type: 'keyword', + }, + 'zeek.intel.seen.indicator_type': { + category: 'zeek', + description: 'The type of data the indicator represents. ', + name: 'zeek.intel.seen.indicator_type', + type: 'keyword', + }, + 'zeek.intel.seen.host': { + category: 'zeek', + description: 'If the indicator type was Intel::ADDR, then this field will be present. ', + name: 'zeek.intel.seen.host', + type: 'keyword', + }, + 'zeek.intel.seen.conn': { + category: 'zeek', + description: + 'If the data was discovered within a connection, the connection record should go here to give context to the data. ', + name: 'zeek.intel.seen.conn', + type: 'keyword', + }, + 'zeek.intel.seen.where': { + category: 'zeek', + description: 'Where the data was discovered. ', + name: 'zeek.intel.seen.where', + type: 'keyword', + }, + 'zeek.intel.seen.node': { + category: 'zeek', + description: 'The name of the node where the match was discovered. ', + name: 'zeek.intel.seen.node', + type: 'keyword', + }, + 'zeek.intel.seen.uid': { + category: 'zeek', + description: + 'If the data was discovered within a connection, the connection uid should go here to give context to the data. If the conn field is provided, this will be automatically filled out. ', + name: 'zeek.intel.seen.uid', + type: 'keyword', + }, + 'zeek.intel.seen.f': { + category: 'zeek', + description: + 'If the data was discovered within a file, the file record should go here to provide context to the data. ', + name: 'zeek.intel.seen.f', + type: 'object', + }, + 'zeek.intel.seen.fuid': { + category: 'zeek', + description: + 'If the data was discovered within a file, the file uid should go here to provide context to the data. If the file record f is provided, this will be automatically filled out. ', + name: 'zeek.intel.seen.fuid', + type: 'keyword', + }, + 'zeek.intel.matched': { + category: 'zeek', + description: 'Event to represent a match in the intelligence data from data that was seen. ', + name: 'zeek.intel.matched', + type: 'keyword', + }, + 'zeek.intel.sources': { + category: 'zeek', + description: 'Sources which supplied data for this match. ', + name: 'zeek.intel.sources', + type: 'keyword', + }, + 'zeek.intel.fuid': { + category: 'zeek', + description: + 'If a file was associated with this intelligence hit, this is the uid for the file. ', + name: 'zeek.intel.fuid', + type: 'keyword', + }, + 'zeek.intel.file_mime_type': { + category: 'zeek', + description: + 'A mime type if the intelligence hit is related to a file. If the $f field is provided this will be automatically filled out. ', + name: 'zeek.intel.file_mime_type', + type: 'keyword', + }, + 'zeek.intel.file_desc': { + category: 'zeek', + description: + 'Frequently files can be described to give a bit more context. If the $f field is provided this field will be automatically filled out. ', + name: 'zeek.intel.file_desc', + type: 'keyword', + }, + 'zeek.irc.nick': { + category: 'zeek', + description: 'Nickname given for the connection. ', + name: 'zeek.irc.nick', + type: 'keyword', + }, + 'zeek.irc.user': { + category: 'zeek', + description: 'Username given for the connection. ', + name: 'zeek.irc.user', + type: 'keyword', + }, + 'zeek.irc.command': { + category: 'zeek', + description: 'Command given by the client. ', + name: 'zeek.irc.command', + type: 'keyword', + }, + 'zeek.irc.value': { + category: 'zeek', + description: 'Value for the command given by the client. ', + name: 'zeek.irc.value', + type: 'keyword', + }, + 'zeek.irc.addl': { + category: 'zeek', + description: 'Any additional data for the command. ', + name: 'zeek.irc.addl', + type: 'keyword', + }, + 'zeek.irc.dcc.file.name': { + category: 'zeek', + description: 'Present if base/protocols/irc/dcc-send.bro is loaded. DCC filename requested. ', + name: 'zeek.irc.dcc.file.name', + type: 'keyword', + }, + 'zeek.irc.dcc.file.size': { + category: 'zeek', + description: + 'Present if base/protocols/irc/dcc-send.bro is loaded. Size of the DCC transfer as indicated by the sender. ', + name: 'zeek.irc.dcc.file.size', + type: 'long', + }, + 'zeek.irc.dcc.mime_type': { + category: 'zeek', + description: + 'present if base/protocols/irc/dcc-send.bro is loaded. Sniffed mime type of the file. ', + name: 'zeek.irc.dcc.mime_type', + type: 'keyword', + }, + 'zeek.irc.fuid': { + category: 'zeek', + description: 'present if base/protocols/irc/files.bro is loaded. File unique ID. ', + name: 'zeek.irc.fuid', + type: 'keyword', + }, + 'zeek.kerberos.request_type': { + category: 'zeek', + description: 'Request type - Authentication Service (AS) or Ticket Granting Service (TGS). ', + name: 'zeek.kerberos.request_type', + type: 'keyword', + }, + 'zeek.kerberos.client': { + category: 'zeek', + description: 'Client name. ', + name: 'zeek.kerberos.client', + type: 'keyword', + }, + 'zeek.kerberos.service': { + category: 'zeek', + description: 'Service name. ', + name: 'zeek.kerberos.service', + type: 'keyword', + }, + 'zeek.kerberos.success': { + category: 'zeek', + description: 'Request result. ', + name: 'zeek.kerberos.success', + type: 'boolean', + }, + 'zeek.kerberos.error.code': { + category: 'zeek', + description: 'Error code. ', + name: 'zeek.kerberos.error.code', + type: 'integer', + }, + 'zeek.kerberos.error.msg': { + category: 'zeek', + description: 'Error message. ', + name: 'zeek.kerberos.error.msg', + type: 'keyword', + }, + 'zeek.kerberos.valid.from': { + category: 'zeek', + description: 'Ticket valid from. ', + name: 'zeek.kerberos.valid.from', + type: 'date', + }, + 'zeek.kerberos.valid.until': { + category: 'zeek', + description: 'Ticket valid until. ', + name: 'zeek.kerberos.valid.until', + type: 'date', + }, + 'zeek.kerberos.valid.days': { + category: 'zeek', + description: 'Number of days the ticket is valid for. ', + name: 'zeek.kerberos.valid.days', + type: 'integer', + }, + 'zeek.kerberos.cipher': { + category: 'zeek', + description: 'Ticket encryption type. ', + name: 'zeek.kerberos.cipher', + type: 'keyword', + }, + 'zeek.kerberos.forwardable': { + category: 'zeek', + description: 'Forwardable ticket requested. ', + name: 'zeek.kerberos.forwardable', + type: 'boolean', + }, + 'zeek.kerberos.renewable': { + category: 'zeek', + description: 'Renewable ticket requested. ', + name: 'zeek.kerberos.renewable', + type: 'boolean', + }, + 'zeek.kerberos.ticket.auth': { + category: 'zeek', + description: 'Hash of ticket used to authorize request/transaction. ', + name: 'zeek.kerberos.ticket.auth', + type: 'keyword', + }, + 'zeek.kerberos.ticket.new': { + category: 'zeek', + description: 'Hash of ticket returned by the KDC. ', + name: 'zeek.kerberos.ticket.new', + type: 'keyword', + }, + 'zeek.kerberos.cert.client.value': { + category: 'zeek', + description: 'Client certificate. ', + name: 'zeek.kerberos.cert.client.value', + type: 'keyword', + }, + 'zeek.kerberos.cert.client.fuid': { + category: 'zeek', + description: 'File unique ID of client cert. ', + name: 'zeek.kerberos.cert.client.fuid', + type: 'keyword', + }, + 'zeek.kerberos.cert.client.subject': { + category: 'zeek', + description: 'Subject of client certificate. ', + name: 'zeek.kerberos.cert.client.subject', + type: 'keyword', + }, + 'zeek.kerberos.cert.server.value': { + category: 'zeek', + description: 'Server certificate. ', + name: 'zeek.kerberos.cert.server.value', + type: 'keyword', + }, + 'zeek.kerberos.cert.server.fuid': { + category: 'zeek', + description: 'File unique ID of server certificate. ', + name: 'zeek.kerberos.cert.server.fuid', + type: 'keyword', + }, + 'zeek.kerberos.cert.server.subject': { + category: 'zeek', + description: 'Subject of server certificate. ', + name: 'zeek.kerberos.cert.server.subject', + type: 'keyword', + }, + 'zeek.modbus.function': { + category: 'zeek', + description: 'The name of the function message that was sent. ', + name: 'zeek.modbus.function', + type: 'keyword', + }, + 'zeek.modbus.exception': { + category: 'zeek', + description: 'The exception if the response was a failure. ', + name: 'zeek.modbus.exception', + type: 'keyword', + }, + 'zeek.modbus.track_address': { + category: 'zeek', + description: + 'Present if policy/protocols/modbus/track-memmap.bro is loaded. Modbus track address. ', + name: 'zeek.modbus.track_address', + type: 'integer', + }, + 'zeek.mysql.cmd': { + category: 'zeek', + description: 'The command that was issued. ', + name: 'zeek.mysql.cmd', + type: 'keyword', + }, + 'zeek.mysql.arg': { + category: 'zeek', + description: 'The argument issued to the command. ', + name: 'zeek.mysql.arg', + type: 'keyword', + }, + 'zeek.mysql.success': { + category: 'zeek', + description: 'Whether the command succeeded. ', + name: 'zeek.mysql.success', + type: 'boolean', + }, + 'zeek.mysql.rows': { + category: 'zeek', + description: 'The number of affected rows, if any. ', + name: 'zeek.mysql.rows', + type: 'integer', + }, + 'zeek.mysql.response': { + category: 'zeek', + description: 'Server message, if any. ', + name: 'zeek.mysql.response', + type: 'keyword', + }, + 'zeek.notice.connection_id': { + category: 'zeek', + description: 'Identifier of the related connection session. ', + name: 'zeek.notice.connection_id', + type: 'keyword', + }, + 'zeek.notice.icmp_id': { + category: 'zeek', + description: 'Identifier of the related ICMP session. ', + name: 'zeek.notice.icmp_id', + type: 'keyword', + }, + 'zeek.notice.file.id': { + category: 'zeek', + description: 'An identifier associated with a single file that is related to this notice. ', + name: 'zeek.notice.file.id', + type: 'keyword', + }, + 'zeek.notice.file.parent_id': { + category: 'zeek', + description: 'Identifier associated with a container file from which this one was extracted. ', + name: 'zeek.notice.file.parent_id', + type: 'keyword', + }, + 'zeek.notice.file.source': { + category: 'zeek', + description: + 'An identification of the source of the file data. E.g. it may be a network protocol over which it was transferred, or a local file path which was read, or some other input source. ', + name: 'zeek.notice.file.source', + type: 'keyword', + }, + 'zeek.notice.file.mime_type': { + category: 'zeek', + description: 'A mime type if the notice is related to a file. ', + name: 'zeek.notice.file.mime_type', + type: 'keyword', + }, + 'zeek.notice.file.is_orig': { + category: 'zeek', + description: + 'If the source of this file is a network connection, this field indicates if the file is being sent by the originator of the connection or the responder. ', + name: 'zeek.notice.file.is_orig', + type: 'boolean', + }, + 'zeek.notice.file.seen_bytes': { + category: 'zeek', + description: 'Number of bytes provided to the file analysis engine for the file. ', + name: 'zeek.notice.file.seen_bytes', + type: 'long', + }, + 'zeek.notice.ffile.total_bytes': { + category: 'zeek', + description: 'Total number of bytes that are supposed to comprise the full file. ', + name: 'zeek.notice.ffile.total_bytes', + type: 'long', + }, + 'zeek.notice.file.missing_bytes': { + category: 'zeek', + description: + 'The number of bytes in the file stream that were completely missed during the process of analysis. ', + name: 'zeek.notice.file.missing_bytes', + type: 'long', + }, + 'zeek.notice.file.overflow_bytes': { + category: 'zeek', + description: + "The number of bytes in the file stream that were not delivered to stream file analyzers. This could be overlapping bytes or bytes that couldn't be reassembled. ", + name: 'zeek.notice.file.overflow_bytes', + type: 'long', + }, + 'zeek.notice.fuid': { + category: 'zeek', + description: 'A file unique ID if this notice is related to a file. ', + name: 'zeek.notice.fuid', + type: 'keyword', + }, + 'zeek.notice.note': { + category: 'zeek', + description: 'The type of the notice. ', + name: 'zeek.notice.note', + type: 'keyword', + }, + 'zeek.notice.msg': { + category: 'zeek', + description: 'The human readable message for the notice. ', + name: 'zeek.notice.msg', + type: 'keyword', + }, + 'zeek.notice.sub': { + category: 'zeek', + description: 'The human readable sub-message. ', + name: 'zeek.notice.sub', + type: 'keyword', + }, + 'zeek.notice.n': { + category: 'zeek', + description: 'Associated count, or a status code. ', + name: 'zeek.notice.n', + type: 'long', + }, + 'zeek.notice.peer_name': { + category: 'zeek', + description: 'Name of remote peer that raised this notice. ', + name: 'zeek.notice.peer_name', + type: 'keyword', + }, + 'zeek.notice.peer_descr': { + category: 'zeek', + description: 'Textual description for the peer that raised this notice. ', + name: 'zeek.notice.peer_descr', + type: 'text', + }, + 'zeek.notice.actions': { + category: 'zeek', + description: 'The actions which have been applied to this notice. ', + name: 'zeek.notice.actions', + type: 'keyword', + }, + 'zeek.notice.email_body_sections': { + category: 'zeek', + description: + 'By adding chunks of text into this element, other scripts can expand on notices that are being emailed. ', + name: 'zeek.notice.email_body_sections', + type: 'text', + }, + 'zeek.notice.email_delay_tokens': { + category: 'zeek', + description: + 'Adding a string token to this set will cause the built-in emailing functionality to delay sending the email either the token has been removed or the email has been delayed for the specified time duration. ', + name: 'zeek.notice.email_delay_tokens', + type: 'keyword', + }, + 'zeek.notice.identifier': { + category: 'zeek', + description: + 'This field is provided when a notice is generated for the purpose of deduplicating notices. ', + name: 'zeek.notice.identifier', + type: 'keyword', + }, + 'zeek.notice.suppress_for': { + category: 'zeek', + description: + 'This field indicates the length of time that this unique notice should be suppressed. ', + name: 'zeek.notice.suppress_for', + type: 'double', + }, + 'zeek.notice.dropped': { + category: 'zeek', + description: 'Indicate if the source IP address was dropped and denied network access. ', + name: 'zeek.notice.dropped', + type: 'boolean', + }, + 'zeek.ntlm.domain': { + category: 'zeek', + description: 'Domain name given by the client. ', + name: 'zeek.ntlm.domain', + type: 'keyword', + }, + 'zeek.ntlm.hostname': { + category: 'zeek', + description: 'Hostname given by the client. ', + name: 'zeek.ntlm.hostname', + type: 'keyword', + }, + 'zeek.ntlm.success': { + category: 'zeek', + description: 'Indicate whether or not the authentication was successful. ', + name: 'zeek.ntlm.success', + type: 'boolean', + }, + 'zeek.ntlm.username': { + category: 'zeek', + description: 'Username given by the client. ', + name: 'zeek.ntlm.username', + type: 'keyword', + }, + 'zeek.ntlm.server.name.dns': { + category: 'zeek', + description: 'DNS name given by the server in a CHALLENGE. ', + name: 'zeek.ntlm.server.name.dns', + type: 'keyword', + }, + 'zeek.ntlm.server.name.netbios': { + category: 'zeek', + description: 'NetBIOS name given by the server in a CHALLENGE. ', + name: 'zeek.ntlm.server.name.netbios', + type: 'keyword', + }, + 'zeek.ntlm.server.name.tree': { + category: 'zeek', + description: 'Tree name given by the server in a CHALLENGE. ', + name: 'zeek.ntlm.server.name.tree', + type: 'keyword', + }, + 'zeek.ocsp.file_id': { + category: 'zeek', + description: 'File id of the OCSP reply. ', + name: 'zeek.ocsp.file_id', + type: 'keyword', + }, + 'zeek.ocsp.hash.algorithm': { + category: 'zeek', + description: 'Hash algorithm used to generate issuerNameHash and issuerKeyHash. ', + name: 'zeek.ocsp.hash.algorithm', + type: 'keyword', + }, + 'zeek.ocsp.hash.issuer.name': { + category: 'zeek', + description: "Hash of the issuer's distingueshed name. ", + name: 'zeek.ocsp.hash.issuer.name', + type: 'keyword', + }, + 'zeek.ocsp.hash.issuer.key': { + category: 'zeek', + description: "Hash of the issuer's public key. ", + name: 'zeek.ocsp.hash.issuer.key', + type: 'keyword', + }, + 'zeek.ocsp.serial_number': { + category: 'zeek', + description: 'Serial number of the affected certificate. ', + name: 'zeek.ocsp.serial_number', + type: 'keyword', + }, + 'zeek.ocsp.status': { + category: 'zeek', + description: 'Status of the affected certificate. ', + name: 'zeek.ocsp.status', + type: 'keyword', + }, + 'zeek.ocsp.revoke.time': { + category: 'zeek', + description: 'Time at which the certificate was revoked. ', + name: 'zeek.ocsp.revoke.time', + type: 'date', + }, + 'zeek.ocsp.revoke.reason': { + category: 'zeek', + description: 'Reason for which the certificate was revoked. ', + name: 'zeek.ocsp.revoke.reason', + type: 'keyword', + }, + 'zeek.ocsp.update.this': { + category: 'zeek', + description: 'The time at which the status being shows is known to have been correct. ', + name: 'zeek.ocsp.update.this', + type: 'date', + }, + 'zeek.ocsp.update.next': { + category: 'zeek', + description: + 'The latest time at which new information about the status of the certificate will be available. ', + name: 'zeek.ocsp.update.next', + type: 'date', + }, + 'zeek.pe.client': { + category: 'zeek', + description: "The client's version string. ", + name: 'zeek.pe.client', + type: 'keyword', + }, + 'zeek.pe.id': { + category: 'zeek', + description: 'File id of this portable executable file. ', + name: 'zeek.pe.id', + type: 'keyword', + }, + 'zeek.pe.machine': { + category: 'zeek', + description: 'The target machine that the file was compiled for. ', + name: 'zeek.pe.machine', + type: 'keyword', + }, + 'zeek.pe.compile_time': { + category: 'zeek', + description: 'The time that the file was created at. ', + name: 'zeek.pe.compile_time', + type: 'date', + }, + 'zeek.pe.os': { + category: 'zeek', + description: 'The required operating system. ', + name: 'zeek.pe.os', + type: 'keyword', + }, + 'zeek.pe.subsystem': { + category: 'zeek', + description: 'The subsystem that is required to run this file. ', + name: 'zeek.pe.subsystem', + type: 'keyword', + }, + 'zeek.pe.is_exe': { + category: 'zeek', + description: 'Is the file an executable, or just an object file? ', + name: 'zeek.pe.is_exe', + type: 'boolean', + }, + 'zeek.pe.is_64bit': { + category: 'zeek', + description: 'Is the file a 64-bit executable? ', + name: 'zeek.pe.is_64bit', + type: 'boolean', + }, + 'zeek.pe.uses_aslr': { + category: 'zeek', + description: 'Does the file support Address Space Layout Randomization? ', + name: 'zeek.pe.uses_aslr', + type: 'boolean', + }, + 'zeek.pe.uses_dep': { + category: 'zeek', + description: 'Does the file support Data Execution Prevention? ', + name: 'zeek.pe.uses_dep', + type: 'boolean', + }, + 'zeek.pe.uses_code_integrity': { + category: 'zeek', + description: 'Does the file enforce code integrity checks? ', + name: 'zeek.pe.uses_code_integrity', + type: 'boolean', + }, + 'zeek.pe.uses_seh': { + category: 'zeek', + description: 'Does the file use structured exception handing? ', + name: 'zeek.pe.uses_seh', + type: 'boolean', + }, + 'zeek.pe.has_import_table': { + category: 'zeek', + description: 'Does the file have an import table? ', + name: 'zeek.pe.has_import_table', + type: 'boolean', + }, + 'zeek.pe.has_export_table': { + category: 'zeek', + description: 'Does the file have an export table? ', + name: 'zeek.pe.has_export_table', + type: 'boolean', + }, + 'zeek.pe.has_cert_table': { + category: 'zeek', + description: 'Does the file have an attribute certificate table? ', + name: 'zeek.pe.has_cert_table', + type: 'boolean', + }, + 'zeek.pe.has_debug_data': { + category: 'zeek', + description: 'Does the file have a debug table? ', + name: 'zeek.pe.has_debug_data', + type: 'boolean', + }, + 'zeek.pe.section_names': { + category: 'zeek', + description: 'The names of the sections, in order. ', + name: 'zeek.pe.section_names', + type: 'keyword', + }, + 'zeek.radius.username': { + category: 'zeek', + description: 'The username, if present. ', + name: 'zeek.radius.username', + type: 'keyword', + }, + 'zeek.radius.mac': { + category: 'zeek', + description: 'MAC address, if present. ', + name: 'zeek.radius.mac', + type: 'keyword', + }, + 'zeek.radius.framed_addr': { + category: 'zeek', + description: + 'The address given to the network access server, if present. This is only a hint from the RADIUS server and the network access server is not required to honor the address. ', + name: 'zeek.radius.framed_addr', + type: 'ip', + }, + 'zeek.radius.remote_ip': { + category: 'zeek', + description: + 'Remote IP address, if present. This is collected from the Tunnel-Client-Endpoint attribute. ', + name: 'zeek.radius.remote_ip', + type: 'ip', + }, + 'zeek.radius.connect_info': { + category: 'zeek', + description: 'Connect info, if present. ', + name: 'zeek.radius.connect_info', + type: 'keyword', + }, + 'zeek.radius.reply_msg': { + category: 'zeek', + description: + 'Reply message from the server challenge. This is frequently shown to the user authenticating. ', + name: 'zeek.radius.reply_msg', + type: 'keyword', + }, + 'zeek.radius.result': { + category: 'zeek', + description: 'Successful or failed authentication. ', + name: 'zeek.radius.result', + type: 'keyword', + }, + 'zeek.radius.ttl': { + category: 'zeek', + description: + 'The duration between the first request and either the "Access-Accept" message or an error. If the field is empty, it means that either the request or response was not seen. ', + name: 'zeek.radius.ttl', + type: 'integer', + }, + 'zeek.radius.logged': { + category: 'zeek', + description: 'Whether this has already been logged and can be ignored. ', + name: 'zeek.radius.logged', + type: 'boolean', + }, + 'zeek.rdp.cookie': { + category: 'zeek', + description: 'Cookie value used by the client machine. This is typically a username. ', + name: 'zeek.rdp.cookie', + type: 'keyword', + }, + 'zeek.rdp.result': { + category: 'zeek', + description: + "Status result for the connection. It's a mix between RDP negotation failure messages and GCC server create response messages. ", + name: 'zeek.rdp.result', + type: 'keyword', + }, + 'zeek.rdp.security_protocol': { + category: 'zeek', + description: 'Security protocol chosen by the server. ', + name: 'zeek.rdp.security_protocol', + type: 'keyword', + }, + 'zeek.rdp.keyboard_layout': { + category: 'zeek', + description: 'Keyboard layout (language) of the client machine. ', + name: 'zeek.rdp.keyboard_layout', + type: 'keyword', + }, + 'zeek.rdp.client.build': { + category: 'zeek', + description: 'RDP client version used by the client machine. ', + name: 'zeek.rdp.client.build', + type: 'keyword', + }, + 'zeek.rdp.client.client_name': { + category: 'zeek', + description: 'Name of the client machine. ', + name: 'zeek.rdp.client.client_name', + type: 'keyword', + }, + 'zeek.rdp.client.product_id': { + category: 'zeek', + description: 'Product ID of the client machine. ', + name: 'zeek.rdp.client.product_id', + type: 'keyword', + }, + 'zeek.rdp.desktop.width': { + category: 'zeek', + description: 'Desktop width of the client machine. ', + name: 'zeek.rdp.desktop.width', + type: 'integer', + }, + 'zeek.rdp.desktop.height': { + category: 'zeek', + description: 'Desktop height of the client machine. ', + name: 'zeek.rdp.desktop.height', + type: 'integer', + }, + 'zeek.rdp.desktop.color_depth': { + category: 'zeek', + description: 'The color depth requested by the client in the high_color_depth field. ', + name: 'zeek.rdp.desktop.color_depth', + type: 'keyword', + }, + 'zeek.rdp.cert.type': { + category: 'zeek', + description: + 'If the connection is being encrypted with native RDP encryption, this is the type of cert being used. ', + name: 'zeek.rdp.cert.type', + type: 'keyword', + }, + 'zeek.rdp.cert.count': { + category: 'zeek', + description: 'The number of certs seen. X.509 can transfer an entire certificate chain. ', + name: 'zeek.rdp.cert.count', + type: 'integer', + }, + 'zeek.rdp.cert.permanent': { + category: 'zeek', + description: + 'Indicates if the provided certificate or certificate chain is permanent or temporary. ', + name: 'zeek.rdp.cert.permanent', + type: 'boolean', + }, + 'zeek.rdp.encryption.level': { + category: 'zeek', + description: 'Encryption level of the connection. ', + name: 'zeek.rdp.encryption.level', + type: 'keyword', + }, + 'zeek.rdp.encryption.method': { + category: 'zeek', + description: 'Encryption method of the connection. ', + name: 'zeek.rdp.encryption.method', + type: 'keyword', + }, + 'zeek.rdp.done': { + category: 'zeek', + description: 'Track status of logging RDP connections. ', + name: 'zeek.rdp.done', + type: 'boolean', + }, + 'zeek.rdp.ssl': { + category: 'zeek', + description: + '(present if policy/protocols/rdp/indicate_ssl.bro is loaded) Flag the connection if it was seen over SSL. ', + name: 'zeek.rdp.ssl', + type: 'boolean', + }, + 'zeek.rfb.version.client.major': { + category: 'zeek', + description: 'Major version of the client. ', + name: 'zeek.rfb.version.client.major', + type: 'keyword', + }, + 'zeek.rfb.version.client.minor': { + category: 'zeek', + description: 'Minor version of the client. ', + name: 'zeek.rfb.version.client.minor', + type: 'keyword', + }, + 'zeek.rfb.version.server.major': { + category: 'zeek', + description: 'Major version of the server. ', + name: 'zeek.rfb.version.server.major', + type: 'keyword', + }, + 'zeek.rfb.version.server.minor': { + category: 'zeek', + description: 'Minor version of the server. ', + name: 'zeek.rfb.version.server.minor', + type: 'keyword', + }, + 'zeek.rfb.auth.success': { + category: 'zeek', + description: 'Whether or not authentication was successful. ', + name: 'zeek.rfb.auth.success', + type: 'boolean', + }, + 'zeek.rfb.auth.method': { + category: 'zeek', + description: 'Identifier of authentication method used. ', + name: 'zeek.rfb.auth.method', + type: 'keyword', + }, + 'zeek.rfb.share_flag': { + category: 'zeek', + description: 'Whether the client has an exclusive or a shared session. ', + name: 'zeek.rfb.share_flag', + type: 'boolean', + }, + 'zeek.rfb.desktop_name': { + category: 'zeek', + description: 'Name of the screen that is being shared. ', + name: 'zeek.rfb.desktop_name', + type: 'keyword', + }, + 'zeek.rfb.width': { + category: 'zeek', + description: 'Width of the screen that is being shared. ', + name: 'zeek.rfb.width', + type: 'integer', + }, + 'zeek.rfb.height': { + category: 'zeek', + description: 'Height of the screen that is being shared. ', + name: 'zeek.rfb.height', + type: 'integer', + }, + 'zeek.sip.transaction_depth': { + category: 'zeek', + description: + 'Represents the pipelined depth into the connection of this request/response transaction. ', + name: 'zeek.sip.transaction_depth', + type: 'integer', + }, + 'zeek.sip.sequence.method': { + category: 'zeek', + description: 'Verb used in the SIP request (INVITE, REGISTER etc.). ', + name: 'zeek.sip.sequence.method', + type: 'keyword', + }, + 'zeek.sip.sequence.number': { + category: 'zeek', + description: 'Contents of the CSeq: header from the client. ', + name: 'zeek.sip.sequence.number', + type: 'keyword', + }, + 'zeek.sip.uri': { + category: 'zeek', + description: 'URI used in the request. ', + name: 'zeek.sip.uri', + type: 'keyword', + }, + 'zeek.sip.date': { + category: 'zeek', + description: 'Contents of the Date: header from the client. ', + name: 'zeek.sip.date', + type: 'keyword', + }, + 'zeek.sip.request.from': { + category: 'zeek', + description: + "Contents of the request From: header Note: The tag= value that's usually appended to the sender is stripped off and not logged. ", + name: 'zeek.sip.request.from', + type: 'keyword', + }, + 'zeek.sip.request.to': { + category: 'zeek', + description: 'Contents of the To: header. ', + name: 'zeek.sip.request.to', + type: 'keyword', + }, + 'zeek.sip.request.path': { + category: 'zeek', + description: 'The client message transmission path, as extracted from the headers. ', + name: 'zeek.sip.request.path', + type: 'keyword', + }, + 'zeek.sip.request.body_length': { + category: 'zeek', + description: 'Contents of the Content-Length: header from the client. ', + name: 'zeek.sip.request.body_length', + type: 'long', + }, + 'zeek.sip.response.from': { + category: 'zeek', + description: + "Contents of the response From: header Note: The tag= value that's usually appended to the sender is stripped off and not logged. ", + name: 'zeek.sip.response.from', + type: 'keyword', + }, + 'zeek.sip.response.to': { + category: 'zeek', + description: 'Contents of the response To: header. ', + name: 'zeek.sip.response.to', + type: 'keyword', + }, + 'zeek.sip.response.path': { + category: 'zeek', + description: 'The server message transmission path, as extracted from the headers. ', + name: 'zeek.sip.response.path', + type: 'keyword', + }, + 'zeek.sip.response.body_length': { + category: 'zeek', + description: 'Contents of the Content-Length: header from the server. ', + name: 'zeek.sip.response.body_length', + type: 'long', + }, + 'zeek.sip.reply_to': { + category: 'zeek', + description: 'Contents of the Reply-To: header. ', + name: 'zeek.sip.reply_to', + type: 'keyword', + }, + 'zeek.sip.call_id': { + category: 'zeek', + description: 'Contents of the Call-ID: header from the client. ', + name: 'zeek.sip.call_id', + type: 'keyword', + }, + 'zeek.sip.subject': { + category: 'zeek', + description: 'Contents of the Subject: header from the client. ', + name: 'zeek.sip.subject', + type: 'keyword', + }, + 'zeek.sip.user_agent': { + category: 'zeek', + description: 'Contents of the User-Agent: header from the client. ', + name: 'zeek.sip.user_agent', + type: 'keyword', + }, + 'zeek.sip.status.code': { + category: 'zeek', + description: 'Status code returned by the server. ', + name: 'zeek.sip.status.code', + type: 'integer', + }, + 'zeek.sip.status.msg': { + category: 'zeek', + description: 'Status message returned by the server. ', + name: 'zeek.sip.status.msg', + type: 'keyword', + }, + 'zeek.sip.warning': { + category: 'zeek', + description: 'Contents of the Warning: header. ', + name: 'zeek.sip.warning', + type: 'keyword', + }, + 'zeek.sip.content_type': { + category: 'zeek', + description: 'Contents of the Content-Type: header from the server. ', + name: 'zeek.sip.content_type', + type: 'keyword', + }, + 'zeek.smb_cmd.command': { + category: 'zeek', + description: 'The command sent by the client. ', + name: 'zeek.smb_cmd.command', + type: 'keyword', + }, + 'zeek.smb_cmd.sub_command': { + category: 'zeek', + description: 'The subcommand sent by the client, if present. ', + name: 'zeek.smb_cmd.sub_command', + type: 'keyword', + }, + 'zeek.smb_cmd.argument': { + category: 'zeek', + description: 'Command argument sent by the client, if any. ', + name: 'zeek.smb_cmd.argument', + type: 'keyword', + }, + 'zeek.smb_cmd.status': { + category: 'zeek', + description: "Server reply to the client's command. ", + name: 'zeek.smb_cmd.status', + type: 'keyword', + }, + 'zeek.smb_cmd.rtt': { + category: 'zeek', + description: 'Round trip time from the request to the response. ', + name: 'zeek.smb_cmd.rtt', + type: 'double', + }, + 'zeek.smb_cmd.version': { + category: 'zeek', + description: 'Version of SMB for the command. ', + name: 'zeek.smb_cmd.version', + type: 'keyword', + }, + 'zeek.smb_cmd.username': { + category: 'zeek', + description: 'Authenticated username, if available. ', + name: 'zeek.smb_cmd.username', + type: 'keyword', + }, + 'zeek.smb_cmd.tree': { + category: 'zeek', + description: + 'If this is related to a tree, this is the tree that was used for the current command. ', + name: 'zeek.smb_cmd.tree', + type: 'keyword', + }, + 'zeek.smb_cmd.tree_service': { + category: 'zeek', + description: 'The type of tree (disk share, printer share, named pipe, etc.). ', + name: 'zeek.smb_cmd.tree_service', + type: 'keyword', + }, + 'zeek.smb_cmd.file.name': { + category: 'zeek', + description: 'Filename if one was seen. ', + name: 'zeek.smb_cmd.file.name', + type: 'keyword', + }, + 'zeek.smb_cmd.file.action': { + category: 'zeek', + description: 'Action this log record represents. ', + name: 'zeek.smb_cmd.file.action', + type: 'keyword', + }, + 'zeek.smb_cmd.file.uid': { + category: 'zeek', + description: 'UID of the referenced file. ', + name: 'zeek.smb_cmd.file.uid', + type: 'keyword', + }, + 'zeek.smb_cmd.file.host.tx': { + category: 'zeek', + description: 'Address of the transmitting host. ', + name: 'zeek.smb_cmd.file.host.tx', + type: 'ip', + }, + 'zeek.smb_cmd.file.host.rx': { + category: 'zeek', + description: 'Address of the receiving host. ', + name: 'zeek.smb_cmd.file.host.rx', + type: 'ip', + }, + 'zeek.smb_cmd.smb1_offered_dialects': { + category: 'zeek', + description: + 'Present if base/protocols/smb/smb1-main.bro is loaded. Dialects offered by the client. ', + name: 'zeek.smb_cmd.smb1_offered_dialects', + type: 'keyword', + }, + 'zeek.smb_cmd.smb2_offered_dialects': { + category: 'zeek', + description: + 'Present if base/protocols/smb/smb2-main.bro is loaded. Dialects offered by the client. ', + name: 'zeek.smb_cmd.smb2_offered_dialects', + type: 'integer', + }, + 'zeek.smb_files.action': { + category: 'zeek', + description: 'Action this log record represents. ', + name: 'zeek.smb_files.action', + type: 'keyword', + }, + 'zeek.smb_files.fid': { + category: 'zeek', + description: 'ID referencing this file. ', + name: 'zeek.smb_files.fid', + type: 'integer', + }, + 'zeek.smb_files.name': { + category: 'zeek', + description: 'Filename if one was seen. ', + name: 'zeek.smb_files.name', + type: 'keyword', + }, + 'zeek.smb_files.path': { + category: 'zeek', + description: 'Path pulled from the tree this file was transferred to or from. ', + name: 'zeek.smb_files.path', + type: 'keyword', + }, + 'zeek.smb_files.previous_name': { + category: 'zeek', + description: "If the rename action was seen, this will be the file's previous name. ", + name: 'zeek.smb_files.previous_name', + type: 'keyword', + }, + 'zeek.smb_files.size': { + category: 'zeek', + description: 'Byte size of the file. ', + name: 'zeek.smb_files.size', + type: 'long', + }, + 'zeek.smb_files.times.accessed': { + category: 'zeek', + description: "The file's access time. ", + name: 'zeek.smb_files.times.accessed', + type: 'date', + }, + 'zeek.smb_files.times.changed': { + category: 'zeek', + description: "The file's change time. ", + name: 'zeek.smb_files.times.changed', + type: 'date', + }, + 'zeek.smb_files.times.created': { + category: 'zeek', + description: "The file's create time. ", + name: 'zeek.smb_files.times.created', + type: 'date', + }, + 'zeek.smb_files.times.modified': { + category: 'zeek', + description: "The file's modify time. ", + name: 'zeek.smb_files.times.modified', + type: 'date', + }, + 'zeek.smb_files.uuid': { + category: 'zeek', + description: 'UUID referencing this file if DCE/RPC. ', + name: 'zeek.smb_files.uuid', + type: 'keyword', + }, + 'zeek.smb_mapping.path': { + category: 'zeek', + description: 'Name of the tree path. ', + name: 'zeek.smb_mapping.path', + type: 'keyword', + }, + 'zeek.smb_mapping.service': { + category: 'zeek', + description: 'The type of resource of the tree (disk share, printer share, named pipe, etc.). ', + name: 'zeek.smb_mapping.service', + type: 'keyword', + }, + 'zeek.smb_mapping.native_file_system': { + category: 'zeek', + description: 'File system of the tree. ', + name: 'zeek.smb_mapping.native_file_system', + type: 'keyword', + }, + 'zeek.smb_mapping.share_type': { + category: 'zeek', + description: + 'If this is SMB2, a share type will be included. For SMB1, the type of share will be deduced and included as well. ', + name: 'zeek.smb_mapping.share_type', + type: 'keyword', + }, + 'zeek.smtp.transaction_depth': { + category: 'zeek', + description: + 'A count to represent the depth of this message transaction in a single connection where multiple messages were transferred. ', + name: 'zeek.smtp.transaction_depth', + type: 'integer', + }, + 'zeek.smtp.helo': { + category: 'zeek', + description: 'Contents of the Helo header. ', + name: 'zeek.smtp.helo', + type: 'keyword', + }, + 'zeek.smtp.mail_from': { + category: 'zeek', + description: 'Email addresses found in the MAIL FROM header. ', + name: 'zeek.smtp.mail_from', + type: 'keyword', + }, + 'zeek.smtp.rcpt_to': { + category: 'zeek', + description: 'Email addresses found in the RCPT TO header. ', + name: 'zeek.smtp.rcpt_to', + type: 'keyword', + }, + 'zeek.smtp.date': { + category: 'zeek', + description: 'Contents of the Date header. ', + name: 'zeek.smtp.date', + type: 'date', + }, + 'zeek.smtp.from': { + category: 'zeek', + description: 'Contents of the From header. ', + name: 'zeek.smtp.from', + type: 'keyword', + }, + 'zeek.smtp.to': { + category: 'zeek', + description: 'Contents of the To header. ', + name: 'zeek.smtp.to', + type: 'keyword', + }, + 'zeek.smtp.cc': { + category: 'zeek', + description: 'Contents of the CC header. ', + name: 'zeek.smtp.cc', + type: 'keyword', + }, + 'zeek.smtp.reply_to': { + category: 'zeek', + description: 'Contents of the ReplyTo header. ', + name: 'zeek.smtp.reply_to', + type: 'keyword', + }, + 'zeek.smtp.msg_id': { + category: 'zeek', + description: 'Contents of the MsgID header. ', + name: 'zeek.smtp.msg_id', + type: 'keyword', + }, + 'zeek.smtp.in_reply_to': { + category: 'zeek', + description: 'Contents of the In-Reply-To header. ', + name: 'zeek.smtp.in_reply_to', + type: 'keyword', + }, + 'zeek.smtp.subject': { + category: 'zeek', + description: 'Contents of the Subject header. ', + name: 'zeek.smtp.subject', + type: 'keyword', + }, + 'zeek.smtp.x_originating_ip': { + category: 'zeek', + description: 'Contents of the X-Originating-IP header. ', + name: 'zeek.smtp.x_originating_ip', + type: 'keyword', + }, + 'zeek.smtp.first_received': { + category: 'zeek', + description: 'Contents of the first Received header. ', + name: 'zeek.smtp.first_received', + type: 'keyword', + }, + 'zeek.smtp.second_received': { + category: 'zeek', + description: 'Contents of the second Received header. ', + name: 'zeek.smtp.second_received', + type: 'keyword', + }, + 'zeek.smtp.last_reply': { + category: 'zeek', + description: 'The last message that the server sent to the client. ', + name: 'zeek.smtp.last_reply', + type: 'keyword', + }, + 'zeek.smtp.path': { + category: 'zeek', + description: 'The message transmission path, as extracted from the headers. ', + name: 'zeek.smtp.path', + type: 'ip', + }, + 'zeek.smtp.user_agent': { + category: 'zeek', + description: 'Value of the User-Agent header from the client. ', + name: 'zeek.smtp.user_agent', + type: 'keyword', + }, + 'zeek.smtp.tls': { + category: 'zeek', + description: 'Indicates that the connection has switched to using TLS. ', + name: 'zeek.smtp.tls', + type: 'boolean', + }, + 'zeek.smtp.process_received_from': { + category: 'zeek', + description: 'Indicates if the "Received: from" headers should still be processed. ', + name: 'zeek.smtp.process_received_from', + type: 'boolean', + }, + 'zeek.smtp.has_client_activity': { + category: 'zeek', + description: 'Indicates if client activity has been seen, but not yet logged. ', + name: 'zeek.smtp.has_client_activity', + type: 'boolean', + }, + 'zeek.smtp.fuids': { + category: 'zeek', + description: + '(present if base/protocols/smtp/files.bro is loaded) An ordered vector of file unique IDs seen attached to the message. ', + name: 'zeek.smtp.fuids', + type: 'keyword', + }, + 'zeek.smtp.is_webmail': { + category: 'zeek', + description: 'Indicates if the message was sent through a webmail interface. ', + name: 'zeek.smtp.is_webmail', + type: 'boolean', + }, + 'zeek.snmp.duration': { + category: 'zeek', + description: + 'The amount of time between the first packet beloning to the SNMP session and the latest one seen. ', + name: 'zeek.snmp.duration', + type: 'double', + }, + 'zeek.snmp.version': { + category: 'zeek', + description: 'The version of SNMP being used. ', + name: 'zeek.snmp.version', + type: 'keyword', + }, + 'zeek.snmp.community': { + category: 'zeek', + description: + "The community string of the first SNMP packet associated with the session. This is used as part of SNMP's (v1 and v2c) administrative/security framework. See RFC 1157 or RFC 1901. ", + name: 'zeek.snmp.community', + type: 'keyword', + }, + 'zeek.snmp.get.requests': { + category: 'zeek', + description: + 'The number of variable bindings in GetRequest/GetNextRequest PDUs seen for the session. ', + name: 'zeek.snmp.get.requests', + type: 'integer', + }, + 'zeek.snmp.get.bulk_requests': { + category: 'zeek', + description: 'The number of variable bindings in GetBulkRequest PDUs seen for the session. ', + name: 'zeek.snmp.get.bulk_requests', + type: 'integer', + }, + 'zeek.snmp.get.responses': { + category: 'zeek', + description: + 'The number of variable bindings in GetResponse/Response PDUs seen for the session. ', + name: 'zeek.snmp.get.responses', + type: 'integer', + }, + 'zeek.snmp.set.requests': { + category: 'zeek', + description: 'The number of variable bindings in SetRequest PDUs seen for the session. ', + name: 'zeek.snmp.set.requests', + type: 'integer', + }, + 'zeek.snmp.display_string': { + category: 'zeek', + description: 'A system description of the SNMP responder endpoint. ', + name: 'zeek.snmp.display_string', + type: 'keyword', + }, + 'zeek.snmp.up_since': { + category: 'zeek', + description: "The time at which the SNMP responder endpoint claims it's been up since. ", + name: 'zeek.snmp.up_since', + type: 'date', + }, + 'zeek.socks.version': { + category: 'zeek', + description: 'Protocol version of SOCKS. ', + name: 'zeek.socks.version', + type: 'integer', + }, + 'zeek.socks.user': { + category: 'zeek', + description: 'Username used to request a login to the proxy. ', + name: 'zeek.socks.user', + type: 'keyword', + }, + 'zeek.socks.password': { + category: 'zeek', + description: 'Password used to request a login to the proxy. ', + name: 'zeek.socks.password', + type: 'keyword', + }, + 'zeek.socks.status': { + category: 'zeek', + description: 'Server status for the attempt at using the proxy. ', + name: 'zeek.socks.status', + type: 'keyword', + }, + 'zeek.socks.request.host': { + category: 'zeek', + description: 'Client requested SOCKS address. Could be an address, a name or both. ', + name: 'zeek.socks.request.host', + type: 'keyword', + }, + 'zeek.socks.request.port': { + category: 'zeek', + description: 'Client requested port. ', + name: 'zeek.socks.request.port', + type: 'integer', + }, + 'zeek.socks.bound.host': { + category: 'zeek', + description: 'Server bound address. Could be an address, a name or both. ', + name: 'zeek.socks.bound.host', + type: 'keyword', + }, + 'zeek.socks.bound.port': { + category: 'zeek', + description: 'Server bound port. ', + name: 'zeek.socks.bound.port', + type: 'integer', + }, + 'zeek.socks.capture_password': { + category: 'zeek', + description: 'Determines if the password will be captured for this request. ', + name: 'zeek.socks.capture_password', + type: 'boolean', + }, + 'zeek.ssh.client': { + category: 'zeek', + description: "The client's version string. ", + name: 'zeek.ssh.client', + type: 'keyword', + }, + 'zeek.ssh.direction': { + category: 'zeek', + description: + 'Direction of the connection. If the client was a local host logging into an external host, this would be OUTBOUND. INBOUND would be set for the opposite situation. ', + name: 'zeek.ssh.direction', + type: 'keyword', + }, + 'zeek.ssh.host_key': { + category: 'zeek', + description: "The server's key thumbprint. ", + name: 'zeek.ssh.host_key', + type: 'keyword', + }, + 'zeek.ssh.server': { + category: 'zeek', + description: "The server's version string. ", + name: 'zeek.ssh.server', + type: 'keyword', + }, + 'zeek.ssh.version': { + category: 'zeek', + description: 'SSH major version (1 or 2). ', + name: 'zeek.ssh.version', + type: 'integer', + }, + 'zeek.ssh.algorithm.cipher': { + category: 'zeek', + description: 'The encryption algorithm in use. ', + name: 'zeek.ssh.algorithm.cipher', + type: 'keyword', + }, + 'zeek.ssh.algorithm.compression': { + category: 'zeek', + description: 'The compression algorithm in use. ', + name: 'zeek.ssh.algorithm.compression', + type: 'keyword', + }, + 'zeek.ssh.algorithm.host_key': { + category: 'zeek', + description: "The server host key's algorithm. ", + name: 'zeek.ssh.algorithm.host_key', + type: 'keyword', + }, + 'zeek.ssh.algorithm.key_exchange': { + category: 'zeek', + description: 'The key exchange algorithm in use. ', + name: 'zeek.ssh.algorithm.key_exchange', + type: 'keyword', + }, + 'zeek.ssh.algorithm.mac': { + category: 'zeek', + description: 'The signing (MAC) algorithm in use. ', + name: 'zeek.ssh.algorithm.mac', + type: 'keyword', + }, + 'zeek.ssh.auth.attempts': { + category: 'zeek', + description: + "The number of authentication attemps we observed. There's always at least one, since some servers might support no authentication at all. It's important to note that not all of these are failures, since some servers require two-factor auth (e.g. password AND pubkey). ", + name: 'zeek.ssh.auth.attempts', + type: 'integer', + }, + 'zeek.ssh.auth.success': { + category: 'zeek', + description: 'Authentication result. ', + name: 'zeek.ssh.auth.success', + type: 'boolean', + }, + 'zeek.ssl.version': { + category: 'zeek', + description: 'SSL/TLS version that was logged. ', + name: 'zeek.ssl.version', + type: 'keyword', + }, + 'zeek.ssl.cipher': { + category: 'zeek', + description: 'SSL/TLS cipher suite that was logged. ', + name: 'zeek.ssl.cipher', + type: 'keyword', + }, + 'zeek.ssl.curve': { + category: 'zeek', + description: 'Elliptic curve that was logged when using ECDH/ECDHE. ', + name: 'zeek.ssl.curve', + type: 'keyword', + }, + 'zeek.ssl.resumed': { + category: 'zeek', + description: + 'Flag to indicate if the session was resumed reusing the key material exchanged in an earlier connection. ', + name: 'zeek.ssl.resumed', + type: 'boolean', + }, + 'zeek.ssl.next_protocol': { + category: 'zeek', + description: + 'Next protocol the server chose using the application layer next protocol extension. ', + name: 'zeek.ssl.next_protocol', + type: 'keyword', + }, + 'zeek.ssl.established': { + category: 'zeek', + description: 'Flag to indicate if this ssl session has been established successfully. ', + name: 'zeek.ssl.established', + type: 'boolean', + }, + 'zeek.ssl.validation.status': { + category: 'zeek', + description: 'Result of certificate validation for this connection. ', + name: 'zeek.ssl.validation.status', + type: 'keyword', + }, + 'zeek.ssl.validation.code': { + category: 'zeek', + description: + 'Result of certificate validation for this connection, given as OpenSSL validation code. ', + name: 'zeek.ssl.validation.code', + type: 'keyword', + }, + 'zeek.ssl.last_alert': { + category: 'zeek', + description: 'Last alert that was seen during the connection. ', + name: 'zeek.ssl.last_alert', + type: 'keyword', + }, + 'zeek.ssl.server.name': { + category: 'zeek', + description: + 'Value of the Server Name Indicator SSL/TLS extension. It indicates the server name that the client was requesting. ', + name: 'zeek.ssl.server.name', + type: 'keyword', + }, + 'zeek.ssl.server.cert_chain': { + category: 'zeek', + description: + 'Chain of certificates offered by the server to validate its complete signing chain. ', + name: 'zeek.ssl.server.cert_chain', + type: 'keyword', + }, + 'zeek.ssl.server.cert_chain_fuids': { + category: 'zeek', + description: + 'An ordered vector of certificate file identifiers for the certificates offered by the server. ', + name: 'zeek.ssl.server.cert_chain_fuids', + type: 'keyword', + }, + 'zeek.ssl.server.issuer.common_name': { + category: 'zeek', + description: 'Common name of the signer of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.issuer.common_name', + type: 'keyword', + }, + 'zeek.ssl.server.issuer.country': { + category: 'zeek', + description: 'Country code of the signer of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.issuer.country', + type: 'keyword', + }, + 'zeek.ssl.server.issuer.locality': { + category: 'zeek', + description: 'Locality of the signer of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.issuer.locality', + type: 'keyword', + }, + 'zeek.ssl.server.issuer.organization': { + category: 'zeek', + description: 'Organization of the signer of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.issuer.organization', + type: 'keyword', + }, + 'zeek.ssl.server.issuer.organizational_unit': { + category: 'zeek', + description: + 'Organizational unit of the signer of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.issuer.organizational_unit', + type: 'keyword', + }, + 'zeek.ssl.server.issuer.state': { + category: 'zeek', + description: + 'State or province name of the signer of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.issuer.state', + type: 'keyword', + }, + 'zeek.ssl.server.subject.common_name': { + category: 'zeek', + description: 'Common name of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.subject.common_name', + type: 'keyword', + }, + 'zeek.ssl.server.subject.country': { + category: 'zeek', + description: 'Country code of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.subject.country', + type: 'keyword', + }, + 'zeek.ssl.server.subject.locality': { + category: 'zeek', + description: 'Locality of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.subject.locality', + type: 'keyword', + }, + 'zeek.ssl.server.subject.organization': { + category: 'zeek', + description: 'Organization of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.subject.organization', + type: 'keyword', + }, + 'zeek.ssl.server.subject.organizational_unit': { + category: 'zeek', + description: 'Organizational unit of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.subject.organizational_unit', + type: 'keyword', + }, + 'zeek.ssl.server.subject.state': { + category: 'zeek', + description: 'State or province name of the X.509 certificate offered by the server. ', + name: 'zeek.ssl.server.subject.state', + type: 'keyword', + }, + 'zeek.ssl.client.cert_chain': { + category: 'zeek', + description: + 'Chain of certificates offered by the client to validate its complete signing chain. ', + name: 'zeek.ssl.client.cert_chain', + type: 'keyword', + }, + 'zeek.ssl.client.cert_chain_fuids': { + category: 'zeek', + description: + 'An ordered vector of certificate file identifiers for the certificates offered by the client. ', + name: 'zeek.ssl.client.cert_chain_fuids', + type: 'keyword', + }, + 'zeek.ssl.client.issuer.common_name': { + category: 'zeek', + description: 'Common name of the signer of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.issuer.common_name', + type: 'keyword', + }, + 'zeek.ssl.client.issuer.country': { + category: 'zeek', + description: 'Country code of the signer of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.issuer.country', + type: 'keyword', + }, + 'zeek.ssl.client.issuer.locality': { + category: 'zeek', + description: 'Locality of the signer of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.issuer.locality', + type: 'keyword', + }, + 'zeek.ssl.client.issuer.organization': { + category: 'zeek', + description: 'Organization of the signer of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.issuer.organization', + type: 'keyword', + }, + 'zeek.ssl.client.issuer.organizational_unit': { + category: 'zeek', + description: + 'Organizational unit of the signer of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.issuer.organizational_unit', + type: 'keyword', + }, + 'zeek.ssl.client.issuer.state': { + category: 'zeek', + description: + 'State or province name of the signer of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.issuer.state', + type: 'keyword', + }, + 'zeek.ssl.client.subject.common_name': { + category: 'zeek', + description: 'Common name of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.subject.common_name', + type: 'keyword', + }, + 'zeek.ssl.client.subject.country': { + category: 'zeek', + description: 'Country code of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.subject.country', + type: 'keyword', + }, + 'zeek.ssl.client.subject.locality': { + category: 'zeek', + description: 'Locality of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.subject.locality', + type: 'keyword', + }, + 'zeek.ssl.client.subject.organization': { + category: 'zeek', + description: 'Organization of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.subject.organization', + type: 'keyword', + }, + 'zeek.ssl.client.subject.organizational_unit': { + category: 'zeek', + description: 'Organizational unit of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.subject.organizational_unit', + type: 'keyword', + }, + 'zeek.ssl.client.subject.state': { + category: 'zeek', + description: 'State or province name of the X.509 certificate offered by the client. ', + name: 'zeek.ssl.client.subject.state', + type: 'keyword', + }, + 'zeek.stats.peer': { + category: 'zeek', + description: 'Peer that generated this log. Mostly for clusters. ', + name: 'zeek.stats.peer', + type: 'keyword', + }, + 'zeek.stats.memory': { + category: 'zeek', + description: 'Amount of memory currently in use in MB. ', + name: 'zeek.stats.memory', + type: 'integer', + }, + 'zeek.stats.packets.processed': { + category: 'zeek', + description: 'Number of packets processed since the last stats interval. ', + name: 'zeek.stats.packets.processed', + type: 'long', + }, + 'zeek.stats.packets.dropped': { + category: 'zeek', + description: + 'Number of packets dropped since the last stats interval if reading live traffic. ', + name: 'zeek.stats.packets.dropped', + type: 'long', + }, + 'zeek.stats.packets.received': { + category: 'zeek', + description: + 'Number of packets seen on the link since the last stats interval if reading live traffic. ', + name: 'zeek.stats.packets.received', + type: 'long', + }, + 'zeek.stats.bytes.received': { + category: 'zeek', + description: 'Number of bytes received since the last stats interval if reading live traffic. ', + name: 'zeek.stats.bytes.received', + type: 'long', + }, + 'zeek.stats.connections.tcp.active': { + category: 'zeek', + description: 'TCP connections currently in memory. ', + name: 'zeek.stats.connections.tcp.active', + type: 'integer', + }, + 'zeek.stats.connections.tcp.count': { + category: 'zeek', + description: 'TCP connections seen since last stats interval. ', + name: 'zeek.stats.connections.tcp.count', + type: 'integer', + }, + 'zeek.stats.connections.udp.active': { + category: 'zeek', + description: 'UDP connections currently in memory. ', + name: 'zeek.stats.connections.udp.active', + type: 'integer', + }, + 'zeek.stats.connections.udp.count': { + category: 'zeek', + description: 'UDP connections seen since last stats interval. ', + name: 'zeek.stats.connections.udp.count', + type: 'integer', + }, + 'zeek.stats.connections.icmp.active': { + category: 'zeek', + description: 'ICMP connections currently in memory. ', + name: 'zeek.stats.connections.icmp.active', + type: 'integer', + }, + 'zeek.stats.connections.icmp.count': { + category: 'zeek', + description: 'ICMP connections seen since last stats interval. ', + name: 'zeek.stats.connections.icmp.count', + type: 'integer', + }, + 'zeek.stats.events.processed': { + category: 'zeek', + description: 'Number of events processed since the last stats interval. ', + name: 'zeek.stats.events.processed', + type: 'integer', + }, + 'zeek.stats.events.queued': { + category: 'zeek', + description: 'Number of events that have been queued since the last stats interval. ', + name: 'zeek.stats.events.queued', + type: 'integer', + }, + 'zeek.stats.timers.count': { + category: 'zeek', + description: 'Number of timers scheduled since last stats interval. ', + name: 'zeek.stats.timers.count', + type: 'integer', + }, + 'zeek.stats.timers.active': { + category: 'zeek', + description: 'Current number of scheduled timers. ', + name: 'zeek.stats.timers.active', + type: 'integer', + }, + 'zeek.stats.files.count': { + category: 'zeek', + description: 'Number of files seen since last stats interval. ', + name: 'zeek.stats.files.count', + type: 'integer', + }, + 'zeek.stats.files.active': { + category: 'zeek', + description: 'Current number of files actively being seen. ', + name: 'zeek.stats.files.active', + type: 'integer', + }, + 'zeek.stats.dns_requests.count': { + category: 'zeek', + description: 'Number of DNS requests seen since last stats interval. ', + name: 'zeek.stats.dns_requests.count', + type: 'integer', + }, + 'zeek.stats.dns_requests.active': { + category: 'zeek', + description: 'Current number of DNS requests awaiting a reply. ', + name: 'zeek.stats.dns_requests.active', + type: 'integer', + }, + 'zeek.stats.reassembly_size.tcp': { + category: 'zeek', + description: 'Current size of TCP data in reassembly. ', + name: 'zeek.stats.reassembly_size.tcp', + type: 'integer', + }, + 'zeek.stats.reassembly_size.file': { + category: 'zeek', + description: 'Current size of File data in reassembly. ', + name: 'zeek.stats.reassembly_size.file', + type: 'integer', + }, + 'zeek.stats.reassembly_size.frag': { + category: 'zeek', + description: 'Current size of packet fragment data in reassembly. ', + name: 'zeek.stats.reassembly_size.frag', + type: 'integer', + }, + 'zeek.stats.reassembly_size.unknown': { + category: 'zeek', + description: 'Current size of unknown data in reassembly (this is only PIA buffer right now). ', + name: 'zeek.stats.reassembly_size.unknown', + type: 'integer', + }, + 'zeek.stats.timestamp_lag': { + category: 'zeek', + description: 'Lag between the wall clock and packet timestamps if reading live traffic. ', + name: 'zeek.stats.timestamp_lag', + type: 'integer', + }, + 'zeek.syslog.facility': { + category: 'zeek', + description: 'Syslog facility for the message. ', + name: 'zeek.syslog.facility', + type: 'keyword', + }, + 'zeek.syslog.severity': { + category: 'zeek', + description: 'Syslog severity for the message. ', + name: 'zeek.syslog.severity', + type: 'keyword', + }, + 'zeek.syslog.message': { + category: 'zeek', + description: 'The plain text message. ', + name: 'zeek.syslog.message', + type: 'keyword', + }, + 'zeek.tunnel.type': { + category: 'zeek', + description: 'The type of tunnel. ', + name: 'zeek.tunnel.type', + type: 'keyword', + }, + 'zeek.tunnel.action': { + category: 'zeek', + description: 'The type of activity that occurred. ', + name: 'zeek.tunnel.action', + type: 'keyword', + }, + 'zeek.weird.name': { + category: 'zeek', + description: 'The name of the weird that occurred. ', + name: 'zeek.weird.name', + type: 'keyword', + }, + 'zeek.weird.additional_info': { + category: 'zeek', + description: 'Additional information accompanying the weird if any. ', + name: 'zeek.weird.additional_info', + type: 'keyword', + }, + 'zeek.weird.notice': { + category: 'zeek', + description: 'Indicate if this weird was also turned into a notice. ', + name: 'zeek.weird.notice', + type: 'boolean', + }, + 'zeek.weird.peer': { + category: 'zeek', + description: + 'The peer that originated this weird. This is helpful in cluster deployments if a particular cluster node is having trouble to help identify which node is having trouble. ', + name: 'zeek.weird.peer', + type: 'keyword', + }, + 'zeek.weird.identifier': { + category: 'zeek', + description: + 'This field is to be provided when a weird is generated for the purpose of deduplicating weirds. The identifier string should be unique for a single instance of the weird. This field is used to define when a weird is conceptually a duplicate of a previous weird. ', + name: 'zeek.weird.identifier', + type: 'keyword', + }, + 'zeek.x509.id': { + category: 'zeek', + description: 'File id of this certificate. ', + name: 'zeek.x509.id', + type: 'keyword', + }, + 'zeek.x509.certificate.version': { + category: 'zeek', + description: 'Version number. ', + name: 'zeek.x509.certificate.version', + type: 'integer', + }, + 'zeek.x509.certificate.serial': { + category: 'zeek', + description: 'Serial number. ', + name: 'zeek.x509.certificate.serial', + type: 'keyword', + }, + 'zeek.x509.certificate.subject.country': { + category: 'zeek', + description: 'Country provided in the certificate subject. ', + name: 'zeek.x509.certificate.subject.country', + type: 'keyword', + }, + 'zeek.x509.certificate.subject.common_name': { + category: 'zeek', + description: 'Common name provided in the certificate subject. ', + name: 'zeek.x509.certificate.subject.common_name', + type: 'keyword', + }, + 'zeek.x509.certificate.subject.locality': { + category: 'zeek', + description: 'Locality provided in the certificate subject. ', + name: 'zeek.x509.certificate.subject.locality', + type: 'keyword', + }, + 'zeek.x509.certificate.subject.organization': { + category: 'zeek', + description: 'Organization provided in the certificate subject. ', + name: 'zeek.x509.certificate.subject.organization', + type: 'keyword', + }, + 'zeek.x509.certificate.subject.organizational_unit': { + category: 'zeek', + description: 'Organizational unit provided in the certificate subject. ', + name: 'zeek.x509.certificate.subject.organizational_unit', + type: 'keyword', + }, + 'zeek.x509.certificate.subject.state': { + category: 'zeek', + description: 'State or province provided in the certificate subject. ', + name: 'zeek.x509.certificate.subject.state', + type: 'keyword', + }, + 'zeek.x509.certificate.issuer.country': { + category: 'zeek', + description: 'Country provided in the certificate issuer field. ', + name: 'zeek.x509.certificate.issuer.country', + type: 'keyword', + }, + 'zeek.x509.certificate.issuer.common_name': { + category: 'zeek', + description: 'Common name provided in the certificate issuer field. ', + name: 'zeek.x509.certificate.issuer.common_name', + type: 'keyword', + }, + 'zeek.x509.certificate.issuer.locality': { + category: 'zeek', + description: 'Locality provided in the certificate issuer field. ', + name: 'zeek.x509.certificate.issuer.locality', + type: 'keyword', + }, + 'zeek.x509.certificate.issuer.organization': { + category: 'zeek', + description: 'Organization provided in the certificate issuer field. ', + name: 'zeek.x509.certificate.issuer.organization', + type: 'keyword', + }, + 'zeek.x509.certificate.issuer.organizational_unit': { + category: 'zeek', + description: 'Organizational unit provided in the certificate issuer field. ', + name: 'zeek.x509.certificate.issuer.organizational_unit', + type: 'keyword', + }, + 'zeek.x509.certificate.issuer.state': { + category: 'zeek', + description: 'State or province provided in the certificate issuer field. ', + name: 'zeek.x509.certificate.issuer.state', + type: 'keyword', + }, + 'zeek.x509.certificate.common_name': { + category: 'zeek', + description: 'Last (most specific) common name. ', + name: 'zeek.x509.certificate.common_name', + type: 'keyword', + }, + 'zeek.x509.certificate.valid.from': { + category: 'zeek', + description: 'Timestamp before when certificate is not valid. ', + name: 'zeek.x509.certificate.valid.from', + type: 'date', + }, + 'zeek.x509.certificate.valid.until': { + category: 'zeek', + description: 'Timestamp after when certificate is not valid. ', + name: 'zeek.x509.certificate.valid.until', + type: 'date', + }, + 'zeek.x509.certificate.key.algorithm': { + category: 'zeek', + description: 'Name of the key algorithm. ', + name: 'zeek.x509.certificate.key.algorithm', + type: 'keyword', + }, + 'zeek.x509.certificate.key.type': { + category: 'zeek', + description: 'Key type, if key parseable by openssl (either rsa, dsa or ec). ', + name: 'zeek.x509.certificate.key.type', + type: 'keyword', + }, + 'zeek.x509.certificate.key.length': { + category: 'zeek', + description: 'Key length in bits. ', + name: 'zeek.x509.certificate.key.length', + type: 'integer', + }, + 'zeek.x509.certificate.signature_algorithm': { + category: 'zeek', + description: 'Name of the signature algorithm. ', + name: 'zeek.x509.certificate.signature_algorithm', + type: 'keyword', + }, + 'zeek.x509.certificate.exponent': { + category: 'zeek', + description: 'Exponent, if RSA-certificate. ', + name: 'zeek.x509.certificate.exponent', + type: 'keyword', + }, + 'zeek.x509.certificate.curve': { + category: 'zeek', + description: 'Curve, if EC-certificate. ', + name: 'zeek.x509.certificate.curve', + type: 'keyword', + }, + 'zeek.x509.san.dns': { + category: 'zeek', + description: 'List of DNS entries in SAN. ', + name: 'zeek.x509.san.dns', + type: 'keyword', + }, + 'zeek.x509.san.uri': { + category: 'zeek', + description: 'List of URI entries in SAN. ', + name: 'zeek.x509.san.uri', + type: 'keyword', + }, + 'zeek.x509.san.email': { + category: 'zeek', + description: 'List of email entries in SAN. ', + name: 'zeek.x509.san.email', + type: 'keyword', + }, + 'zeek.x509.san.ip': { + category: 'zeek', + description: 'List of IP entries in SAN. ', + name: 'zeek.x509.san.ip', + type: 'ip', + }, + 'zeek.x509.san.other_fields': { + category: 'zeek', + description: 'True if the certificate contained other, not recognized or parsed name fields. ', + name: 'zeek.x509.san.other_fields', + type: 'boolean', + }, + 'zeek.x509.basic_constraints.certificate_authority': { + category: 'zeek', + description: 'CA flag set or not. ', + name: 'zeek.x509.basic_constraints.certificate_authority', + type: 'boolean', + }, + 'zeek.x509.basic_constraints.path_length': { + category: 'zeek', + description: 'Maximum path length. ', + name: 'zeek.x509.basic_constraints.path_length', + type: 'integer', + }, + 'zeek.x509.log_cert': { + category: 'zeek', + description: + 'Present if policy/protocols/ssl/log-hostcerts-only.bro is loaded Logging of certificate is suppressed if set to F. ', + name: 'zeek.x509.log_cert', + type: 'boolean', + }, + 'awscloudwatch.log_group': { + category: 'awscloudwatch', + description: 'The name of the log group to which this event belongs.', + name: 'awscloudwatch.log_group', + type: 'keyword', + }, + 'awscloudwatch.log_stream': { + category: 'awscloudwatch', + description: 'The name of the log stream to which this event belongs.', + name: 'awscloudwatch.log_stream', + type: 'keyword', + }, + 'awscloudwatch.ingestion_time': { + category: 'awscloudwatch', + description: 'The time the event was ingested in AWS CloudWatch.', + name: 'awscloudwatch.ingestion_time', + type: 'keyword', + }, + 'netflow.type': { + category: 'netflow', + description: 'The type of NetFlow record described by this event. ', + name: 'netflow.type', + type: 'keyword', + }, + 'netflow.exporter.address': { + category: 'netflow', + description: "Exporter's network address in IP:port format. ", + name: 'netflow.exporter.address', + type: 'keyword', + }, + 'netflow.exporter.source_id': { + category: 'netflow', + description: 'Observation domain ID to which this record belongs. ', + name: 'netflow.exporter.source_id', + type: 'long', + }, + 'netflow.exporter.timestamp': { + category: 'netflow', + description: 'Time and date of export. ', + name: 'netflow.exporter.timestamp', + type: 'date', + }, + 'netflow.exporter.uptime_millis': { + category: 'netflow', + description: 'How long the exporter process has been running, in milliseconds. ', + name: 'netflow.exporter.uptime_millis', + type: 'long', + }, + 'netflow.exporter.version': { + category: 'netflow', + description: 'NetFlow version used. ', + name: 'netflow.exporter.version', + type: 'integer', + }, + 'netflow.octet_delta_count': { + category: 'netflow', + name: 'netflow.octet_delta_count', + type: 'long', + }, + 'netflow.packet_delta_count': { + category: 'netflow', + name: 'netflow.packet_delta_count', + type: 'long', + }, + 'netflow.delta_flow_count': { + category: 'netflow', + name: 'netflow.delta_flow_count', + type: 'long', + }, + 'netflow.protocol_identifier': { + category: 'netflow', + name: 'netflow.protocol_identifier', + type: 'short', + }, + 'netflow.ip_class_of_service': { + category: 'netflow', + name: 'netflow.ip_class_of_service', + type: 'short', + }, + 'netflow.tcp_control_bits': { + category: 'netflow', + name: 'netflow.tcp_control_bits', + type: 'integer', + }, + 'netflow.source_transport_port': { + category: 'netflow', + name: 'netflow.source_transport_port', + type: 'integer', + }, + 'netflow.source_ipv4_address': { + category: 'netflow', + name: 'netflow.source_ipv4_address', + type: 'ip', + }, + 'netflow.source_ipv4_prefix_length': { + category: 'netflow', + name: 'netflow.source_ipv4_prefix_length', + type: 'short', + }, + 'netflow.ingress_interface': { + category: 'netflow', + name: 'netflow.ingress_interface', + type: 'long', + }, + 'netflow.destination_transport_port': { + category: 'netflow', + name: 'netflow.destination_transport_port', + type: 'integer', + }, + 'netflow.destination_ipv4_address': { + category: 'netflow', + name: 'netflow.destination_ipv4_address', + type: 'ip', + }, + 'netflow.destination_ipv4_prefix_length': { + category: 'netflow', + name: 'netflow.destination_ipv4_prefix_length', + type: 'short', + }, + 'netflow.egress_interface': { + category: 'netflow', + name: 'netflow.egress_interface', + type: 'long', + }, + 'netflow.ip_next_hop_ipv4_address': { + category: 'netflow', + name: 'netflow.ip_next_hop_ipv4_address', + type: 'ip', + }, + 'netflow.bgp_source_as_number': { + category: 'netflow', + name: 'netflow.bgp_source_as_number', + type: 'long', + }, + 'netflow.bgp_destination_as_number': { + category: 'netflow', + name: 'netflow.bgp_destination_as_number', + type: 'long', + }, + 'netflow.bgp_next_hop_ipv4_address': { + category: 'netflow', + name: 'netflow.bgp_next_hop_ipv4_address', + type: 'ip', + }, + 'netflow.post_mcast_packet_delta_count': { + category: 'netflow', + name: 'netflow.post_mcast_packet_delta_count', + type: 'long', + }, + 'netflow.post_mcast_octet_delta_count': { + category: 'netflow', + name: 'netflow.post_mcast_octet_delta_count', + type: 'long', + }, + 'netflow.flow_end_sys_up_time': { + category: 'netflow', + name: 'netflow.flow_end_sys_up_time', + type: 'long', + }, + 'netflow.flow_start_sys_up_time': { + category: 'netflow', + name: 'netflow.flow_start_sys_up_time', + type: 'long', + }, + 'netflow.post_octet_delta_count': { + category: 'netflow', + name: 'netflow.post_octet_delta_count', + type: 'long', + }, + 'netflow.post_packet_delta_count': { + category: 'netflow', + name: 'netflow.post_packet_delta_count', + type: 'long', + }, + 'netflow.minimum_ip_total_length': { + category: 'netflow', + name: 'netflow.minimum_ip_total_length', + type: 'long', + }, + 'netflow.maximum_ip_total_length': { + category: 'netflow', + name: 'netflow.maximum_ip_total_length', + type: 'long', + }, + 'netflow.source_ipv6_address': { + category: 'netflow', + name: 'netflow.source_ipv6_address', + type: 'ip', + }, + 'netflow.destination_ipv6_address': { + category: 'netflow', + name: 'netflow.destination_ipv6_address', + type: 'ip', + }, + 'netflow.source_ipv6_prefix_length': { + category: 'netflow', + name: 'netflow.source_ipv6_prefix_length', + type: 'short', + }, + 'netflow.destination_ipv6_prefix_length': { + category: 'netflow', + name: 'netflow.destination_ipv6_prefix_length', + type: 'short', + }, + 'netflow.flow_label_ipv6': { + category: 'netflow', + name: 'netflow.flow_label_ipv6', + type: 'long', + }, + 'netflow.icmp_type_code_ipv4': { + category: 'netflow', + name: 'netflow.icmp_type_code_ipv4', + type: 'integer', + }, + 'netflow.igmp_type': { + category: 'netflow', + name: 'netflow.igmp_type', + type: 'short', + }, + 'netflow.sampling_interval': { + category: 'netflow', + name: 'netflow.sampling_interval', + type: 'long', + }, + 'netflow.sampling_algorithm': { + category: 'netflow', + name: 'netflow.sampling_algorithm', + type: 'short', + }, + 'netflow.flow_active_timeout': { + category: 'netflow', + name: 'netflow.flow_active_timeout', + type: 'integer', + }, + 'netflow.flow_idle_timeout': { + category: 'netflow', + name: 'netflow.flow_idle_timeout', + type: 'integer', + }, + 'netflow.engine_type': { + category: 'netflow', + name: 'netflow.engine_type', + type: 'short', + }, + 'netflow.engine_id': { + category: 'netflow', + name: 'netflow.engine_id', + type: 'short', + }, + 'netflow.exported_octet_total_count': { + category: 'netflow', + name: 'netflow.exported_octet_total_count', + type: 'long', + }, + 'netflow.exported_message_total_count': { + category: 'netflow', + name: 'netflow.exported_message_total_count', + type: 'long', + }, + 'netflow.exported_flow_record_total_count': { + category: 'netflow', + name: 'netflow.exported_flow_record_total_count', + type: 'long', + }, + 'netflow.ipv4_router_sc': { + category: 'netflow', + name: 'netflow.ipv4_router_sc', + type: 'ip', + }, + 'netflow.source_ipv4_prefix': { + category: 'netflow', + name: 'netflow.source_ipv4_prefix', + type: 'ip', + }, + 'netflow.destination_ipv4_prefix': { + category: 'netflow', + name: 'netflow.destination_ipv4_prefix', + type: 'ip', + }, + 'netflow.mpls_top_label_type': { + category: 'netflow', + name: 'netflow.mpls_top_label_type', + type: 'short', + }, + 'netflow.mpls_top_label_ipv4_address': { + category: 'netflow', + name: 'netflow.mpls_top_label_ipv4_address', + type: 'ip', + }, + 'netflow.sampler_id': { + category: 'netflow', + name: 'netflow.sampler_id', + type: 'short', + }, + 'netflow.sampler_mode': { + category: 'netflow', + name: 'netflow.sampler_mode', + type: 'short', + }, + 'netflow.sampler_random_interval': { + category: 'netflow', + name: 'netflow.sampler_random_interval', + type: 'long', + }, + 'netflow.class_id': { + category: 'netflow', + name: 'netflow.class_id', + type: 'long', + }, + 'netflow.minimum_ttl': { + category: 'netflow', + name: 'netflow.minimum_ttl', + type: 'short', + }, + 'netflow.maximum_ttl': { + category: 'netflow', + name: 'netflow.maximum_ttl', + type: 'short', + }, + 'netflow.fragment_identification': { + category: 'netflow', + name: 'netflow.fragment_identification', + type: 'long', + }, + 'netflow.post_ip_class_of_service': { + category: 'netflow', + name: 'netflow.post_ip_class_of_service', + type: 'short', + }, + 'netflow.source_mac_address': { + category: 'netflow', + name: 'netflow.source_mac_address', + type: 'keyword', + }, + 'netflow.post_destination_mac_address': { + category: 'netflow', + name: 'netflow.post_destination_mac_address', + type: 'keyword', + }, + 'netflow.vlan_id': { + category: 'netflow', + name: 'netflow.vlan_id', + type: 'integer', + }, + 'netflow.post_vlan_id': { + category: 'netflow', + name: 'netflow.post_vlan_id', + type: 'integer', + }, + 'netflow.ip_version': { + category: 'netflow', + name: 'netflow.ip_version', + type: 'short', + }, + 'netflow.flow_direction': { + category: 'netflow', + name: 'netflow.flow_direction', + type: 'short', + }, + 'netflow.ip_next_hop_ipv6_address': { + category: 'netflow', + name: 'netflow.ip_next_hop_ipv6_address', + type: 'ip', + }, + 'netflow.bgp_next_hop_ipv6_address': { + category: 'netflow', + name: 'netflow.bgp_next_hop_ipv6_address', + type: 'ip', + }, + 'netflow.ipv6_extension_headers': { + category: 'netflow', + name: 'netflow.ipv6_extension_headers', + type: 'long', + }, + 'netflow.mpls_top_label_stack_section': { + category: 'netflow', + name: 'netflow.mpls_top_label_stack_section', + type: 'short', + }, + 'netflow.mpls_label_stack_section2': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section2', + type: 'short', + }, + 'netflow.mpls_label_stack_section3': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section3', + type: 'short', + }, + 'netflow.mpls_label_stack_section4': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section4', + type: 'short', + }, + 'netflow.mpls_label_stack_section5': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section5', + type: 'short', + }, + 'netflow.mpls_label_stack_section6': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section6', + type: 'short', + }, + 'netflow.mpls_label_stack_section7': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section7', + type: 'short', + }, + 'netflow.mpls_label_stack_section8': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section8', + type: 'short', + }, + 'netflow.mpls_label_stack_section9': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section9', + type: 'short', + }, + 'netflow.mpls_label_stack_section10': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section10', + type: 'short', + }, + 'netflow.destination_mac_address': { + category: 'netflow', + name: 'netflow.destination_mac_address', + type: 'keyword', + }, + 'netflow.post_source_mac_address': { + category: 'netflow', + name: 'netflow.post_source_mac_address', + type: 'keyword', + }, + 'netflow.interface_name': { + category: 'netflow', + name: 'netflow.interface_name', + type: 'keyword', + }, + 'netflow.interface_description': { + category: 'netflow', + name: 'netflow.interface_description', + type: 'keyword', + }, + 'netflow.sampler_name': { + category: 'netflow', + name: 'netflow.sampler_name', + type: 'keyword', + }, + 'netflow.octet_total_count': { + category: 'netflow', + name: 'netflow.octet_total_count', + type: 'long', + }, + 'netflow.packet_total_count': { + category: 'netflow', + name: 'netflow.packet_total_count', + type: 'long', + }, + 'netflow.flags_and_sampler_id': { + category: 'netflow', + name: 'netflow.flags_and_sampler_id', + type: 'long', + }, + 'netflow.fragment_offset': { + category: 'netflow', + name: 'netflow.fragment_offset', + type: 'integer', + }, + 'netflow.forwarding_status': { + category: 'netflow', + name: 'netflow.forwarding_status', + type: 'short', + }, + 'netflow.mpls_vpn_route_distinguisher': { + category: 'netflow', + name: 'netflow.mpls_vpn_route_distinguisher', + type: 'short', + }, + 'netflow.mpls_top_label_prefix_length': { + category: 'netflow', + name: 'netflow.mpls_top_label_prefix_length', + type: 'short', + }, + 'netflow.src_traffic_index': { + category: 'netflow', + name: 'netflow.src_traffic_index', + type: 'long', + }, + 'netflow.dst_traffic_index': { + category: 'netflow', + name: 'netflow.dst_traffic_index', + type: 'long', + }, + 'netflow.application_description': { + category: 'netflow', + name: 'netflow.application_description', + type: 'keyword', + }, + 'netflow.application_id': { + category: 'netflow', + name: 'netflow.application_id', + type: 'short', + }, + 'netflow.application_name': { + category: 'netflow', + name: 'netflow.application_name', + type: 'keyword', + }, + 'netflow.post_ip_diff_serv_code_point': { + category: 'netflow', + name: 'netflow.post_ip_diff_serv_code_point', + type: 'short', + }, + 'netflow.multicast_replication_factor': { + category: 'netflow', + name: 'netflow.multicast_replication_factor', + type: 'long', + }, + 'netflow.class_name': { + category: 'netflow', + name: 'netflow.class_name', + type: 'keyword', + }, + 'netflow.classification_engine_id': { + category: 'netflow', + name: 'netflow.classification_engine_id', + type: 'short', + }, + 'netflow.layer2packet_section_offset': { + category: 'netflow', + name: 'netflow.layer2packet_section_offset', + type: 'integer', + }, + 'netflow.layer2packet_section_size': { + category: 'netflow', + name: 'netflow.layer2packet_section_size', + type: 'integer', + }, + 'netflow.layer2packet_section_data': { + category: 'netflow', + name: 'netflow.layer2packet_section_data', + type: 'short', + }, + 'netflow.bgp_next_adjacent_as_number': { + category: 'netflow', + name: 'netflow.bgp_next_adjacent_as_number', + type: 'long', + }, + 'netflow.bgp_prev_adjacent_as_number': { + category: 'netflow', + name: 'netflow.bgp_prev_adjacent_as_number', + type: 'long', + }, + 'netflow.exporter_ipv4_address': { + category: 'netflow', + name: 'netflow.exporter_ipv4_address', + type: 'ip', + }, + 'netflow.exporter_ipv6_address': { + category: 'netflow', + name: 'netflow.exporter_ipv6_address', + type: 'ip', + }, + 'netflow.dropped_octet_delta_count': { + category: 'netflow', + name: 'netflow.dropped_octet_delta_count', + type: 'long', + }, + 'netflow.dropped_packet_delta_count': { + category: 'netflow', + name: 'netflow.dropped_packet_delta_count', + type: 'long', + }, + 'netflow.dropped_octet_total_count': { + category: 'netflow', + name: 'netflow.dropped_octet_total_count', + type: 'long', + }, + 'netflow.dropped_packet_total_count': { + category: 'netflow', + name: 'netflow.dropped_packet_total_count', + type: 'long', + }, + 'netflow.flow_end_reason': { + category: 'netflow', + name: 'netflow.flow_end_reason', + type: 'short', + }, + 'netflow.common_properties_id': { + category: 'netflow', + name: 'netflow.common_properties_id', + type: 'long', + }, + 'netflow.observation_point_id': { + category: 'netflow', + name: 'netflow.observation_point_id', + type: 'long', + }, + 'netflow.icmp_type_code_ipv6': { + category: 'netflow', + name: 'netflow.icmp_type_code_ipv6', + type: 'integer', + }, + 'netflow.mpls_top_label_ipv6_address': { + category: 'netflow', + name: 'netflow.mpls_top_label_ipv6_address', + type: 'ip', + }, + 'netflow.line_card_id': { + category: 'netflow', + name: 'netflow.line_card_id', + type: 'long', + }, + 'netflow.port_id': { + category: 'netflow', + name: 'netflow.port_id', + type: 'long', + }, + 'netflow.metering_process_id': { + category: 'netflow', + name: 'netflow.metering_process_id', + type: 'long', + }, + 'netflow.exporting_process_id': { + category: 'netflow', + name: 'netflow.exporting_process_id', + type: 'long', + }, + 'netflow.template_id': { + category: 'netflow', + name: 'netflow.template_id', + type: 'integer', + }, + 'netflow.wlan_channel_id': { + category: 'netflow', + name: 'netflow.wlan_channel_id', + type: 'short', + }, + 'netflow.wlan_ssid': { + category: 'netflow', + name: 'netflow.wlan_ssid', + type: 'keyword', + }, + 'netflow.flow_id': { + category: 'netflow', + name: 'netflow.flow_id', + type: 'long', + }, + 'netflow.observation_domain_id': { + category: 'netflow', + name: 'netflow.observation_domain_id', + type: 'long', + }, + 'netflow.flow_start_seconds': { + category: 'netflow', + name: 'netflow.flow_start_seconds', + type: 'date', + }, + 'netflow.flow_end_seconds': { + category: 'netflow', + name: 'netflow.flow_end_seconds', + type: 'date', + }, + 'netflow.flow_start_milliseconds': { + category: 'netflow', + name: 'netflow.flow_start_milliseconds', + type: 'date', + }, + 'netflow.flow_end_milliseconds': { + category: 'netflow', + name: 'netflow.flow_end_milliseconds', + type: 'date', + }, + 'netflow.flow_start_microseconds': { + category: 'netflow', + name: 'netflow.flow_start_microseconds', + type: 'date', + }, + 'netflow.flow_end_microseconds': { + category: 'netflow', + name: 'netflow.flow_end_microseconds', + type: 'date', + }, + 'netflow.flow_start_nanoseconds': { + category: 'netflow', + name: 'netflow.flow_start_nanoseconds', + type: 'date', + }, + 'netflow.flow_end_nanoseconds': { + category: 'netflow', + name: 'netflow.flow_end_nanoseconds', + type: 'date', + }, + 'netflow.flow_start_delta_microseconds': { + category: 'netflow', + name: 'netflow.flow_start_delta_microseconds', + type: 'long', + }, + 'netflow.flow_end_delta_microseconds': { + category: 'netflow', + name: 'netflow.flow_end_delta_microseconds', + type: 'long', + }, + 'netflow.system_init_time_milliseconds': { + category: 'netflow', + name: 'netflow.system_init_time_milliseconds', + type: 'date', + }, + 'netflow.flow_duration_milliseconds': { + category: 'netflow', + name: 'netflow.flow_duration_milliseconds', + type: 'long', + }, + 'netflow.flow_duration_microseconds': { + category: 'netflow', + name: 'netflow.flow_duration_microseconds', + type: 'long', + }, + 'netflow.observed_flow_total_count': { + category: 'netflow', + name: 'netflow.observed_flow_total_count', + type: 'long', + }, + 'netflow.ignored_packet_total_count': { + category: 'netflow', + name: 'netflow.ignored_packet_total_count', + type: 'long', + }, + 'netflow.ignored_octet_total_count': { + category: 'netflow', + name: 'netflow.ignored_octet_total_count', + type: 'long', + }, + 'netflow.not_sent_flow_total_count': { + category: 'netflow', + name: 'netflow.not_sent_flow_total_count', + type: 'long', + }, + 'netflow.not_sent_packet_total_count': { + category: 'netflow', + name: 'netflow.not_sent_packet_total_count', + type: 'long', + }, + 'netflow.not_sent_octet_total_count': { + category: 'netflow', + name: 'netflow.not_sent_octet_total_count', + type: 'long', + }, + 'netflow.destination_ipv6_prefix': { + category: 'netflow', + name: 'netflow.destination_ipv6_prefix', + type: 'ip', + }, + 'netflow.source_ipv6_prefix': { + category: 'netflow', + name: 'netflow.source_ipv6_prefix', + type: 'ip', + }, + 'netflow.post_octet_total_count': { + category: 'netflow', + name: 'netflow.post_octet_total_count', + type: 'long', + }, + 'netflow.post_packet_total_count': { + category: 'netflow', + name: 'netflow.post_packet_total_count', + type: 'long', + }, + 'netflow.flow_key_indicator': { + category: 'netflow', + name: 'netflow.flow_key_indicator', + type: 'long', + }, + 'netflow.post_mcast_packet_total_count': { + category: 'netflow', + name: 'netflow.post_mcast_packet_total_count', + type: 'long', + }, + 'netflow.post_mcast_octet_total_count': { + category: 'netflow', + name: 'netflow.post_mcast_octet_total_count', + type: 'long', + }, + 'netflow.icmp_type_ipv4': { + category: 'netflow', + name: 'netflow.icmp_type_ipv4', + type: 'short', + }, + 'netflow.icmp_code_ipv4': { + category: 'netflow', + name: 'netflow.icmp_code_ipv4', + type: 'short', + }, + 'netflow.icmp_type_ipv6': { + category: 'netflow', + name: 'netflow.icmp_type_ipv6', + type: 'short', + }, + 'netflow.icmp_code_ipv6': { + category: 'netflow', + name: 'netflow.icmp_code_ipv6', + type: 'short', + }, + 'netflow.udp_source_port': { + category: 'netflow', + name: 'netflow.udp_source_port', + type: 'integer', + }, + 'netflow.udp_destination_port': { + category: 'netflow', + name: 'netflow.udp_destination_port', + type: 'integer', + }, + 'netflow.tcp_source_port': { + category: 'netflow', + name: 'netflow.tcp_source_port', + type: 'integer', + }, + 'netflow.tcp_destination_port': { + category: 'netflow', + name: 'netflow.tcp_destination_port', + type: 'integer', + }, + 'netflow.tcp_sequence_number': { + category: 'netflow', + name: 'netflow.tcp_sequence_number', + type: 'long', + }, + 'netflow.tcp_acknowledgement_number': { + category: 'netflow', + name: 'netflow.tcp_acknowledgement_number', + type: 'long', + }, + 'netflow.tcp_window_size': { + category: 'netflow', + name: 'netflow.tcp_window_size', + type: 'integer', + }, + 'netflow.tcp_urgent_pointer': { + category: 'netflow', + name: 'netflow.tcp_urgent_pointer', + type: 'integer', + }, + 'netflow.tcp_header_length': { + category: 'netflow', + name: 'netflow.tcp_header_length', + type: 'short', + }, + 'netflow.ip_header_length': { + category: 'netflow', + name: 'netflow.ip_header_length', + type: 'short', + }, + 'netflow.total_length_ipv4': { + category: 'netflow', + name: 'netflow.total_length_ipv4', + type: 'integer', + }, + 'netflow.payload_length_ipv6': { + category: 'netflow', + name: 'netflow.payload_length_ipv6', + type: 'integer', + }, + 'netflow.ip_ttl': { + category: 'netflow', + name: 'netflow.ip_ttl', + type: 'short', + }, + 'netflow.next_header_ipv6': { + category: 'netflow', + name: 'netflow.next_header_ipv6', + type: 'short', + }, + 'netflow.mpls_payload_length': { + category: 'netflow', + name: 'netflow.mpls_payload_length', + type: 'long', + }, + 'netflow.ip_diff_serv_code_point': { + category: 'netflow', + name: 'netflow.ip_diff_serv_code_point', + type: 'short', + }, + 'netflow.ip_precedence': { + category: 'netflow', + name: 'netflow.ip_precedence', + type: 'short', + }, + 'netflow.fragment_flags': { + category: 'netflow', + name: 'netflow.fragment_flags', + type: 'short', + }, + 'netflow.octet_delta_sum_of_squares': { + category: 'netflow', + name: 'netflow.octet_delta_sum_of_squares', + type: 'long', + }, + 'netflow.octet_total_sum_of_squares': { + category: 'netflow', + name: 'netflow.octet_total_sum_of_squares', + type: 'long', + }, + 'netflow.mpls_top_label_ttl': { + category: 'netflow', + name: 'netflow.mpls_top_label_ttl', + type: 'short', + }, + 'netflow.mpls_label_stack_length': { + category: 'netflow', + name: 'netflow.mpls_label_stack_length', + type: 'long', + }, + 'netflow.mpls_label_stack_depth': { + category: 'netflow', + name: 'netflow.mpls_label_stack_depth', + type: 'long', + }, + 'netflow.mpls_top_label_exp': { + category: 'netflow', + name: 'netflow.mpls_top_label_exp', + type: 'short', + }, + 'netflow.ip_payload_length': { + category: 'netflow', + name: 'netflow.ip_payload_length', + type: 'long', + }, + 'netflow.udp_message_length': { + category: 'netflow', + name: 'netflow.udp_message_length', + type: 'integer', + }, + 'netflow.is_multicast': { + category: 'netflow', + name: 'netflow.is_multicast', + type: 'short', + }, + 'netflow.ipv4_ihl': { + category: 'netflow', + name: 'netflow.ipv4_ihl', + type: 'short', + }, + 'netflow.ipv4_options': { + category: 'netflow', + name: 'netflow.ipv4_options', + type: 'long', + }, + 'netflow.tcp_options': { + category: 'netflow', + name: 'netflow.tcp_options', + type: 'long', + }, + 'netflow.padding_octets': { + category: 'netflow', + name: 'netflow.padding_octets', + type: 'short', + }, + 'netflow.collector_ipv4_address': { + category: 'netflow', + name: 'netflow.collector_ipv4_address', + type: 'ip', + }, + 'netflow.collector_ipv6_address': { + category: 'netflow', + name: 'netflow.collector_ipv6_address', + type: 'ip', + }, + 'netflow.export_interface': { + category: 'netflow', + name: 'netflow.export_interface', + type: 'long', + }, + 'netflow.export_protocol_version': { + category: 'netflow', + name: 'netflow.export_protocol_version', + type: 'short', + }, + 'netflow.export_transport_protocol': { + category: 'netflow', + name: 'netflow.export_transport_protocol', + type: 'short', + }, + 'netflow.collector_transport_port': { + category: 'netflow', + name: 'netflow.collector_transport_port', + type: 'integer', + }, + 'netflow.exporter_transport_port': { + category: 'netflow', + name: 'netflow.exporter_transport_port', + type: 'integer', + }, + 'netflow.tcp_syn_total_count': { + category: 'netflow', + name: 'netflow.tcp_syn_total_count', + type: 'long', + }, + 'netflow.tcp_fin_total_count': { + category: 'netflow', + name: 'netflow.tcp_fin_total_count', + type: 'long', + }, + 'netflow.tcp_rst_total_count': { + category: 'netflow', + name: 'netflow.tcp_rst_total_count', + type: 'long', + }, + 'netflow.tcp_psh_total_count': { + category: 'netflow', + name: 'netflow.tcp_psh_total_count', + type: 'long', + }, + 'netflow.tcp_ack_total_count': { + category: 'netflow', + name: 'netflow.tcp_ack_total_count', + type: 'long', + }, + 'netflow.tcp_urg_total_count': { + category: 'netflow', + name: 'netflow.tcp_urg_total_count', + type: 'long', + }, + 'netflow.ip_total_length': { + category: 'netflow', + name: 'netflow.ip_total_length', + type: 'long', + }, + 'netflow.post_nat_source_ipv4_address': { + category: 'netflow', + name: 'netflow.post_nat_source_ipv4_address', + type: 'ip', + }, + 'netflow.post_nat_destination_ipv4_address': { + category: 'netflow', + name: 'netflow.post_nat_destination_ipv4_address', + type: 'ip', + }, + 'netflow.post_napt_source_transport_port': { + category: 'netflow', + name: 'netflow.post_napt_source_transport_port', + type: 'integer', + }, + 'netflow.post_napt_destination_transport_port': { + category: 'netflow', + name: 'netflow.post_napt_destination_transport_port', + type: 'integer', + }, + 'netflow.nat_originating_address_realm': { + category: 'netflow', + name: 'netflow.nat_originating_address_realm', + type: 'short', + }, + 'netflow.nat_event': { + category: 'netflow', + name: 'netflow.nat_event', + type: 'short', + }, + 'netflow.initiator_octets': { + category: 'netflow', + name: 'netflow.initiator_octets', + type: 'long', + }, + 'netflow.responder_octets': { + category: 'netflow', + name: 'netflow.responder_octets', + type: 'long', + }, + 'netflow.firewall_event': { + category: 'netflow', + name: 'netflow.firewall_event', + type: 'short', + }, + 'netflow.ingress_vrfid': { + category: 'netflow', + name: 'netflow.ingress_vrfid', + type: 'long', + }, + 'netflow.egress_vrfid': { + category: 'netflow', + name: 'netflow.egress_vrfid', + type: 'long', + }, + 'netflow.vr_fname': { + category: 'netflow', + name: 'netflow.vr_fname', + type: 'keyword', + }, + 'netflow.post_mpls_top_label_exp': { + category: 'netflow', + name: 'netflow.post_mpls_top_label_exp', + type: 'short', + }, + 'netflow.tcp_window_scale': { + category: 'netflow', + name: 'netflow.tcp_window_scale', + type: 'integer', + }, + 'netflow.biflow_direction': { + category: 'netflow', + name: 'netflow.biflow_direction', + type: 'short', + }, + 'netflow.ethernet_header_length': { + category: 'netflow', + name: 'netflow.ethernet_header_length', + type: 'short', + }, + 'netflow.ethernet_payload_length': { + category: 'netflow', + name: 'netflow.ethernet_payload_length', + type: 'integer', + }, + 'netflow.ethernet_total_length': { + category: 'netflow', + name: 'netflow.ethernet_total_length', + type: 'integer', + }, + 'netflow.dot1q_vlan_id': { + category: 'netflow', + name: 'netflow.dot1q_vlan_id', + type: 'integer', + }, + 'netflow.dot1q_priority': { + category: 'netflow', + name: 'netflow.dot1q_priority', + type: 'short', + }, + 'netflow.dot1q_customer_vlan_id': { + category: 'netflow', + name: 'netflow.dot1q_customer_vlan_id', + type: 'integer', + }, + 'netflow.dot1q_customer_priority': { + category: 'netflow', + name: 'netflow.dot1q_customer_priority', + type: 'short', + }, + 'netflow.metro_evc_id': { + category: 'netflow', + name: 'netflow.metro_evc_id', + type: 'keyword', + }, + 'netflow.metro_evc_type': { + category: 'netflow', + name: 'netflow.metro_evc_type', + type: 'short', + }, + 'netflow.pseudo_wire_id': { + category: 'netflow', + name: 'netflow.pseudo_wire_id', + type: 'long', + }, + 'netflow.pseudo_wire_type': { + category: 'netflow', + name: 'netflow.pseudo_wire_type', + type: 'integer', + }, + 'netflow.pseudo_wire_control_word': { + category: 'netflow', + name: 'netflow.pseudo_wire_control_word', + type: 'long', + }, + 'netflow.ingress_physical_interface': { + category: 'netflow', + name: 'netflow.ingress_physical_interface', + type: 'long', + }, + 'netflow.egress_physical_interface': { + category: 'netflow', + name: 'netflow.egress_physical_interface', + type: 'long', + }, + 'netflow.post_dot1q_vlan_id': { + category: 'netflow', + name: 'netflow.post_dot1q_vlan_id', + type: 'integer', + }, + 'netflow.post_dot1q_customer_vlan_id': { + category: 'netflow', + name: 'netflow.post_dot1q_customer_vlan_id', + type: 'integer', + }, + 'netflow.ethernet_type': { + category: 'netflow', + name: 'netflow.ethernet_type', + type: 'integer', + }, + 'netflow.post_ip_precedence': { + category: 'netflow', + name: 'netflow.post_ip_precedence', + type: 'short', + }, + 'netflow.collection_time_milliseconds': { + category: 'netflow', + name: 'netflow.collection_time_milliseconds', + type: 'date', + }, + 'netflow.export_sctp_stream_id': { + category: 'netflow', + name: 'netflow.export_sctp_stream_id', + type: 'integer', + }, + 'netflow.max_export_seconds': { + category: 'netflow', + name: 'netflow.max_export_seconds', + type: 'date', + }, + 'netflow.max_flow_end_seconds': { + category: 'netflow', + name: 'netflow.max_flow_end_seconds', + type: 'date', + }, + 'netflow.message_md5_checksum': { + category: 'netflow', + name: 'netflow.message_md5_checksum', + type: 'short', + }, + 'netflow.message_scope': { + category: 'netflow', + name: 'netflow.message_scope', + type: 'short', + }, + 'netflow.min_export_seconds': { + category: 'netflow', + name: 'netflow.min_export_seconds', + type: 'date', + }, + 'netflow.min_flow_start_seconds': { + category: 'netflow', + name: 'netflow.min_flow_start_seconds', + type: 'date', + }, + 'netflow.opaque_octets': { + category: 'netflow', + name: 'netflow.opaque_octets', + type: 'short', + }, + 'netflow.session_scope': { + category: 'netflow', + name: 'netflow.session_scope', + type: 'short', + }, + 'netflow.max_flow_end_microseconds': { + category: 'netflow', + name: 'netflow.max_flow_end_microseconds', + type: 'date', + }, + 'netflow.max_flow_end_milliseconds': { + category: 'netflow', + name: 'netflow.max_flow_end_milliseconds', + type: 'date', + }, + 'netflow.max_flow_end_nanoseconds': { + category: 'netflow', + name: 'netflow.max_flow_end_nanoseconds', + type: 'date', + }, + 'netflow.min_flow_start_microseconds': { + category: 'netflow', + name: 'netflow.min_flow_start_microseconds', + type: 'date', + }, + 'netflow.min_flow_start_milliseconds': { + category: 'netflow', + name: 'netflow.min_flow_start_milliseconds', + type: 'date', + }, + 'netflow.min_flow_start_nanoseconds': { + category: 'netflow', + name: 'netflow.min_flow_start_nanoseconds', + type: 'date', + }, + 'netflow.collector_certificate': { + category: 'netflow', + name: 'netflow.collector_certificate', + type: 'short', + }, + 'netflow.exporter_certificate': { + category: 'netflow', + name: 'netflow.exporter_certificate', + type: 'short', + }, + 'netflow.data_records_reliability': { + category: 'netflow', + name: 'netflow.data_records_reliability', + type: 'boolean', + }, + 'netflow.observation_point_type': { + category: 'netflow', + name: 'netflow.observation_point_type', + type: 'short', + }, + 'netflow.new_connection_delta_count': { + category: 'netflow', + name: 'netflow.new_connection_delta_count', + type: 'long', + }, + 'netflow.connection_sum_duration_seconds': { + category: 'netflow', + name: 'netflow.connection_sum_duration_seconds', + type: 'long', + }, + 'netflow.connection_transaction_id': { + category: 'netflow', + name: 'netflow.connection_transaction_id', + type: 'long', + }, + 'netflow.post_nat_source_ipv6_address': { + category: 'netflow', + name: 'netflow.post_nat_source_ipv6_address', + type: 'ip', + }, + 'netflow.post_nat_destination_ipv6_address': { + category: 'netflow', + name: 'netflow.post_nat_destination_ipv6_address', + type: 'ip', + }, + 'netflow.nat_pool_id': { + category: 'netflow', + name: 'netflow.nat_pool_id', + type: 'long', + }, + 'netflow.nat_pool_name': { + category: 'netflow', + name: 'netflow.nat_pool_name', + type: 'keyword', + }, + 'netflow.anonymization_flags': { + category: 'netflow', + name: 'netflow.anonymization_flags', + type: 'integer', + }, + 'netflow.anonymization_technique': { + category: 'netflow', + name: 'netflow.anonymization_technique', + type: 'integer', + }, + 'netflow.information_element_index': { + category: 'netflow', + name: 'netflow.information_element_index', + type: 'integer', + }, + 'netflow.p2p_technology': { + category: 'netflow', + name: 'netflow.p2p_technology', + type: 'keyword', + }, + 'netflow.tunnel_technology': { + category: 'netflow', + name: 'netflow.tunnel_technology', + type: 'keyword', + }, + 'netflow.encrypted_technology': { + category: 'netflow', + name: 'netflow.encrypted_technology', + type: 'keyword', + }, + 'netflow.bgp_validity_state': { + category: 'netflow', + name: 'netflow.bgp_validity_state', + type: 'short', + }, + 'netflow.ip_sec_spi': { + category: 'netflow', + name: 'netflow.ip_sec_spi', + type: 'long', + }, + 'netflow.gre_key': { + category: 'netflow', + name: 'netflow.gre_key', + type: 'long', + }, + 'netflow.nat_type': { + category: 'netflow', + name: 'netflow.nat_type', + type: 'short', + }, + 'netflow.initiator_packets': { + category: 'netflow', + name: 'netflow.initiator_packets', + type: 'long', + }, + 'netflow.responder_packets': { + category: 'netflow', + name: 'netflow.responder_packets', + type: 'long', + }, + 'netflow.observation_domain_name': { + category: 'netflow', + name: 'netflow.observation_domain_name', + type: 'keyword', + }, + 'netflow.selection_sequence_id': { + category: 'netflow', + name: 'netflow.selection_sequence_id', + type: 'long', + }, + 'netflow.selector_id': { + category: 'netflow', + name: 'netflow.selector_id', + type: 'long', + }, + 'netflow.information_element_id': { + category: 'netflow', + name: 'netflow.information_element_id', + type: 'integer', + }, + 'netflow.selector_algorithm': { + category: 'netflow', + name: 'netflow.selector_algorithm', + type: 'integer', + }, + 'netflow.sampling_packet_interval': { + category: 'netflow', + name: 'netflow.sampling_packet_interval', + type: 'long', + }, + 'netflow.sampling_packet_space': { + category: 'netflow', + name: 'netflow.sampling_packet_space', + type: 'long', + }, + 'netflow.sampling_time_interval': { + category: 'netflow', + name: 'netflow.sampling_time_interval', + type: 'long', + }, + 'netflow.sampling_time_space': { + category: 'netflow', + name: 'netflow.sampling_time_space', + type: 'long', + }, + 'netflow.sampling_size': { + category: 'netflow', + name: 'netflow.sampling_size', + type: 'long', + }, + 'netflow.sampling_population': { + category: 'netflow', + name: 'netflow.sampling_population', + type: 'long', + }, + 'netflow.sampling_probability': { + category: 'netflow', + name: 'netflow.sampling_probability', + type: 'double', + }, + 'netflow.data_link_frame_size': { + category: 'netflow', + name: 'netflow.data_link_frame_size', + type: 'integer', + }, + 'netflow.ip_header_packet_section': { + category: 'netflow', + name: 'netflow.ip_header_packet_section', + type: 'short', + }, + 'netflow.ip_payload_packet_section': { + category: 'netflow', + name: 'netflow.ip_payload_packet_section', + type: 'short', + }, + 'netflow.data_link_frame_section': { + category: 'netflow', + name: 'netflow.data_link_frame_section', + type: 'short', + }, + 'netflow.mpls_label_stack_section': { + category: 'netflow', + name: 'netflow.mpls_label_stack_section', + type: 'short', + }, + 'netflow.mpls_payload_packet_section': { + category: 'netflow', + name: 'netflow.mpls_payload_packet_section', + type: 'short', + }, + 'netflow.selector_id_total_pkts_observed': { + category: 'netflow', + name: 'netflow.selector_id_total_pkts_observed', + type: 'long', + }, + 'netflow.selector_id_total_pkts_selected': { + category: 'netflow', + name: 'netflow.selector_id_total_pkts_selected', + type: 'long', + }, + 'netflow.absolute_error': { + category: 'netflow', + name: 'netflow.absolute_error', + type: 'double', + }, + 'netflow.relative_error': { + category: 'netflow', + name: 'netflow.relative_error', + type: 'double', + }, + 'netflow.observation_time_seconds': { + category: 'netflow', + name: 'netflow.observation_time_seconds', + type: 'date', + }, + 'netflow.observation_time_milliseconds': { + category: 'netflow', + name: 'netflow.observation_time_milliseconds', + type: 'date', + }, + 'netflow.observation_time_microseconds': { + category: 'netflow', + name: 'netflow.observation_time_microseconds', + type: 'date', + }, + 'netflow.observation_time_nanoseconds': { + category: 'netflow', + name: 'netflow.observation_time_nanoseconds', + type: 'date', + }, + 'netflow.digest_hash_value': { + category: 'netflow', + name: 'netflow.digest_hash_value', + type: 'long', + }, + 'netflow.hash_ip_payload_offset': { + category: 'netflow', + name: 'netflow.hash_ip_payload_offset', + type: 'long', + }, + 'netflow.hash_ip_payload_size': { + category: 'netflow', + name: 'netflow.hash_ip_payload_size', + type: 'long', + }, + 'netflow.hash_output_range_min': { + category: 'netflow', + name: 'netflow.hash_output_range_min', + type: 'long', + }, + 'netflow.hash_output_range_max': { + category: 'netflow', + name: 'netflow.hash_output_range_max', + type: 'long', + }, + 'netflow.hash_selected_range_min': { + category: 'netflow', + name: 'netflow.hash_selected_range_min', + type: 'long', + }, + 'netflow.hash_selected_range_max': { + category: 'netflow', + name: 'netflow.hash_selected_range_max', + type: 'long', + }, + 'netflow.hash_digest_output': { + category: 'netflow', + name: 'netflow.hash_digest_output', + type: 'boolean', + }, + 'netflow.hash_initialiser_value': { + category: 'netflow', + name: 'netflow.hash_initialiser_value', + type: 'long', + }, + 'netflow.selector_name': { + category: 'netflow', + name: 'netflow.selector_name', + type: 'keyword', + }, + 'netflow.upper_ci_limit': { + category: 'netflow', + name: 'netflow.upper_ci_limit', + type: 'double', + }, + 'netflow.lower_ci_limit': { + category: 'netflow', + name: 'netflow.lower_ci_limit', + type: 'double', + }, + 'netflow.confidence_level': { + category: 'netflow', + name: 'netflow.confidence_level', + type: 'double', + }, + 'netflow.information_element_data_type': { + category: 'netflow', + name: 'netflow.information_element_data_type', + type: 'short', + }, + 'netflow.information_element_description': { + category: 'netflow', + name: 'netflow.information_element_description', + type: 'keyword', + }, + 'netflow.information_element_name': { + category: 'netflow', + name: 'netflow.information_element_name', + type: 'keyword', + }, + 'netflow.information_element_range_begin': { + category: 'netflow', + name: 'netflow.information_element_range_begin', + type: 'long', + }, + 'netflow.information_element_range_end': { + category: 'netflow', + name: 'netflow.information_element_range_end', + type: 'long', + }, + 'netflow.information_element_semantics': { + category: 'netflow', + name: 'netflow.information_element_semantics', + type: 'short', + }, + 'netflow.information_element_units': { + category: 'netflow', + name: 'netflow.information_element_units', + type: 'integer', + }, + 'netflow.private_enterprise_number': { + category: 'netflow', + name: 'netflow.private_enterprise_number', + type: 'long', + }, + 'netflow.virtual_station_interface_id': { + category: 'netflow', + name: 'netflow.virtual_station_interface_id', + type: 'short', + }, + 'netflow.virtual_station_interface_name': { + category: 'netflow', + name: 'netflow.virtual_station_interface_name', + type: 'keyword', + }, + 'netflow.virtual_station_uuid': { + category: 'netflow', + name: 'netflow.virtual_station_uuid', + type: 'short', + }, + 'netflow.virtual_station_name': { + category: 'netflow', + name: 'netflow.virtual_station_name', + type: 'keyword', + }, + 'netflow.layer2_segment_id': { + category: 'netflow', + name: 'netflow.layer2_segment_id', + type: 'long', + }, + 'netflow.layer2_octet_delta_count': { + category: 'netflow', + name: 'netflow.layer2_octet_delta_count', + type: 'long', + }, + 'netflow.layer2_octet_total_count': { + category: 'netflow', + name: 'netflow.layer2_octet_total_count', + type: 'long', + }, + 'netflow.ingress_unicast_packet_total_count': { + category: 'netflow', + name: 'netflow.ingress_unicast_packet_total_count', + type: 'long', + }, + 'netflow.ingress_multicast_packet_total_count': { + category: 'netflow', + name: 'netflow.ingress_multicast_packet_total_count', + type: 'long', + }, + 'netflow.ingress_broadcast_packet_total_count': { + category: 'netflow', + name: 'netflow.ingress_broadcast_packet_total_count', + type: 'long', + }, + 'netflow.egress_unicast_packet_total_count': { + category: 'netflow', + name: 'netflow.egress_unicast_packet_total_count', + type: 'long', + }, + 'netflow.egress_broadcast_packet_total_count': { + category: 'netflow', + name: 'netflow.egress_broadcast_packet_total_count', + type: 'long', + }, + 'netflow.monitoring_interval_start_milli_seconds': { + category: 'netflow', + name: 'netflow.monitoring_interval_start_milli_seconds', + type: 'date', + }, + 'netflow.monitoring_interval_end_milli_seconds': { + category: 'netflow', + name: 'netflow.monitoring_interval_end_milli_seconds', + type: 'date', + }, + 'netflow.port_range_start': { + category: 'netflow', + name: 'netflow.port_range_start', + type: 'integer', + }, + 'netflow.port_range_end': { + category: 'netflow', + name: 'netflow.port_range_end', + type: 'integer', + }, + 'netflow.port_range_step_size': { + category: 'netflow', + name: 'netflow.port_range_step_size', + type: 'integer', + }, + 'netflow.port_range_num_ports': { + category: 'netflow', + name: 'netflow.port_range_num_ports', + type: 'integer', + }, + 'netflow.sta_mac_address': { + category: 'netflow', + name: 'netflow.sta_mac_address', + type: 'keyword', + }, + 'netflow.sta_ipv4_address': { + category: 'netflow', + name: 'netflow.sta_ipv4_address', + type: 'ip', + }, + 'netflow.wtp_mac_address': { + category: 'netflow', + name: 'netflow.wtp_mac_address', + type: 'keyword', + }, + 'netflow.ingress_interface_type': { + category: 'netflow', + name: 'netflow.ingress_interface_type', + type: 'long', + }, + 'netflow.egress_interface_type': { + category: 'netflow', + name: 'netflow.egress_interface_type', + type: 'long', + }, + 'netflow.rtp_sequence_number': { + category: 'netflow', + name: 'netflow.rtp_sequence_number', + type: 'integer', + }, + 'netflow.user_name': { + category: 'netflow', + name: 'netflow.user_name', + type: 'keyword', + }, + 'netflow.application_category_name': { + category: 'netflow', + name: 'netflow.application_category_name', + type: 'keyword', + }, + 'netflow.application_sub_category_name': { + category: 'netflow', + name: 'netflow.application_sub_category_name', + type: 'keyword', + }, + 'netflow.application_group_name': { + category: 'netflow', + name: 'netflow.application_group_name', + type: 'keyword', + }, + 'netflow.original_flows_present': { + category: 'netflow', + name: 'netflow.original_flows_present', + type: 'long', + }, + 'netflow.original_flows_initiated': { + category: 'netflow', + name: 'netflow.original_flows_initiated', + type: 'long', + }, + 'netflow.original_flows_completed': { + category: 'netflow', + name: 'netflow.original_flows_completed', + type: 'long', + }, + 'netflow.distinct_count_of_source_ip_address': { + category: 'netflow', + name: 'netflow.distinct_count_of_source_ip_address', + type: 'long', + }, + 'netflow.distinct_count_of_destination_ip_address': { + category: 'netflow', + name: 'netflow.distinct_count_of_destination_ip_address', + type: 'long', + }, + 'netflow.distinct_count_of_source_ipv4_address': { + category: 'netflow', + name: 'netflow.distinct_count_of_source_ipv4_address', + type: 'long', + }, + 'netflow.distinct_count_of_destination_ipv4_address': { + category: 'netflow', + name: 'netflow.distinct_count_of_destination_ipv4_address', + type: 'long', + }, + 'netflow.distinct_count_of_source_ipv6_address': { + category: 'netflow', + name: 'netflow.distinct_count_of_source_ipv6_address', + type: 'long', + }, + 'netflow.distinct_count_of_destination_ipv6_address': { + category: 'netflow', + name: 'netflow.distinct_count_of_destination_ipv6_address', + type: 'long', + }, + 'netflow.value_distribution_method': { + category: 'netflow', + name: 'netflow.value_distribution_method', + type: 'short', + }, + 'netflow.rfc3550_jitter_milliseconds': { + category: 'netflow', + name: 'netflow.rfc3550_jitter_milliseconds', + type: 'long', + }, + 'netflow.rfc3550_jitter_microseconds': { + category: 'netflow', + name: 'netflow.rfc3550_jitter_microseconds', + type: 'long', + }, + 'netflow.rfc3550_jitter_nanoseconds': { + category: 'netflow', + name: 'netflow.rfc3550_jitter_nanoseconds', + type: 'long', + }, + 'netflow.dot1q_dei': { + category: 'netflow', + name: 'netflow.dot1q_dei', + type: 'boolean', + }, + 'netflow.dot1q_customer_dei': { + category: 'netflow', + name: 'netflow.dot1q_customer_dei', + type: 'boolean', + }, + 'netflow.flow_selector_algorithm': { + category: 'netflow', + name: 'netflow.flow_selector_algorithm', + type: 'integer', + }, + 'netflow.flow_selected_octet_delta_count': { + category: 'netflow', + name: 'netflow.flow_selected_octet_delta_count', + type: 'long', + }, + 'netflow.flow_selected_packet_delta_count': { + category: 'netflow', + name: 'netflow.flow_selected_packet_delta_count', + type: 'long', + }, + 'netflow.flow_selected_flow_delta_count': { + category: 'netflow', + name: 'netflow.flow_selected_flow_delta_count', + type: 'long', + }, + 'netflow.selector_id_total_flows_observed': { + category: 'netflow', + name: 'netflow.selector_id_total_flows_observed', + type: 'long', + }, + 'netflow.selector_id_total_flows_selected': { + category: 'netflow', + name: 'netflow.selector_id_total_flows_selected', + type: 'long', + }, + 'netflow.sampling_flow_interval': { + category: 'netflow', + name: 'netflow.sampling_flow_interval', + type: 'long', + }, + 'netflow.sampling_flow_spacing': { + category: 'netflow', + name: 'netflow.sampling_flow_spacing', + type: 'long', + }, + 'netflow.flow_sampling_time_interval': { + category: 'netflow', + name: 'netflow.flow_sampling_time_interval', + type: 'long', + }, + 'netflow.flow_sampling_time_spacing': { + category: 'netflow', + name: 'netflow.flow_sampling_time_spacing', + type: 'long', + }, + 'netflow.hash_flow_domain': { + category: 'netflow', + name: 'netflow.hash_flow_domain', + type: 'integer', + }, + 'netflow.transport_octet_delta_count': { + category: 'netflow', + name: 'netflow.transport_octet_delta_count', + type: 'long', + }, + 'netflow.transport_packet_delta_count': { + category: 'netflow', + name: 'netflow.transport_packet_delta_count', + type: 'long', + }, + 'netflow.original_exporter_ipv4_address': { + category: 'netflow', + name: 'netflow.original_exporter_ipv4_address', + type: 'ip', + }, + 'netflow.original_exporter_ipv6_address': { + category: 'netflow', + name: 'netflow.original_exporter_ipv6_address', + type: 'ip', + }, + 'netflow.original_observation_domain_id': { + category: 'netflow', + name: 'netflow.original_observation_domain_id', + type: 'long', + }, + 'netflow.intermediate_process_id': { + category: 'netflow', + name: 'netflow.intermediate_process_id', + type: 'long', + }, + 'netflow.ignored_data_record_total_count': { + category: 'netflow', + name: 'netflow.ignored_data_record_total_count', + type: 'long', + }, + 'netflow.data_link_frame_type': { + category: 'netflow', + name: 'netflow.data_link_frame_type', + type: 'integer', + }, + 'netflow.section_offset': { + category: 'netflow', + name: 'netflow.section_offset', + type: 'integer', + }, + 'netflow.section_exported_octets': { + category: 'netflow', + name: 'netflow.section_exported_octets', + type: 'integer', + }, + 'netflow.dot1q_service_instance_tag': { + category: 'netflow', + name: 'netflow.dot1q_service_instance_tag', + type: 'short', + }, + 'netflow.dot1q_service_instance_id': { + category: 'netflow', + name: 'netflow.dot1q_service_instance_id', + type: 'long', + }, + 'netflow.dot1q_service_instance_priority': { + category: 'netflow', + name: 'netflow.dot1q_service_instance_priority', + type: 'short', + }, + 'netflow.dot1q_customer_source_mac_address': { + category: 'netflow', + name: 'netflow.dot1q_customer_source_mac_address', + type: 'keyword', + }, + 'netflow.dot1q_customer_destination_mac_address': { + category: 'netflow', + name: 'netflow.dot1q_customer_destination_mac_address', + type: 'keyword', + }, + 'netflow.post_layer2_octet_delta_count': { + category: 'netflow', + name: 'netflow.post_layer2_octet_delta_count', + type: 'long', + }, + 'netflow.post_mcast_layer2_octet_delta_count': { + category: 'netflow', + name: 'netflow.post_mcast_layer2_octet_delta_count', + type: 'long', + }, + 'netflow.post_layer2_octet_total_count': { + category: 'netflow', + name: 'netflow.post_layer2_octet_total_count', + type: 'long', + }, + 'netflow.post_mcast_layer2_octet_total_count': { + category: 'netflow', + name: 'netflow.post_mcast_layer2_octet_total_count', + type: 'long', + }, + 'netflow.minimum_layer2_total_length': { + category: 'netflow', + name: 'netflow.minimum_layer2_total_length', + type: 'long', + }, + 'netflow.maximum_layer2_total_length': { + category: 'netflow', + name: 'netflow.maximum_layer2_total_length', + type: 'long', + }, + 'netflow.dropped_layer2_octet_delta_count': { + category: 'netflow', + name: 'netflow.dropped_layer2_octet_delta_count', + type: 'long', + }, + 'netflow.dropped_layer2_octet_total_count': { + category: 'netflow', + name: 'netflow.dropped_layer2_octet_total_count', + type: 'long', + }, + 'netflow.ignored_layer2_octet_total_count': { + category: 'netflow', + name: 'netflow.ignored_layer2_octet_total_count', + type: 'long', + }, + 'netflow.not_sent_layer2_octet_total_count': { + category: 'netflow', + name: 'netflow.not_sent_layer2_octet_total_count', + type: 'long', + }, + 'netflow.layer2_octet_delta_sum_of_squares': { + category: 'netflow', + name: 'netflow.layer2_octet_delta_sum_of_squares', + type: 'long', + }, + 'netflow.layer2_octet_total_sum_of_squares': { + category: 'netflow', + name: 'netflow.layer2_octet_total_sum_of_squares', + type: 'long', + }, + 'netflow.layer2_frame_delta_count': { + category: 'netflow', + name: 'netflow.layer2_frame_delta_count', + type: 'long', + }, + 'netflow.layer2_frame_total_count': { + category: 'netflow', + name: 'netflow.layer2_frame_total_count', + type: 'long', + }, + 'netflow.pseudo_wire_destination_ipv4_address': { + category: 'netflow', + name: 'netflow.pseudo_wire_destination_ipv4_address', + type: 'ip', + }, + 'netflow.ignored_layer2_frame_total_count': { + category: 'netflow', + name: 'netflow.ignored_layer2_frame_total_count', + type: 'long', + }, + 'netflow.mib_object_value_integer': { + category: 'netflow', + name: 'netflow.mib_object_value_integer', + type: 'integer', + }, + 'netflow.mib_object_value_octet_string': { + category: 'netflow', + name: 'netflow.mib_object_value_octet_string', + type: 'short', + }, + 'netflow.mib_object_value_oid': { + category: 'netflow', + name: 'netflow.mib_object_value_oid', + type: 'short', + }, + 'netflow.mib_object_value_bits': { + category: 'netflow', + name: 'netflow.mib_object_value_bits', + type: 'short', + }, + 'netflow.mib_object_value_ip_address': { + category: 'netflow', + name: 'netflow.mib_object_value_ip_address', + type: 'ip', + }, + 'netflow.mib_object_value_counter': { + category: 'netflow', + name: 'netflow.mib_object_value_counter', + type: 'long', + }, + 'netflow.mib_object_value_gauge': { + category: 'netflow', + name: 'netflow.mib_object_value_gauge', + type: 'long', + }, + 'netflow.mib_object_value_time_ticks': { + category: 'netflow', + name: 'netflow.mib_object_value_time_ticks', + type: 'long', + }, + 'netflow.mib_object_value_unsigned': { + category: 'netflow', + name: 'netflow.mib_object_value_unsigned', + type: 'long', + }, + 'netflow.mib_object_identifier': { + category: 'netflow', + name: 'netflow.mib_object_identifier', + type: 'short', + }, + 'netflow.mib_sub_identifier': { + category: 'netflow', + name: 'netflow.mib_sub_identifier', + type: 'long', + }, + 'netflow.mib_index_indicator': { + category: 'netflow', + name: 'netflow.mib_index_indicator', + type: 'long', + }, + 'netflow.mib_capture_time_semantics': { + category: 'netflow', + name: 'netflow.mib_capture_time_semantics', + type: 'short', + }, + 'netflow.mib_context_engine_id': { + category: 'netflow', + name: 'netflow.mib_context_engine_id', + type: 'short', + }, + 'netflow.mib_context_name': { + category: 'netflow', + name: 'netflow.mib_context_name', + type: 'keyword', + }, + 'netflow.mib_object_name': { + category: 'netflow', + name: 'netflow.mib_object_name', + type: 'keyword', + }, + 'netflow.mib_object_description': { + category: 'netflow', + name: 'netflow.mib_object_description', + type: 'keyword', + }, + 'netflow.mib_object_syntax': { + category: 'netflow', + name: 'netflow.mib_object_syntax', + type: 'keyword', + }, + 'netflow.mib_module_name': { + category: 'netflow', + name: 'netflow.mib_module_name', + type: 'keyword', + }, + 'netflow.mobile_imsi': { + category: 'netflow', + name: 'netflow.mobile_imsi', + type: 'keyword', + }, + 'netflow.mobile_msisdn': { + category: 'netflow', + name: 'netflow.mobile_msisdn', + type: 'keyword', + }, + 'netflow.http_status_code': { + category: 'netflow', + name: 'netflow.http_status_code', + type: 'integer', + }, + 'netflow.source_transport_ports_limit': { + category: 'netflow', + name: 'netflow.source_transport_ports_limit', + type: 'integer', + }, + 'netflow.http_request_method': { + category: 'netflow', + name: 'netflow.http_request_method', + type: 'keyword', + }, + 'netflow.http_request_host': { + category: 'netflow', + name: 'netflow.http_request_host', + type: 'keyword', + }, + 'netflow.http_request_target': { + category: 'netflow', + name: 'netflow.http_request_target', + type: 'keyword', + }, + 'netflow.http_message_version': { + category: 'netflow', + name: 'netflow.http_message_version', + type: 'keyword', + }, + 'netflow.nat_instance_id': { + category: 'netflow', + name: 'netflow.nat_instance_id', + type: 'long', + }, + 'netflow.internal_address_realm': { + category: 'netflow', + name: 'netflow.internal_address_realm', + type: 'short', + }, + 'netflow.external_address_realm': { + category: 'netflow', + name: 'netflow.external_address_realm', + type: 'short', + }, + 'netflow.nat_quota_exceeded_event': { + category: 'netflow', + name: 'netflow.nat_quota_exceeded_event', + type: 'long', + }, + 'netflow.nat_threshold_event': { + category: 'netflow', + name: 'netflow.nat_threshold_event', + type: 'long', + }, + 'netflow.http_user_agent': { + category: 'netflow', + name: 'netflow.http_user_agent', + type: 'keyword', + }, + 'netflow.http_content_type': { + category: 'netflow', + name: 'netflow.http_content_type', + type: 'keyword', + }, + 'netflow.http_reason_phrase': { + category: 'netflow', + name: 'netflow.http_reason_phrase', + type: 'keyword', + }, + 'netflow.max_session_entries': { + category: 'netflow', + name: 'netflow.max_session_entries', + type: 'long', + }, + 'netflow.max_bib_entries': { + category: 'netflow', + name: 'netflow.max_bib_entries', + type: 'long', + }, + 'netflow.max_entries_per_user': { + category: 'netflow', + name: 'netflow.max_entries_per_user', + type: 'long', + }, + 'netflow.max_subscribers': { + category: 'netflow', + name: 'netflow.max_subscribers', + type: 'long', + }, + 'netflow.max_fragments_pending_reassembly': { + category: 'netflow', + name: 'netflow.max_fragments_pending_reassembly', + type: 'long', + }, + 'netflow.address_pool_high_threshold': { + category: 'netflow', + name: 'netflow.address_pool_high_threshold', + type: 'long', + }, + 'netflow.address_pool_low_threshold': { + category: 'netflow', + name: 'netflow.address_pool_low_threshold', + type: 'long', + }, + 'netflow.address_port_mapping_high_threshold': { + category: 'netflow', + name: 'netflow.address_port_mapping_high_threshold', + type: 'long', + }, + 'netflow.address_port_mapping_low_threshold': { + category: 'netflow', + name: 'netflow.address_port_mapping_low_threshold', + type: 'long', + }, + 'netflow.address_port_mapping_per_user_high_threshold': { + category: 'netflow', + name: 'netflow.address_port_mapping_per_user_high_threshold', + type: 'long', + }, + 'netflow.global_address_mapping_high_threshold': { + category: 'netflow', + name: 'netflow.global_address_mapping_high_threshold', + type: 'long', + }, + 'netflow.vpn_identifier': { + category: 'netflow', + name: 'netflow.vpn_identifier', + type: 'short', + }, + bucket_name: { + category: 'base', + description: 'Name of the S3 bucket that this log retrieved from. ', + name: 'bucket_name', + type: 'keyword', + }, + object_key: { + category: 'base', + description: 'Name of the S3 object that this log retrieved from. ', + name: 'object_key', + type: 'keyword', + }, + 'cef.version': { + category: 'cef', + description: 'Version of the CEF specification used by the message. ', + name: 'cef.version', + type: 'keyword', + }, + 'cef.device.vendor': { + category: 'cef', + description: 'Vendor of the device that produced the message. ', + name: 'cef.device.vendor', + type: 'keyword', + }, + 'cef.device.product': { + category: 'cef', + description: 'Product of the device that produced the message. ', + name: 'cef.device.product', + type: 'keyword', + }, + 'cef.device.version': { + category: 'cef', + description: 'Version of the product that produced the message. ', + name: 'cef.device.version', + type: 'keyword', + }, + 'cef.device.event_class_id': { + category: 'cef', + description: 'Unique identifier of the event type. ', + name: 'cef.device.event_class_id', + type: 'keyword', + }, + 'cef.severity': { + category: 'cef', + description: + 'Importance of the event. The valid string values are Unknown, Low, Medium, High, and Very-High. The valid integer values are 0-3=Low, 4-6=Medium, 7- 8=High, and 9-10=Very-High. ', + example: 'Very-High', + name: 'cef.severity', + type: 'keyword', + }, + 'cef.name': { + category: 'cef', + description: 'Short description of the event. ', + name: 'cef.name', + type: 'keyword', + }, + 'cef.extensions.agentAddress': { + category: 'cef', + description: 'The IP address of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentAddress', + type: 'ip', + }, + 'cef.extensions.agentDnsDomain': { + category: 'cef', + description: 'The DNS domain name of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentDnsDomain', + type: 'keyword', + }, + 'cef.extensions.agentHostName': { + category: 'cef', + description: 'The hostname of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentHostName', + type: 'keyword', + }, + 'cef.extensions.agentId': { + category: 'cef', + description: 'The agent ID of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentId', + type: 'keyword', + }, + 'cef.extensions.agentMacAddress': { + category: 'cef', + description: 'The MAC address of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentMacAddress', + type: 'keyword', + }, + 'cef.extensions.agentNtDomain': { + category: 'cef', + description: 'null', + name: 'cef.extensions.agentNtDomain', + type: 'keyword', + }, + 'cef.extensions.agentReceiptTime': { + category: 'cef', + description: + 'The time at which information about the event was received by the ArcSight connector.', + name: 'cef.extensions.agentReceiptTime', + type: 'date', + }, + 'cef.extensions.agentTimeZone': { + category: 'cef', + description: 'The agent time zone of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentTimeZone', + type: 'keyword', + }, + 'cef.extensions.agentTranslatedAddress': { + category: 'cef', + description: 'null', + name: 'cef.extensions.agentTranslatedAddress', + type: 'ip', + }, + 'cef.extensions.agentTranslatedZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.agentTranslatedZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.agentTranslatedZoneURI': { + category: 'cef', + description: 'null', + name: 'cef.extensions.agentTranslatedZoneURI', + type: 'keyword', + }, + 'cef.extensions.agentType': { + category: 'cef', + description: 'The agent type of the ArcSight connector that processed the event', + name: 'cef.extensions.agentType', + type: 'keyword', + }, + 'cef.extensions.agentVersion': { + category: 'cef', + description: 'The version of the ArcSight connector that processed the event.', + name: 'cef.extensions.agentVersion', + type: 'keyword', + }, + 'cef.extensions.agentZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.agentZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.agentZoneURI': { + category: 'cef', + description: 'null', + name: 'cef.extensions.agentZoneURI', + type: 'keyword', + }, + 'cef.extensions.applicationProtocol': { + category: 'cef', + description: + 'Application level protocol, example values are HTTP, HTTPS, SSHv2, Telnet, POP, IMPA, IMAPS, and so on.', + name: 'cef.extensions.applicationProtocol', + type: 'keyword', + }, + 'cef.extensions.baseEventCount': { + category: 'cef', + description: + 'A count associated with this event. How many times was this same event observed? Count can be omitted if it is 1.', + name: 'cef.extensions.baseEventCount', + type: 'long', + }, + 'cef.extensions.bytesIn': { + category: 'cef', + description: + 'Number of bytes transferred inbound, relative to the source to destination relationship, meaning that data was flowing from source to destination.', + name: 'cef.extensions.bytesIn', + type: 'long', + }, + 'cef.extensions.bytesOut': { + category: 'cef', + description: + 'Number of bytes transferred outbound relative to the source to destination relationship. For example, the byte number of data flowing from the destination to the source.', + name: 'cef.extensions.bytesOut', + type: 'long', + }, + 'cef.extensions.customerExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.customerExternalID', + type: 'keyword', + }, + 'cef.extensions.customerURI': { + category: 'cef', + description: 'null', + name: 'cef.extensions.customerURI', + type: 'keyword', + }, + 'cef.extensions.destinationAddress': { + category: 'cef', + description: + 'Identifies the destination address that the event refers to in an IP network. The format is an IPv4 address.', + name: 'cef.extensions.destinationAddress', + type: 'ip', + }, + 'cef.extensions.destinationDnsDomain': { + category: 'cef', + description: 'The DNS domain part of the complete fully qualified domain name (FQDN).', + name: 'cef.extensions.destinationDnsDomain', + type: 'keyword', + }, + 'cef.extensions.destinationGeoLatitude': { + category: 'cef', + description: "The latitudinal value from which the destination's IP address belongs.", + name: 'cef.extensions.destinationGeoLatitude', + type: 'double', + }, + 'cef.extensions.destinationGeoLongitude': { + category: 'cef', + description: "The longitudinal value from which the destination's IP address belongs.", + name: 'cef.extensions.destinationGeoLongitude', + type: 'double', + }, + 'cef.extensions.destinationHostName': { + category: 'cef', + description: + 'Identifies the destination that an event refers to in an IP network. The format should be a fully qualified domain name (FQDN) associated with the destination node, when a node is available.', + name: 'cef.extensions.destinationHostName', + type: 'keyword', + }, + 'cef.extensions.destinationMacAddress': { + category: 'cef', + description: 'Six colon-seperated hexadecimal numbers.', + name: 'cef.extensions.destinationMacAddress', + type: 'keyword', + }, + 'cef.extensions.destinationNtDomain': { + category: 'cef', + description: 'The Windows domain name of the destination address.', + name: 'cef.extensions.destinationNtDomain', + type: 'keyword', + }, + 'cef.extensions.destinationPort': { + category: 'cef', + description: 'The valid port numbers are between 0 and 65535.', + name: 'cef.extensions.destinationPort', + type: 'long', + }, + 'cef.extensions.destinationProcessId': { + category: 'cef', + description: + 'Provides the ID of the destination process associated with the event. For example, if an event contains process ID 105, "105" is the process ID.', + name: 'cef.extensions.destinationProcessId', + type: 'long', + }, + 'cef.extensions.destinationProcessName': { + category: 'cef', + description: "The name of the event's destination process.", + name: 'cef.extensions.destinationProcessName', + type: 'keyword', + }, + 'cef.extensions.destinationServiceName': { + category: 'cef', + description: 'The service targeted by this event.', + name: 'cef.extensions.destinationServiceName', + type: 'keyword', + }, + 'cef.extensions.destinationTranslatedAddress': { + category: 'cef', + description: 'Identifies the translated destination that the event refers to in an IP network.', + name: 'cef.extensions.destinationTranslatedAddress', + type: 'ip', + }, + 'cef.extensions.destinationTranslatedPort': { + category: 'cef', + description: + 'Port after it was translated; for example, a firewall. Valid port numbers are 0 to 65535.', + name: 'cef.extensions.destinationTranslatedPort', + type: 'long', + }, + 'cef.extensions.destinationTranslatedZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.destinationTranslatedZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.destinationTranslatedZoneURI': { + category: 'cef', + description: + 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.', + name: 'cef.extensions.destinationTranslatedZoneURI', + type: 'keyword', + }, + 'cef.extensions.destinationUserId': { + category: 'cef', + description: + 'Identifies the destination user by ID. For example, in UNIX, the root user is generally associated with user ID 0.', + name: 'cef.extensions.destinationUserId', + type: 'keyword', + }, + 'cef.extensions.destinationUserName': { + category: 'cef', + description: + "Identifies the destination user by name. This is the user associated with the event's destination. Email addresses are often mapped into the UserName fields. The recipient is a candidate to put into this field.", + name: 'cef.extensions.destinationUserName', + type: 'keyword', + }, + 'cef.extensions.destinationUserPrivileges': { + category: 'cef', + description: + 'The typical values are "Administrator", "User", and "Guest". This identifies the destination user\'s privileges. In UNIX, for example, activity executed on the root user would be identified with destinationUser Privileges of "Administrator".', + name: 'cef.extensions.destinationUserPrivileges', + type: 'keyword', + }, + 'cef.extensions.destinationZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.destinationZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.destinationZoneURI': { + category: 'cef', + description: + 'The URI for the Zone that the destination asset has been assigned to in ArcSight.', + name: 'cef.extensions.destinationZoneURI', + type: 'keyword', + }, + 'cef.extensions.deviceAction': { + category: 'cef', + description: 'Action taken by the device.', + name: 'cef.extensions.deviceAction', + type: 'keyword', + }, + 'cef.extensions.deviceAddress': { + category: 'cef', + description: 'Identifies the device address that an event refers to in an IP network.', + name: 'cef.extensions.deviceAddress', + type: 'ip', + }, + 'cef.extensions.deviceCustomFloatingPoint1Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomFloatingPoint1Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomFloatingPoint3Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomFloatingPoint3Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomFloatingPoint4Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomFloatingPoint4Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomDate1': { + category: 'cef', + description: + 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomDate1', + type: 'date', + }, + 'cef.extensions.deviceCustomDate1Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomDate1Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomDate2': { + category: 'cef', + description: + 'One of two timestamp fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomDate2', + type: 'date', + }, + 'cef.extensions.deviceCustomDate2Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomDate2Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomFloatingPoint1': { + category: 'cef', + description: + 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomFloatingPoint1', + type: 'double', + }, + 'cef.extensions.deviceCustomFloatingPoint2': { + category: 'cef', + description: + 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomFloatingPoint2', + type: 'double', + }, + 'cef.extensions.deviceCustomFloatingPoint2Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomFloatingPoint2Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomFloatingPoint3': { + category: 'cef', + description: + 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomFloatingPoint3', + type: 'double', + }, + 'cef.extensions.deviceCustomFloatingPoint4': { + category: 'cef', + description: + 'One of four floating point fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomFloatingPoint4', + type: 'double', + }, + 'cef.extensions.deviceCustomIPv6Address1': { + category: 'cef', + description: + 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomIPv6Address1', + type: 'ip', + }, + 'cef.extensions.deviceCustomIPv6Address1Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomIPv6Address1Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomIPv6Address2': { + category: 'cef', + description: + 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomIPv6Address2', + type: 'ip', + }, + 'cef.extensions.deviceCustomIPv6Address2Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomIPv6Address2Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomIPv6Address3': { + category: 'cef', + description: + 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomIPv6Address3', + type: 'ip', + }, + 'cef.extensions.deviceCustomIPv6Address3Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomIPv6Address3Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomIPv6Address4': { + category: 'cef', + description: + 'One of four IPv6 address fields available to map fields that do not apply to any other in this dictionary.', + name: 'cef.extensions.deviceCustomIPv6Address4', + type: 'ip', + }, + 'cef.extensions.deviceCustomIPv6Address4Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomIPv6Address4Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomNumber1': { + category: 'cef', + description: + 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomNumber1', + type: 'long', + }, + 'cef.extensions.deviceCustomNumber1Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomNumber1Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomNumber2': { + category: 'cef', + description: + 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomNumber2', + type: 'long', + }, + 'cef.extensions.deviceCustomNumber2Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomNumber2Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomNumber3': { + category: 'cef', + description: + 'One of three number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomNumber3', + type: 'long', + }, + 'cef.extensions.deviceCustomNumber3Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomNumber3Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString1': { + category: 'cef', + description: + 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomString1', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString1Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomString1Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString2': { + category: 'cef', + description: + 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomString2', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString2Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomString2Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString3': { + category: 'cef', + description: + 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomString3', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString3Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomString3Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString4': { + category: 'cef', + description: + 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomString4', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString4Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomString4Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString5': { + category: 'cef', + description: + 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomString5', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString5Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomString5Label', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString6': { + category: 'cef', + description: + 'One of six strings available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceCustomString6', + type: 'keyword', + }, + 'cef.extensions.deviceCustomString6Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceCustomString6Label', + type: 'keyword', + }, + 'cef.extensions.deviceDirection': { + category: 'cef', + description: + 'Any information about what direction the observed communication has taken. The following values are supported - "0" for inbound or "1" for outbound.', + name: 'cef.extensions.deviceDirection', + type: 'long', + }, + 'cef.extensions.deviceDnsDomain': { + category: 'cef', + description: 'The DNS domain part of the complete fully qualified domain name (FQDN).', + name: 'cef.extensions.deviceDnsDomain', + type: 'keyword', + }, + 'cef.extensions.deviceEventCategory': { + category: 'cef', + description: + 'Represents the category assigned by the originating device. Devices often use their own categorization schema to classify event. Example "/Monitor/Disk/Read".', + name: 'cef.extensions.deviceEventCategory', + type: 'keyword', + }, + 'cef.extensions.deviceExternalId': { + category: 'cef', + description: 'A name that uniquely identifies the device generating this event.', + name: 'cef.extensions.deviceExternalId', + type: 'keyword', + }, + 'cef.extensions.deviceFacility': { + category: 'cef', + description: + 'The facility generating this event. For example, Syslog has an explicit facility associated with every event.', + name: 'cef.extensions.deviceFacility', + type: 'keyword', + }, + 'cef.extensions.deviceFlexNumber1': { + category: 'cef', + description: + 'One of two alternative number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceFlexNumber1', + type: 'long', + }, + 'cef.extensions.deviceFlexNumber1Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceFlexNumber1Label', + type: 'keyword', + }, + 'cef.extensions.deviceFlexNumber2': { + category: 'cef', + description: + 'One of two alternative number fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible.', + name: 'cef.extensions.deviceFlexNumber2', + type: 'long', + }, + 'cef.extensions.deviceFlexNumber2Label': { + category: 'cef', + description: + 'All custom fields have a corresponding label field. Each of these fields is a string and describes the purpose of the custom field.', + name: 'cef.extensions.deviceFlexNumber2Label', + type: 'keyword', + }, + 'cef.extensions.deviceHostName': { + category: 'cef', + description: + 'The format should be a fully qualified domain name (FQDN) associated with the device node, when a node is available.', + name: 'cef.extensions.deviceHostName', + type: 'keyword', + }, + 'cef.extensions.deviceInboundInterface': { + category: 'cef', + description: 'Interface on which the packet or data entered the device.', + name: 'cef.extensions.deviceInboundInterface', + type: 'keyword', + }, + 'cef.extensions.deviceMacAddress': { + category: 'cef', + description: 'Six colon-separated hexadecimal numbers.', + name: 'cef.extensions.deviceMacAddress', + type: 'keyword', + }, + 'cef.extensions.deviceNtDomain': { + category: 'cef', + description: 'The Windows domain name of the device address.', + name: 'cef.extensions.deviceNtDomain', + type: 'keyword', + }, + 'cef.extensions.deviceOutboundInterface': { + category: 'cef', + description: 'Interface on which the packet or data left the device.', + name: 'cef.extensions.deviceOutboundInterface', + type: 'keyword', + }, + 'cef.extensions.devicePayloadId': { + category: 'cef', + description: 'Unique identifier for the payload associated with the event.', + name: 'cef.extensions.devicePayloadId', + type: 'keyword', + }, + 'cef.extensions.deviceProcessId': { + category: 'cef', + description: 'Provides the ID of the process on the device generating the event.', + name: 'cef.extensions.deviceProcessId', + type: 'long', + }, + 'cef.extensions.deviceProcessName': { + category: 'cef', + description: + 'Process name associated with the event. An example might be the process generating the syslog entry in UNIX.', + name: 'cef.extensions.deviceProcessName', + type: 'keyword', + }, + 'cef.extensions.deviceReceiptTime': { + category: 'cef', + description: + 'The time at which the event related to the activity was received. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)', + name: 'cef.extensions.deviceReceiptTime', + type: 'date', + }, + 'cef.extensions.deviceTimeZone': { + category: 'cef', + description: 'The time zone for the device generating the event.', + name: 'cef.extensions.deviceTimeZone', + type: 'keyword', + }, + 'cef.extensions.deviceTranslatedAddress': { + category: 'cef', + description: + 'Identifies the translated device address that the event refers to in an IP network.', + name: 'cef.extensions.deviceTranslatedAddress', + type: 'ip', + }, + 'cef.extensions.deviceTranslatedZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.deviceTranslatedZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.deviceTranslatedZoneURI': { + category: 'cef', + description: + 'The URI for the Translated Zone that the device asset has been assigned to in ArcSight.', + name: 'cef.extensions.deviceTranslatedZoneURI', + type: 'keyword', + }, + 'cef.extensions.deviceZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.deviceZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.deviceZoneURI': { + category: 'cef', + description: 'Thee URI for the Zone that the device asset has been assigned to in ArcSight.', + name: 'cef.extensions.deviceZoneURI', + type: 'keyword', + }, + 'cef.extensions.endTime': { + category: 'cef', + description: + 'The time at which the activity related to the event ended. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st1970). An example would be reporting the end of a session.', + name: 'cef.extensions.endTime', + type: 'date', + }, + 'cef.extensions.eventId': { + category: 'cef', + description: 'This is a unique ID that ArcSight assigns to each event.', + name: 'cef.extensions.eventId', + type: 'long', + }, + 'cef.extensions.eventOutcome': { + category: 'cef', + description: "Displays the outcome, usually as 'success' or 'failure'.", + name: 'cef.extensions.eventOutcome', + type: 'keyword', + }, + 'cef.extensions.externalId': { + category: 'cef', + description: + 'The ID used by an originating device. They are usually increasing numbers, associated with events.', + name: 'cef.extensions.externalId', + type: 'keyword', + }, + 'cef.extensions.fileCreateTime': { + category: 'cef', + description: 'Time when the file was created.', + name: 'cef.extensions.fileCreateTime', + type: 'date', + }, + 'cef.extensions.fileHash': { + category: 'cef', + description: 'Hash of a file.', + name: 'cef.extensions.fileHash', + type: 'keyword', + }, + 'cef.extensions.fileId': { + category: 'cef', + description: 'An ID associated with a file could be the inode.', + name: 'cef.extensions.fileId', + type: 'keyword', + }, + 'cef.extensions.fileModificationTime': { + category: 'cef', + description: 'Time when the file was last modified.', + name: 'cef.extensions.fileModificationTime', + type: 'date', + }, + 'cef.extensions.filename': { + category: 'cef', + description: 'Name of the file only (without its path).', + name: 'cef.extensions.filename', + type: 'keyword', + }, + 'cef.extensions.filePath': { + category: 'cef', + description: 'Full path to the file, including file name itself.', + name: 'cef.extensions.filePath', + type: 'keyword', + }, + 'cef.extensions.filePermission': { + category: 'cef', + description: 'Permissions of the file.', + name: 'cef.extensions.filePermission', + type: 'keyword', + }, + 'cef.extensions.fileSize': { + category: 'cef', + description: 'Size of the file.', + name: 'cef.extensions.fileSize', + type: 'long', + }, + 'cef.extensions.fileType': { + category: 'cef', + description: 'Type of file (pipe, socket, etc.)', + name: 'cef.extensions.fileType', + type: 'keyword', + }, + 'cef.extensions.flexDate1': { + category: 'cef', + description: + 'A timestamp field available to map a timestamp that does not apply to any other defined timestamp field in this dictionary. Use all flex fields sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.', + name: 'cef.extensions.flexDate1', + type: 'date', + }, + 'cef.extensions.flexDate1Label': { + category: 'cef', + description: 'The label field is a string and describes the purpose of the flex field.', + name: 'cef.extensions.flexDate1Label', + type: 'keyword', + }, + 'cef.extensions.flexString1': { + category: 'cef', + description: + 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.', + name: 'cef.extensions.flexString1', + type: 'keyword', + }, + 'cef.extensions.flexString2': { + category: 'cef', + description: + 'One of four floating point fields available to map fields that do not apply to any other in this dictionary. Use sparingly and seek a more specific, dictionary supplied field when possible. These fields are typically reserved for customer use and should not be set by vendors unless necessary.', + name: 'cef.extensions.flexString2', + type: 'keyword', + }, + 'cef.extensions.flexString1Label': { + category: 'cef', + description: 'The label field is a string and describes the purpose of the flex field.', + name: 'cef.extensions.flexString1Label', + type: 'keyword', + }, + 'cef.extensions.flexString2Label': { + category: 'cef', + description: 'The label field is a string and describes the purpose of the flex field.', + name: 'cef.extensions.flexString2Label', + type: 'keyword', + }, + 'cef.extensions.message': { + category: 'cef', + description: + 'An arbitrary message giving more details about the event. Multi-line entries can be produced by using \\n as the new line separator.', + name: 'cef.extensions.message', + type: 'keyword', + }, + 'cef.extensions.oldFileCreateTime': { + category: 'cef', + description: 'Time when old file was created.', + name: 'cef.extensions.oldFileCreateTime', + type: 'date', + }, + 'cef.extensions.oldFileHash': { + category: 'cef', + description: 'Hash of the old file.', + name: 'cef.extensions.oldFileHash', + type: 'keyword', + }, + 'cef.extensions.oldFileId': { + category: 'cef', + description: 'An ID associated with the old file could be the inode.', + name: 'cef.extensions.oldFileId', + type: 'keyword', + }, + 'cef.extensions.oldFileModificationTime': { + category: 'cef', + description: 'Time when old file was last modified.', + name: 'cef.extensions.oldFileModificationTime', + type: 'date', + }, + 'cef.extensions.oldFileName': { + category: 'cef', + description: 'Name of the old file.', + name: 'cef.extensions.oldFileName', + type: 'keyword', + }, + 'cef.extensions.oldFilePath': { + category: 'cef', + description: 'Full path to the old file, including the file name itself.', + name: 'cef.extensions.oldFilePath', + type: 'keyword', + }, + 'cef.extensions.oldFilePermission': { + category: 'cef', + description: 'Permissions of the old file.', + name: 'cef.extensions.oldFilePermission', + type: 'keyword', + }, + 'cef.extensions.oldFileSize': { + category: 'cef', + description: 'Size of the old file.', + name: 'cef.extensions.oldFileSize', + type: 'long', + }, + 'cef.extensions.oldFileType': { + category: 'cef', + description: 'Type of the old file (pipe, socket, etc.)', + name: 'cef.extensions.oldFileType', + type: 'keyword', + }, + 'cef.extensions.rawEvent': { + category: 'cef', + description: 'null', + name: 'cef.extensions.rawEvent', + type: 'keyword', + }, + 'cef.extensions.Reason': { + category: 'cef', + description: + 'The reason an audit event was generated. For example "bad password" or "unknown user". This could also be an error or return code. Example "0x1234".', + name: 'cef.extensions.Reason', + type: 'keyword', + }, + 'cef.extensions.requestClientApplication': { + category: 'cef', + description: 'The User-Agent associated with the request.', + name: 'cef.extensions.requestClientApplication', + type: 'keyword', + }, + 'cef.extensions.requestContext': { + category: 'cef', + description: + 'Description of the content from which the request originated (for example, HTTP Referrer)', + name: 'cef.extensions.requestContext', + type: 'keyword', + }, + 'cef.extensions.requestCookies': { + category: 'cef', + description: 'Cookies associated with the request.', + name: 'cef.extensions.requestCookies', + type: 'keyword', + }, + 'cef.extensions.requestMethod': { + category: 'cef', + description: 'The HTTP method used to access a URL.', + name: 'cef.extensions.requestMethod', + type: 'keyword', + }, + 'cef.extensions.requestUrl': { + category: 'cef', + description: + 'In the case of an HTTP request, this field contains the URL accessed. The URL should contain the protocol as well.', + name: 'cef.extensions.requestUrl', + type: 'keyword', + }, + 'cef.extensions.sourceAddress': { + category: 'cef', + description: 'Identifies the source that an event refers to in an IP network.', + name: 'cef.extensions.sourceAddress', + type: 'ip', + }, + 'cef.extensions.sourceDnsDomain': { + category: 'cef', + description: 'The DNS domain part of the complete fully qualified domain name (FQDN).', + name: 'cef.extensions.sourceDnsDomain', + type: 'keyword', + }, + 'cef.extensions.sourceGeoLatitude': { + category: 'cef', + description: 'null', + name: 'cef.extensions.sourceGeoLatitude', + type: 'double', + }, + 'cef.extensions.sourceGeoLongitude': { + category: 'cef', + description: 'null', + name: 'cef.extensions.sourceGeoLongitude', + type: 'double', + }, + 'cef.extensions.sourceHostName': { + category: 'cef', + description: + "Identifies the source that an event refers to in an IP network. The format should be a fully qualified domain name (FQDN) associated with the source node, when a mode is available. Examples: 'host' or 'host.domain.com'. ", + name: 'cef.extensions.sourceHostName', + type: 'keyword', + }, + 'cef.extensions.sourceMacAddress': { + category: 'cef', + description: 'Six colon-separated hexadecimal numbers.', + example: '00:0d:60:af:1b:61', + name: 'cef.extensions.sourceMacAddress', + type: 'keyword', + }, + 'cef.extensions.sourceNtDomain': { + category: 'cef', + description: 'The Windows domain name for the source address.', + name: 'cef.extensions.sourceNtDomain', + type: 'keyword', + }, + 'cef.extensions.sourcePort': { + category: 'cef', + description: 'The valid port numbers are 0 to 65535.', + name: 'cef.extensions.sourcePort', + type: 'long', + }, + 'cef.extensions.sourceProcessId': { + category: 'cef', + description: 'The ID of the source process associated with the event.', + name: 'cef.extensions.sourceProcessId', + type: 'long', + }, + 'cef.extensions.sourceProcessName': { + category: 'cef', + description: "The name of the event's source process.", + name: 'cef.extensions.sourceProcessName', + type: 'keyword', + }, + 'cef.extensions.sourceServiceName': { + category: 'cef', + description: 'The service that is responsible for generating this event.', + name: 'cef.extensions.sourceServiceName', + type: 'keyword', + }, + 'cef.extensions.sourceTranslatedAddress': { + category: 'cef', + description: 'Identifies the translated source that the event refers to in an IP network.', + name: 'cef.extensions.sourceTranslatedAddress', + type: 'ip', + }, + 'cef.extensions.sourceTranslatedPort': { + category: 'cef', + description: + 'A port number after being translated by, for example, a firewall. Valid port numbers are 0 to 65535.', + name: 'cef.extensions.sourceTranslatedPort', + type: 'long', + }, + 'cef.extensions.sourceTranslatedZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.sourceTranslatedZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.sourceTranslatedZoneURI': { + category: 'cef', + description: + 'The URI for the Translated Zone that the destination asset has been assigned to in ArcSight.', + name: 'cef.extensions.sourceTranslatedZoneURI', + type: 'keyword', + }, + 'cef.extensions.sourceUserId': { + category: 'cef', + description: + 'Identifies the source user by ID. This is the user associated with the source of the event. For example, in UNIX, the root user is generally associated with user ID 0.', + name: 'cef.extensions.sourceUserId', + type: 'keyword', + }, + 'cef.extensions.sourceUserName': { + category: 'cef', + description: + 'Identifies the source user by name. Email addresses are also mapped into the UserName fields. The sender is a candidate to put into this field.', + name: 'cef.extensions.sourceUserName', + type: 'keyword', + }, + 'cef.extensions.sourceUserPrivileges': { + category: 'cef', + description: + 'The typical values are "Administrator", "User", and "Guest". It identifies the source user\'s privileges. In UNIX, for example, activity executed by the root user would be identified with "Administrator".', + name: 'cef.extensions.sourceUserPrivileges', + type: 'keyword', + }, + 'cef.extensions.sourceZoneExternalID': { + category: 'cef', + description: 'null', + name: 'cef.extensions.sourceZoneExternalID', + type: 'keyword', + }, + 'cef.extensions.sourceZoneURI': { + category: 'cef', + description: 'The URI for the Zone that the source asset has been assigned to in ArcSight.', + name: 'cef.extensions.sourceZoneURI', + type: 'keyword', + }, + 'cef.extensions.startTime': { + category: 'cef', + description: + 'The time when the activity the event referred to started. The format is MMM dd yyyy HH:mm:ss or milliseconds since epoch (Jan 1st 1970)', + name: 'cef.extensions.startTime', + type: 'date', + }, + 'cef.extensions.transportProtocol': { + category: 'cef', + description: + 'Identifies the Layer-4 protocol used. The possible values are protocols such as TCP or UDP.', + name: 'cef.extensions.transportProtocol', + type: 'keyword', + }, + 'cef.extensions.type': { + category: 'cef', + description: + '0 means base event, 1 means aggregated, 2 means correlation, and 3 means action. This field can be omitted for base events (type 0).', + name: 'cef.extensions.type', + type: 'long', + }, + 'cef.extensions.categoryDeviceType': { + category: 'cef', + description: 'Device type. Examples - Proxy, IDS, Web Server', + name: 'cef.extensions.categoryDeviceType', + type: 'keyword', + }, + 'cef.extensions.categoryObject': { + category: 'cef', + description: + 'Object that the event is about. For example it can be an operating sytem, database, file, etc.', + name: 'cef.extensions.categoryObject', + type: 'keyword', + }, + 'cef.extensions.categoryBehavior': { + category: 'cef', + description: + "Action or a behavior associated with an event. It's what is being done to the object.", + name: 'cef.extensions.categoryBehavior', + type: 'keyword', + }, + 'cef.extensions.categoryTechnique': { + category: 'cef', + description: 'Technique being used (e.g. /DoS).', + name: 'cef.extensions.categoryTechnique', + type: 'keyword', + }, + 'cef.extensions.categoryDeviceGroup': { + category: 'cef', + description: 'General device group like Firewall.', + name: 'cef.extensions.categoryDeviceGroup', + type: 'keyword', + }, + 'cef.extensions.categorySignificance': { + category: 'cef', + description: 'Characterization of the importance of the event.', + name: 'cef.extensions.categorySignificance', + type: 'keyword', + }, + 'cef.extensions.categoryOutcome': { + category: 'cef', + description: 'Outcome of the event (e.g. sucess, failure, or attempt).', + name: 'cef.extensions.categoryOutcome', + type: 'keyword', + }, + 'cef.extensions.managerReceiptTime': { + category: 'cef', + description: 'When the Arcsight ESM received the event.', + name: 'cef.extensions.managerReceiptTime', + type: 'date', + }, + 'source.service.name': { + category: 'source', + description: 'Service that is the source of the event.', + name: 'source.service.name', + type: 'keyword', + }, + 'destination.service.name': { + category: 'destination', + description: 'Service that is the target of the event.', + name: 'destination.service.name', + type: 'keyword', + }, + type: { + category: 'base', + description: + 'The type of the transaction (for example, HTTP, MySQL, Redis, or RUM) or "flow" in case of flows. ', + name: 'type', + }, + 'server.process.name': { + category: 'server', + description: 'The name of the process that served the transaction. ', + name: 'server.process.name', + }, + 'server.process.args': { + category: 'server', + description: 'The command-line of the process that served the transaction. ', + name: 'server.process.args', + }, + 'server.process.executable': { + category: 'server', + description: 'Absolute path to the server process executable. ', + name: 'server.process.executable', + }, + 'server.process.working_directory': { + category: 'server', + description: 'The working directory of the server process. ', + name: 'server.process.working_directory', + }, + 'server.process.start': { + category: 'server', + description: 'The time the server process started. ', + name: 'server.process.start', + }, + 'client.process.name': { + category: 'client', + description: 'The name of the process that initiated the transaction. ', + name: 'client.process.name', + }, + 'client.process.args': { + category: 'client', + description: 'The command-line of the process that initiated the transaction. ', + name: 'client.process.args', + }, + 'client.process.executable': { + category: 'client', + description: 'Absolute path to the client process executable. ', + name: 'client.process.executable', + }, + 'client.process.working_directory': { + category: 'client', + description: 'The working directory of the client process. ', + name: 'client.process.working_directory', + }, + 'client.process.start': { + category: 'client', + description: 'The time the client process started. ', + name: 'client.process.start', + }, + real_ip: { + category: 'base', + description: + 'If the server initiating the transaction is a proxy, this field contains the original client IP address. For HTTP, for example, the IP address extracted from a configurable HTTP header, by default `X-Forwarded-For`. Unless this field is disabled, it always has a value, and it matches the `client_ip` for non proxy clients. ', + name: 'real_ip', + type: 'alias', + }, + transport: { + category: 'base', + description: + 'The transport protocol used for the transaction. If not specified, then tcp is assumed. ', + name: 'transport', + type: 'alias', + }, + 'flow.final': { + category: 'flow', + description: + 'Indicates if event is last event in flow. If final is false, the event reports an intermediate flow state only. ', + name: 'flow.final', + type: 'boolean', + }, + 'flow.id': { + category: 'flow', + description: 'Internal flow ID based on connection meta data and address. ', + name: 'flow.id', + }, + 'flow.vlan': { + category: 'flow', + description: + "VLAN identifier from the 802.1q frame. In case of a multi-tagged frame this field will be an array with the outer tag's VLAN identifier listed first. ", + name: 'flow.vlan', + type: 'long', + }, + flow_id: { + category: 'base', + name: 'flow_id', + type: 'alias', + }, + final: { + category: 'base', + name: 'final', + type: 'alias', + }, + vlan: { + category: 'base', + name: 'vlan', + type: 'alias', + }, + 'source.stats.net_bytes_total': { + category: 'source', + name: 'source.stats.net_bytes_total', + type: 'alias', + }, + 'source.stats.net_packets_total': { + category: 'source', + name: 'source.stats.net_packets_total', + type: 'alias', + }, + 'dest.stats.net_bytes_total': { + category: 'dest', + name: 'dest.stats.net_bytes_total', + type: 'alias', + }, + 'dest.stats.net_packets_total': { + category: 'dest', + name: 'dest.stats.net_packets_total', + type: 'alias', + }, + status: { + category: 'base', + description: + 'The high level status of the transaction. The way to compute this value depends on the protocol, but the result has a meaning independent of the protocol. ', + name: 'status', + }, + method: { + category: 'base', + description: + 'The command/verb/method of the transaction. For HTTP, this is the method name (GET, POST, PUT, and so on), for SQL this is the verb (SELECT, UPDATE, DELETE, and so on). ', + name: 'method', + }, + resource: { + category: 'base', + description: + 'The logical resource that this transaction refers to. For HTTP, this is the URL path up to the last slash (/). For example, if the URL is `/users/1`, the resource is `/users`. For databases, the resource is typically the table name. The field is not filled for all transaction types. ', + name: 'resource', + }, + path: { + category: 'base', + description: + 'The path the transaction refers to. For HTTP, this is the URL. For SQL databases, this is the table name. For key-value stores, this is the key. ', + name: 'path', + }, + query: { + category: 'base', + description: + 'The query in a human readable format. For HTTP, it will typically be something like `GET /users/_search?name=test`. For MySQL, it is something like `SELECT id from users where name=test`. ', + name: 'query', + type: 'keyword', + }, + params: { + category: 'base', + description: + 'The request parameters. For HTTP, these are the POST or GET parameters. For Thrift-RPC, these are the parameters from the request. ', + name: 'params', + type: 'text', + }, + notes: { + category: 'base', + description: + 'Messages from Packetbeat itself. This field usually contains error messages for interpreting the raw data. This information can be helpful for troubleshooting. ', + name: 'notes', + type: 'alias', + }, + request: { + category: 'base', + description: + 'For text protocols, this is the request as seen on the wire (application layer only). For binary protocols this is our representation of the request. ', + name: 'request', + type: 'text', + }, + response: { + category: 'base', + description: + 'For text protocols, this is the response as seen on the wire (application layer only). For binary protocols this is our representation of the request. ', + name: 'response', + type: 'text', + }, + bytes_in: { + category: 'base', + description: + 'The number of bytes of the request. Note that this size is the application layer message length, without the length of the IP or TCP headers. ', + name: 'bytes_in', + type: 'alias', + }, + bytes_out: { + category: 'base', + description: + 'The number of bytes of the response. Note that this size is the application layer message length, without the length of the IP or TCP headers. ', + name: 'bytes_out', + type: 'alias', + }, + 'amqp.reply-code': { + category: 'amqp', + description: 'AMQP reply code to an error, similar to http reply-code ', + example: 404, + name: 'amqp.reply-code', + type: 'long', + }, + 'amqp.reply-text': { + category: 'amqp', + description: 'Text explaining the error. ', + name: 'amqp.reply-text', + type: 'keyword', + }, + 'amqp.class-id': { + category: 'amqp', + description: 'Failing method class. ', + name: 'amqp.class-id', + type: 'long', + }, + 'amqp.method-id': { + category: 'amqp', + description: 'Failing method ID. ', + name: 'amqp.method-id', + type: 'long', + }, + 'amqp.exchange': { + category: 'amqp', + description: 'Name of the exchange. ', + name: 'amqp.exchange', + type: 'keyword', + }, + 'amqp.exchange-type': { + category: 'amqp', + description: 'Exchange type. ', + example: 'fanout', + name: 'amqp.exchange-type', + type: 'keyword', + }, + 'amqp.passive': { + category: 'amqp', + description: 'If set, do not create exchange/queue. ', + name: 'amqp.passive', + type: 'boolean', + }, + 'amqp.durable': { + category: 'amqp', + description: 'If set, request a durable exchange/queue. ', + name: 'amqp.durable', + type: 'boolean', + }, + 'amqp.exclusive': { + category: 'amqp', + description: 'If set, request an exclusive queue. ', + name: 'amqp.exclusive', + type: 'boolean', + }, + 'amqp.auto-delete': { + category: 'amqp', + description: 'If set, auto-delete queue when unused. ', + name: 'amqp.auto-delete', + type: 'boolean', + }, + 'amqp.no-wait': { + category: 'amqp', + description: 'If set, the server will not respond to the method. ', + name: 'amqp.no-wait', + type: 'boolean', + }, + 'amqp.consumer-tag': { + category: 'amqp', + description: 'Identifier for the consumer, valid within the current channel. ', + name: 'amqp.consumer-tag', + }, + 'amqp.delivery-tag': { + category: 'amqp', + description: 'The server-assigned and channel-specific delivery tag. ', + name: 'amqp.delivery-tag', + type: 'long', + }, + 'amqp.message-count': { + category: 'amqp', + description: + 'The number of messages in the queue, which will be zero for newly-declared queues. ', + name: 'amqp.message-count', + type: 'long', + }, + 'amqp.consumer-count': { + category: 'amqp', + description: 'The number of consumers of a queue. ', + name: 'amqp.consumer-count', + type: 'long', + }, + 'amqp.routing-key': { + category: 'amqp', + description: 'Message routing key. ', + name: 'amqp.routing-key', + type: 'keyword', + }, + 'amqp.no-ack': { + category: 'amqp', + description: 'If set, the server does not expect acknowledgements for messages. ', + name: 'amqp.no-ack', + type: 'boolean', + }, + 'amqp.no-local': { + category: 'amqp', + description: + 'If set, the server will not send messages to the connection that published them. ', + name: 'amqp.no-local', + type: 'boolean', + }, + 'amqp.if-unused': { + category: 'amqp', + description: 'Delete only if unused. ', + name: 'amqp.if-unused', + type: 'boolean', + }, + 'amqp.if-empty': { + category: 'amqp', + description: 'Delete only if empty. ', + name: 'amqp.if-empty', + type: 'boolean', + }, + 'amqp.queue': { + category: 'amqp', + description: 'The queue name identifies the queue within the vhost. ', + name: 'amqp.queue', + type: 'keyword', + }, + 'amqp.redelivered': { + category: 'amqp', + description: + 'Indicates that the message has been previously delivered to this or another client. ', + name: 'amqp.redelivered', + type: 'boolean', + }, + 'amqp.multiple': { + category: 'amqp', + description: 'Acknowledge multiple messages. ', + name: 'amqp.multiple', + type: 'boolean', + }, + 'amqp.arguments': { + category: 'amqp', + description: 'Optional additional arguments passed to some methods. Can be of various types. ', + name: 'amqp.arguments', + type: 'object', + }, + 'amqp.mandatory': { + category: 'amqp', + description: 'Indicates mandatory routing. ', + name: 'amqp.mandatory', + type: 'boolean', + }, + 'amqp.immediate': { + category: 'amqp', + description: 'Request immediate delivery. ', + name: 'amqp.immediate', + type: 'boolean', + }, + 'amqp.content-type': { + category: 'amqp', + description: 'MIME content type. ', + example: 'text/plain', + name: 'amqp.content-type', + type: 'keyword', + }, + 'amqp.content-encoding': { + category: 'amqp', + description: 'MIME content encoding. ', + name: 'amqp.content-encoding', + type: 'keyword', + }, + 'amqp.headers': { + category: 'amqp', + description: 'Message header field table. ', + name: 'amqp.headers', + type: 'object', + }, + 'amqp.delivery-mode': { + category: 'amqp', + description: 'Non-persistent (1) or persistent (2). ', + name: 'amqp.delivery-mode', + type: 'keyword', + }, + 'amqp.priority': { + category: 'amqp', + description: 'Message priority, 0 to 9. ', + name: 'amqp.priority', + type: 'long', + }, + 'amqp.correlation-id': { + category: 'amqp', + description: 'Application correlation identifier. ', + name: 'amqp.correlation-id', + type: 'keyword', + }, + 'amqp.reply-to': { + category: 'amqp', + description: 'Address to reply to. ', + name: 'amqp.reply-to', + type: 'keyword', + }, + 'amqp.expiration': { + category: 'amqp', + description: 'Message expiration specification. ', + name: 'amqp.expiration', + type: 'keyword', + }, + 'amqp.message-id': { + category: 'amqp', + description: 'Application message identifier. ', + name: 'amqp.message-id', + type: 'keyword', + }, + 'amqp.timestamp': { + category: 'amqp', + description: 'Message timestamp. ', + name: 'amqp.timestamp', + type: 'keyword', + }, + 'amqp.type': { + category: 'amqp', + description: 'Message type name. ', + name: 'amqp.type', + type: 'keyword', + }, + 'amqp.user-id': { + category: 'amqp', + description: 'Creating user id. ', + name: 'amqp.user-id', + type: 'keyword', + }, + 'amqp.app-id': { + category: 'amqp', + description: 'Creating application id. ', + name: 'amqp.app-id', + type: 'keyword', + }, + no_request: { + category: 'base', + name: 'no_request', + type: 'alias', + }, + 'cassandra.no_request': { + category: 'cassandra', + description: 'Indicates that there is no request because this is a PUSH message. ', + name: 'cassandra.no_request', + type: 'boolean', + }, + 'cassandra.request.headers.version': { + category: 'cassandra', + description: 'The version of the protocol.', + name: 'cassandra.request.headers.version', + type: 'long', + }, + 'cassandra.request.headers.flags': { + category: 'cassandra', + description: 'Flags applying to this frame.', + name: 'cassandra.request.headers.flags', + type: 'keyword', + }, + 'cassandra.request.headers.stream': { + category: 'cassandra', + description: + 'A frame has a stream id. If a client sends a request message with the stream id X, it is guaranteed that the stream id of the response to that message will be X.', + name: 'cassandra.request.headers.stream', + type: 'keyword', + }, + 'cassandra.request.headers.op': { + category: 'cassandra', + description: 'An operation type that distinguishes the actual message.', + name: 'cassandra.request.headers.op', + type: 'keyword', + }, + 'cassandra.request.headers.length': { + category: 'cassandra', + description: + 'A integer representing the length of the body of the frame (a frame is limited to 256MB in length).', + name: 'cassandra.request.headers.length', + type: 'long', + }, + 'cassandra.request.query': { + category: 'cassandra', + description: 'The CQL query which client send to cassandra.', + name: 'cassandra.request.query', + type: 'keyword', + }, + 'cassandra.response.headers.version': { + category: 'cassandra', + description: 'The version of the protocol.', + name: 'cassandra.response.headers.version', + type: 'long', + }, + 'cassandra.response.headers.flags': { + category: 'cassandra', + description: 'Flags applying to this frame.', + name: 'cassandra.response.headers.flags', + type: 'keyword', + }, + 'cassandra.response.headers.stream': { + category: 'cassandra', + description: + 'A frame has a stream id. If a client sends a request message with the stream id X, it is guaranteed that the stream id of the response to that message will be X.', + name: 'cassandra.response.headers.stream', + type: 'keyword', + }, + 'cassandra.response.headers.op': { + category: 'cassandra', + description: 'An operation type that distinguishes the actual message.', + name: 'cassandra.response.headers.op', + type: 'keyword', + }, + 'cassandra.response.headers.length': { + category: 'cassandra', + description: + 'A integer representing the length of the body of the frame (a frame is limited to 256MB in length).', + name: 'cassandra.response.headers.length', + type: 'long', + }, + 'cassandra.response.result.type': { + category: 'cassandra', + description: 'Cassandra result type.', + name: 'cassandra.response.result.type', + type: 'keyword', + }, + 'cassandra.response.result.rows.num_rows': { + category: 'cassandra', + description: 'Representing the number of rows present in this result.', + name: 'cassandra.response.result.rows.num_rows', + type: 'long', + }, + 'cassandra.response.result.rows.meta.keyspace': { + category: 'cassandra', + description: 'Only present after set Global_tables_spec, the keyspace name.', + name: 'cassandra.response.result.rows.meta.keyspace', + type: 'keyword', + }, + 'cassandra.response.result.rows.meta.table': { + category: 'cassandra', + description: 'Only present after set Global_tables_spec, the table name.', + name: 'cassandra.response.result.rows.meta.table', + type: 'keyword', + }, + 'cassandra.response.result.rows.meta.flags': { + category: 'cassandra', + description: 'Provides information on the formatting of the remaining information.', + name: 'cassandra.response.result.rows.meta.flags', + type: 'keyword', + }, + 'cassandra.response.result.rows.meta.col_count': { + category: 'cassandra', + description: + 'Representing the number of columns selected by the query that produced this result.', + name: 'cassandra.response.result.rows.meta.col_count', + type: 'long', + }, + 'cassandra.response.result.rows.meta.pkey_columns': { + category: 'cassandra', + description: 'Representing the PK columns index and counts.', + name: 'cassandra.response.result.rows.meta.pkey_columns', + type: 'long', + }, + 'cassandra.response.result.rows.meta.paging_state': { + category: 'cassandra', + description: + 'The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query.', + name: 'cassandra.response.result.rows.meta.paging_state', + type: 'keyword', + }, + 'cassandra.response.result.keyspace': { + category: 'cassandra', + description: 'Indicating the name of the keyspace that has been set.', + name: 'cassandra.response.result.keyspace', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.change': { + category: 'cassandra', + description: 'Representing the type of changed involved.', + name: 'cassandra.response.result.schema_change.change', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.keyspace': { + category: 'cassandra', + description: 'This describes which keyspace has changed.', + name: 'cassandra.response.result.schema_change.keyspace', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.table': { + category: 'cassandra', + description: 'This describes which table has changed.', + name: 'cassandra.response.result.schema_change.table', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.object': { + category: 'cassandra', + description: + 'This describes the name of said affected object (either the table, user type, function, or aggregate name).', + name: 'cassandra.response.result.schema_change.object', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.target': { + category: 'cassandra', + description: 'Target could be "FUNCTION" or "AGGREGATE", multiple arguments.', + name: 'cassandra.response.result.schema_change.target', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.name': { + category: 'cassandra', + description: 'The function/aggregate name.', + name: 'cassandra.response.result.schema_change.name', + type: 'keyword', + }, + 'cassandra.response.result.schema_change.args': { + category: 'cassandra', + description: 'One string for each argument type (as CQL type).', + name: 'cassandra.response.result.schema_change.args', + type: 'keyword', + }, + 'cassandra.response.result.prepared.prepared_id': { + category: 'cassandra', + description: 'Representing the prepared query ID.', + name: 'cassandra.response.result.prepared.prepared_id', + type: 'keyword', + }, + 'cassandra.response.result.prepared.req_meta.keyspace': { + category: 'cassandra', + description: 'Only present after set Global_tables_spec, the keyspace name.', + name: 'cassandra.response.result.prepared.req_meta.keyspace', + type: 'keyword', + }, + 'cassandra.response.result.prepared.req_meta.table': { + category: 'cassandra', + description: 'Only present after set Global_tables_spec, the table name.', + name: 'cassandra.response.result.prepared.req_meta.table', + type: 'keyword', + }, + 'cassandra.response.result.prepared.req_meta.flags': { + category: 'cassandra', + description: 'Provides information on the formatting of the remaining information.', + name: 'cassandra.response.result.prepared.req_meta.flags', + type: 'keyword', + }, + 'cassandra.response.result.prepared.req_meta.col_count': { + category: 'cassandra', + description: + 'Representing the number of columns selected by the query that produced this result.', + name: 'cassandra.response.result.prepared.req_meta.col_count', + type: 'long', + }, + 'cassandra.response.result.prepared.req_meta.pkey_columns': { + category: 'cassandra', + description: 'Representing the PK columns index and counts.', + name: 'cassandra.response.result.prepared.req_meta.pkey_columns', + type: 'long', + }, + 'cassandra.response.result.prepared.req_meta.paging_state': { + category: 'cassandra', + description: + 'The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query.', + name: 'cassandra.response.result.prepared.req_meta.paging_state', + type: 'keyword', + }, + 'cassandra.response.result.prepared.resp_meta.keyspace': { + category: 'cassandra', + description: 'Only present after set Global_tables_spec, the keyspace name.', + name: 'cassandra.response.result.prepared.resp_meta.keyspace', + type: 'keyword', + }, + 'cassandra.response.result.prepared.resp_meta.table': { + category: 'cassandra', + description: 'Only present after set Global_tables_spec, the table name.', + name: 'cassandra.response.result.prepared.resp_meta.table', + type: 'keyword', + }, + 'cassandra.response.result.prepared.resp_meta.flags': { + category: 'cassandra', + description: 'Provides information on the formatting of the remaining information.', + name: 'cassandra.response.result.prepared.resp_meta.flags', + type: 'keyword', + }, + 'cassandra.response.result.prepared.resp_meta.col_count': { + category: 'cassandra', + description: + 'Representing the number of columns selected by the query that produced this result.', + name: 'cassandra.response.result.prepared.resp_meta.col_count', + type: 'long', + }, + 'cassandra.response.result.prepared.resp_meta.pkey_columns': { + category: 'cassandra', + description: 'Representing the PK columns index and counts.', + name: 'cassandra.response.result.prepared.resp_meta.pkey_columns', + type: 'long', + }, + 'cassandra.response.result.prepared.resp_meta.paging_state': { + category: 'cassandra', + description: + 'The paging_state is a bytes value that should be used in QUERY/EXECUTE to continue paging and retrieve the remainder of the result for this query.', + name: 'cassandra.response.result.prepared.resp_meta.paging_state', + type: 'keyword', + }, + 'cassandra.response.supported': { + category: 'cassandra', + description: + 'Indicates which startup options are supported by the server. This message comes as a response to an OPTIONS message.', + name: 'cassandra.response.supported', + type: 'object', + }, + 'cassandra.response.authentication.class': { + category: 'cassandra', + description: 'Indicates the full class name of the IAuthenticator in use', + name: 'cassandra.response.authentication.class', + type: 'keyword', + }, + 'cassandra.response.warnings': { + category: 'cassandra', + description: 'The text of the warnings, only occur when Warning flag was set.', + name: 'cassandra.response.warnings', + type: 'keyword', + }, + 'cassandra.response.event.type': { + category: 'cassandra', + description: 'Representing the event type.', + name: 'cassandra.response.event.type', + type: 'keyword', + }, + 'cassandra.response.event.change': { + category: 'cassandra', + description: + 'The message corresponding respectively to the type of change followed by the address of the new/removed node.', + name: 'cassandra.response.event.change', + type: 'keyword', + }, + 'cassandra.response.event.host': { + category: 'cassandra', + description: 'Representing the node ip.', + name: 'cassandra.response.event.host', + type: 'keyword', + }, + 'cassandra.response.event.port': { + category: 'cassandra', + description: 'Representing the node port.', + name: 'cassandra.response.event.port', + type: 'long', + }, + 'cassandra.response.event.schema_change.change': { + category: 'cassandra', + description: 'Representing the type of changed involved.', + name: 'cassandra.response.event.schema_change.change', + type: 'keyword', + }, + 'cassandra.response.event.schema_change.keyspace': { + category: 'cassandra', + description: 'This describes which keyspace has changed.', + name: 'cassandra.response.event.schema_change.keyspace', + type: 'keyword', + }, + 'cassandra.response.event.schema_change.table': { + category: 'cassandra', + description: 'This describes which table has changed.', + name: 'cassandra.response.event.schema_change.table', + type: 'keyword', + }, + 'cassandra.response.event.schema_change.object': { + category: 'cassandra', + description: + 'This describes the name of said affected object (either the table, user type, function, or aggregate name).', + name: 'cassandra.response.event.schema_change.object', + type: 'keyword', + }, + 'cassandra.response.event.schema_change.target': { + category: 'cassandra', + description: 'Target could be "FUNCTION" or "AGGREGATE", multiple arguments.', + name: 'cassandra.response.event.schema_change.target', + type: 'keyword', + }, + 'cassandra.response.event.schema_change.name': { + category: 'cassandra', + description: 'The function/aggregate name.', + name: 'cassandra.response.event.schema_change.name', + type: 'keyword', + }, + 'cassandra.response.event.schema_change.args': { + category: 'cassandra', + description: 'One string for each argument type (as CQL type).', + name: 'cassandra.response.event.schema_change.args', + type: 'keyword', + }, + 'cassandra.response.error.code': { + category: 'cassandra', + description: 'The error code of the Cassandra response.', + name: 'cassandra.response.error.code', + type: 'long', + }, + 'cassandra.response.error.msg': { + category: 'cassandra', + description: 'The error message of the Cassandra response.', + name: 'cassandra.response.error.msg', + type: 'keyword', + }, + 'cassandra.response.error.type': { + category: 'cassandra', + description: 'The error type of the Cassandra response.', + name: 'cassandra.response.error.type', + type: 'keyword', + }, + 'cassandra.response.error.details.read_consistency': { + category: 'cassandra', + description: 'Representing the consistency level of the query that triggered the exception.', + name: 'cassandra.response.error.details.read_consistency', + type: 'keyword', + }, + 'cassandra.response.error.details.required': { + category: 'cassandra', + description: + 'Representing the number of nodes that should be alive to respect consistency level.', + name: 'cassandra.response.error.details.required', + type: 'long', + }, + 'cassandra.response.error.details.alive': { + category: 'cassandra', + description: + 'Representing the number of replicas that were known to be alive when the request had been processed (since an unavailable exception has been triggered).', + name: 'cassandra.response.error.details.alive', + type: 'long', + }, + 'cassandra.response.error.details.received': { + category: 'cassandra', + description: 'Representing the number of nodes having acknowledged the request.', + name: 'cassandra.response.error.details.received', + type: 'long', + }, + 'cassandra.response.error.details.blockfor': { + category: 'cassandra', + description: + 'Representing the number of replicas whose acknowledgement is required to achieve consistency level.', + name: 'cassandra.response.error.details.blockfor', + type: 'long', + }, + 'cassandra.response.error.details.write_type': { + category: 'cassandra', + description: 'Describe the type of the write that timed out.', + name: 'cassandra.response.error.details.write_type', + type: 'keyword', + }, + 'cassandra.response.error.details.data_present': { + category: 'cassandra', + description: 'It means the replica that was asked for data had responded.', + name: 'cassandra.response.error.details.data_present', + type: 'boolean', + }, + 'cassandra.response.error.details.keyspace': { + category: 'cassandra', + description: 'The keyspace of the failed function.', + name: 'cassandra.response.error.details.keyspace', + type: 'keyword', + }, + 'cassandra.response.error.details.table': { + category: 'cassandra', + description: 'The keyspace of the failed function.', + name: 'cassandra.response.error.details.table', + type: 'keyword', + }, + 'cassandra.response.error.details.stmt_id': { + category: 'cassandra', + description: 'Representing the unknown ID.', + name: 'cassandra.response.error.details.stmt_id', + type: 'keyword', + }, + 'cassandra.response.error.details.num_failures': { + category: 'cassandra', + description: + 'Representing the number of nodes that experience a failure while executing the request.', + name: 'cassandra.response.error.details.num_failures', + type: 'keyword', + }, + 'cassandra.response.error.details.function': { + category: 'cassandra', + description: 'The name of the failed function.', + name: 'cassandra.response.error.details.function', + type: 'keyword', + }, + 'cassandra.response.error.details.arg_types': { + category: 'cassandra', + description: 'One string for each argument type (as CQL type) of the failed function.', + name: 'cassandra.response.error.details.arg_types', + type: 'keyword', + }, + 'dhcpv4.transaction_id': { + category: 'dhcpv4', + description: + 'Transaction ID, a random number chosen by the client, used by the client and server to associate messages and responses between a client and a server. ', + name: 'dhcpv4.transaction_id', + type: 'keyword', + }, + 'dhcpv4.seconds': { + category: 'dhcpv4', + description: + 'Number of seconds elapsed since client began address acquisition or renewal process. ', + name: 'dhcpv4.seconds', + type: 'long', + }, + 'dhcpv4.flags': { + category: 'dhcpv4', + description: + 'Flags are set by the client to indicate how the DHCP server should its reply -- either unicast or broadcast. ', + name: 'dhcpv4.flags', + type: 'keyword', + }, + 'dhcpv4.client_ip': { + category: 'dhcpv4', + description: 'The current IP address of the client.', + name: 'dhcpv4.client_ip', + type: 'ip', + }, + 'dhcpv4.assigned_ip': { + category: 'dhcpv4', + description: + 'The IP address that the DHCP server is assigning to the client. This field is also known as "your" IP address. ', + name: 'dhcpv4.assigned_ip', + type: 'ip', + }, + 'dhcpv4.server_ip': { + category: 'dhcpv4', + description: + 'The IP address of the DHCP server that the client should use for the next step in the bootstrap process. ', + name: 'dhcpv4.server_ip', + type: 'ip', + }, + 'dhcpv4.relay_ip': { + category: 'dhcpv4', + description: + 'The relay IP address used by the client to contact the server (i.e. a DHCP relay server). ', + name: 'dhcpv4.relay_ip', + type: 'ip', + }, + 'dhcpv4.client_mac': { + category: 'dhcpv4', + description: "The client's MAC address (layer two).", + name: 'dhcpv4.client_mac', + type: 'keyword', + }, + 'dhcpv4.server_name': { + category: 'dhcpv4', + description: + 'The name of the server sending the message. Optional. Used in DHCPOFFER or DHCPACK messages. ', + name: 'dhcpv4.server_name', + type: 'keyword', + }, + 'dhcpv4.op_code': { + category: 'dhcpv4', + description: 'The message op code (bootrequest or bootreply). ', + example: 'bootreply', + name: 'dhcpv4.op_code', + type: 'keyword', + }, + 'dhcpv4.hops': { + category: 'dhcpv4', + description: 'The number of hops the DHCP message went through.', + name: 'dhcpv4.hops', + type: 'long', + }, + 'dhcpv4.hardware_type': { + category: 'dhcpv4', + description: 'The type of hardware used for the local network (Ethernet, LocalTalk, etc). ', + name: 'dhcpv4.hardware_type', + type: 'keyword', + }, + 'dhcpv4.option.message_type': { + category: 'dhcpv4', + description: + 'The specific type of DHCP message being sent (e.g. discover, offer, request, decline, ack, nak, release, inform). ', + example: 'ack', + name: 'dhcpv4.option.message_type', + type: 'keyword', + }, + 'dhcpv4.option.parameter_request_list': { + category: 'dhcpv4', + description: + 'This option is used by a DHCP client to request values for specified configuration parameters. ', + name: 'dhcpv4.option.parameter_request_list', + type: 'keyword', + }, + 'dhcpv4.option.requested_ip_address': { + category: 'dhcpv4', + description: + 'This option is used in a client request (DHCPDISCOVER) to allow the client to request that a particular IP address be assigned. ', + name: 'dhcpv4.option.requested_ip_address', + type: 'ip', + }, + 'dhcpv4.option.server_identifier': { + category: 'dhcpv4', + description: 'IP address of the individual DHCP server which handled this message. ', + name: 'dhcpv4.option.server_identifier', + type: 'ip', + }, + 'dhcpv4.option.broadcast_address': { + category: 'dhcpv4', + description: "This option specifies the broadcast address in use on the client's subnet. ", + name: 'dhcpv4.option.broadcast_address', + type: 'ip', + }, + 'dhcpv4.option.max_dhcp_message_size': { + category: 'dhcpv4', + description: + 'This option specifies the maximum length DHCP message that the client is willing to accept. ', + name: 'dhcpv4.option.max_dhcp_message_size', + type: 'long', + }, + 'dhcpv4.option.class_identifier': { + category: 'dhcpv4', + description: + "This option is used by DHCP clients to optionally identify the vendor type and configuration of a DHCP client. Vendors may choose to define specific vendor class identifiers to convey particular configuration or other identification information about a client. For example, the identifier may encode the client's hardware configuration. ", + name: 'dhcpv4.option.class_identifier', + type: 'keyword', + }, + 'dhcpv4.option.domain_name': { + category: 'dhcpv4', + description: + 'This option specifies the domain name that client should use when resolving hostnames via the Domain Name System. ', + name: 'dhcpv4.option.domain_name', + type: 'keyword', + }, + 'dhcpv4.option.dns_servers': { + category: 'dhcpv4', + description: + 'The domain name server option specifies a list of Domain Name System servers available to the client. ', + name: 'dhcpv4.option.dns_servers', + type: 'ip', + }, + 'dhcpv4.option.vendor_identifying_options': { + category: 'dhcpv4', + description: + 'A DHCP client may use this option to unambiguously identify the vendor that manufactured the hardware on which the client is running, the software in use, or an industry consortium to which the vendor belongs. This field is described in RFC 3925. ', + name: 'dhcpv4.option.vendor_identifying_options', + type: 'object', + }, + 'dhcpv4.option.subnet_mask': { + category: 'dhcpv4', + description: 'The subnet mask that the client should use on the currnet network. ', + name: 'dhcpv4.option.subnet_mask', + type: 'ip', + }, + 'dhcpv4.option.utc_time_offset_sec': { + category: 'dhcpv4', + description: + "The time offset field specifies the offset of the client's subnet in seconds from Coordinated Universal Time (UTC). ", + name: 'dhcpv4.option.utc_time_offset_sec', + type: 'long', + }, + 'dhcpv4.option.router': { + category: 'dhcpv4', + description: + "The router option specifies a list of IP addresses for routers on the client's subnet. ", + name: 'dhcpv4.option.router', + type: 'ip', + }, + 'dhcpv4.option.time_servers': { + category: 'dhcpv4', + description: + 'The time server option specifies a list of RFC 868 time servers available to the client. ', + name: 'dhcpv4.option.time_servers', + type: 'ip', + }, + 'dhcpv4.option.ntp_servers': { + category: 'dhcpv4', + description: + 'This option specifies a list of IP addresses indicating NTP servers available to the client. ', + name: 'dhcpv4.option.ntp_servers', + type: 'ip', + }, + 'dhcpv4.option.hostname': { + category: 'dhcpv4', + description: 'This option specifies the name of the client. ', + name: 'dhcpv4.option.hostname', + type: 'keyword', + }, + 'dhcpv4.option.ip_address_lease_time_sec': { + category: 'dhcpv4', + description: + 'This option is used in a client request (DHCPDISCOVER or DHCPREQUEST) to allow the client to request a lease time for the IP address. In a server reply (DHCPOFFER), a DHCP server uses this option to specify the lease time it is willing to offer. ', + name: 'dhcpv4.option.ip_address_lease_time_sec', + type: 'long', + }, + 'dhcpv4.option.message': { + category: 'dhcpv4', + description: + 'This option is used by a DHCP server to provide an error message to a DHCP client in a DHCPNAK message in the event of a failure. A client may use this option in a DHCPDECLINE message to indicate the why the client declined the offered parameters. ', + name: 'dhcpv4.option.message', + type: 'text', + }, + 'dhcpv4.option.renewal_time_sec': { + category: 'dhcpv4', + description: + 'This option specifies the time interval from address assignment until the client transitions to the RENEWING state. ', + name: 'dhcpv4.option.renewal_time_sec', + type: 'long', + }, + 'dhcpv4.option.rebinding_time_sec': { + category: 'dhcpv4', + description: + 'This option specifies the time interval from address assignment until the client transitions to the REBINDING state. ', + name: 'dhcpv4.option.rebinding_time_sec', + type: 'long', + }, + 'dhcpv4.option.boot_file_name': { + category: 'dhcpv4', + description: + "This option is used to identify a bootfile when the 'file' field in the DHCP header has been used for DHCP options. ", + name: 'dhcpv4.option.boot_file_name', + type: 'keyword', + }, + 'dns.flags.authoritative': { + category: 'dns', + description: + 'A DNS flag specifying that the responding server is an authority for the domain name used in the question. ', + name: 'dns.flags.authoritative', + type: 'boolean', + }, + 'dns.flags.recursion_available': { + category: 'dns', + description: + 'A DNS flag specifying whether recursive query support is available in the name server. ', + name: 'dns.flags.recursion_available', + type: 'boolean', + }, + 'dns.flags.recursion_desired': { + category: 'dns', + description: + 'A DNS flag specifying that the client directs the server to pursue a query recursively. Recursive query support is optional. ', + name: 'dns.flags.recursion_desired', + type: 'boolean', + }, + 'dns.flags.authentic_data': { + category: 'dns', + description: + 'A DNS flag specifying that the recursive server considers the response authentic. ', + name: 'dns.flags.authentic_data', + type: 'boolean', + }, + 'dns.flags.checking_disabled': { + category: 'dns', + description: + 'A DNS flag specifying that the client disables the server signature validation of the query. ', + name: 'dns.flags.checking_disabled', + type: 'boolean', + }, + 'dns.flags.truncated_response': { + category: 'dns', + description: 'A DNS flag specifying that only the first 512 bytes of the reply were returned. ', + name: 'dns.flags.truncated_response', + type: 'boolean', + }, + 'dns.question.etld_plus_one': { + category: 'dns', + description: + 'The effective top-level domain (eTLD) plus one more label. For example, the eTLD+1 for "foo.bar.golang.org." is "golang.org.". The data for determining the eTLD comes from an embedded copy of the data from http://publicsuffix.org.', + example: 'amazon.co.uk.', + name: 'dns.question.etld_plus_one', + }, + 'dns.answers_count': { + category: 'dns', + description: 'The number of resource records contained in the `dns.answers` field. ', + name: 'dns.answers_count', + type: 'long', + }, + 'dns.authorities': { + category: 'dns', + description: 'An array containing a dictionary for each authority section from the answer. ', + name: 'dns.authorities', + type: 'object', + }, + 'dns.authorities_count': { + category: 'dns', + description: + 'The number of resource records contained in the `dns.authorities` field. The `dns.authorities` field may or may not be included depending on the configuration of Packetbeat. ', + name: 'dns.authorities_count', + type: 'long', + }, + 'dns.authorities.name': { + category: 'dns', + description: 'The domain name to which this resource record pertains.', + example: 'example.com.', + name: 'dns.authorities.name', + }, + 'dns.authorities.type': { + category: 'dns', + description: 'The type of data contained in this resource record.', + example: 'NS', + name: 'dns.authorities.type', + }, + 'dns.authorities.class': { + category: 'dns', + description: 'The class of DNS data contained in this resource record.', + example: 'IN', + name: 'dns.authorities.class', + }, + 'dns.additionals': { + category: 'dns', + description: 'An array containing a dictionary for each additional section from the answer. ', + name: 'dns.additionals', + type: 'object', + }, + 'dns.additionals_count': { + category: 'dns', + description: + 'The number of resource records contained in the `dns.additionals` field. The `dns.additionals` field may or may not be included depending on the configuration of Packetbeat. ', + name: 'dns.additionals_count', + type: 'long', + }, + 'dns.additionals.name': { + category: 'dns', + description: 'The domain name to which this resource record pertains.', + example: 'example.com.', + name: 'dns.additionals.name', + }, + 'dns.additionals.type': { + category: 'dns', + description: 'The type of data contained in this resource record.', + example: 'NS', + name: 'dns.additionals.type', + }, + 'dns.additionals.class': { + category: 'dns', + description: 'The class of DNS data contained in this resource record.', + example: 'IN', + name: 'dns.additionals.class', + }, + 'dns.additionals.ttl': { + category: 'dns', + description: + 'The time interval in seconds that this resource record may be cached before it should be discarded. Zero values mean that the data should not be cached. ', + name: 'dns.additionals.ttl', + type: 'long', + }, + 'dns.additionals.data': { + category: 'dns', + description: + 'The data describing the resource. The meaning of this data depends on the type and class of the resource record. ', + name: 'dns.additionals.data', + }, + 'dns.opt.version': { + category: 'dns', + description: 'The EDNS version.', + example: '0', + name: 'dns.opt.version', + }, + 'dns.opt.do': { + category: 'dns', + description: 'If set, the transaction uses DNSSEC.', + name: 'dns.opt.do', + type: 'boolean', + }, + 'dns.opt.ext_rcode': { + category: 'dns', + description: 'Extended response code field.', + example: 'BADVERS', + name: 'dns.opt.ext_rcode', + }, + 'dns.opt.udp_size': { + category: 'dns', + description: "Requestor's UDP payload size (in bytes).", + name: 'dns.opt.udp_size', + type: 'long', + }, + 'http.request.headers': { + category: 'http', + description: + 'A map containing the captured header fields from the request. Which headers to capture is configurable. If headers with the same header name are present in the message, they will be separated by commas. ', + name: 'http.request.headers', + type: 'object', + }, + 'http.request.params': { + category: 'http', + name: 'http.request.params', + type: 'alias', + }, + 'http.response.status_phrase': { + category: 'http', + description: 'The HTTP status phrase.', + example: 'Not Found', + name: 'http.response.status_phrase', + }, + 'http.response.headers': { + category: 'http', + description: + 'A map containing the captured header fields from the response. Which headers to capture is configurable. If headers with the same header name are present in the message, they will be separated by commas. ', + name: 'http.response.headers', + type: 'object', + }, + 'http.response.code': { + category: 'http', + name: 'http.response.code', + type: 'alias', + }, + 'http.response.phrase': { + category: 'http', + name: 'http.response.phrase', + type: 'alias', + }, + 'icmp.version': { + category: 'icmp', + description: 'The version of the ICMP protocol.', + name: 'icmp.version', + }, + 'icmp.request.message': { + category: 'icmp', + description: 'A human readable form of the request.', + name: 'icmp.request.message', + type: 'keyword', + }, + 'icmp.request.type': { + category: 'icmp', + description: 'The request type.', + name: 'icmp.request.type', + type: 'long', + }, + 'icmp.request.code': { + category: 'icmp', + description: 'The request code.', + name: 'icmp.request.code', + type: 'long', + }, + 'icmp.response.message': { + category: 'icmp', + description: 'A human readable form of the response.', + name: 'icmp.response.message', + type: 'keyword', + }, + 'icmp.response.type': { + category: 'icmp', + description: 'The response type.', + name: 'icmp.response.type', + type: 'long', + }, + 'icmp.response.code': { + category: 'icmp', + description: 'The response code.', + name: 'icmp.response.code', + type: 'long', + }, + 'memcache.protocol_type': { + category: 'memcache', + description: + 'The memcache protocol implementation. The value can be "binary" for binary-based, "text" for text-based, or "unknown" for an unknown memcache protocol type. ', + name: 'memcache.protocol_type', + type: 'keyword', + }, + 'memcache.request.line': { + category: 'memcache', + description: 'The raw command line for unknown commands ONLY. ', + name: 'memcache.request.line', + type: 'keyword', + }, + 'memcache.request.command': { + category: 'memcache', + description: + 'The memcache command being requested in the memcache text protocol. For example "set" or "get". The binary protocol opcodes are translated into memcache text protocol commands. ', + name: 'memcache.request.command', + type: 'keyword', + }, + 'memcache.response.command': { + category: 'memcache', + description: + 'Either the text based protocol response message type or the name of the originating request if binary protocol is used. ', + name: 'memcache.response.command', + type: 'keyword', + }, + 'memcache.request.type': { + category: 'memcache', + description: + 'The memcache command classification. This value can be "UNKNOWN", "Load", "Store", "Delete", "Counter", "Info", "SlabCtrl", "LRUCrawler", "Stats", "Success", "Fail", or "Auth". ', + name: 'memcache.request.type', + type: 'keyword', + }, + 'memcache.response.type': { + category: 'memcache', + description: + 'The memcache command classification. This value can be "UNKNOWN", "Load", "Store", "Delete", "Counter", "Info", "SlabCtrl", "LRUCrawler", "Stats", "Success", "Fail", or "Auth". The text based protocol will employ any of these, whereas the binary based protocol will mirror the request commands only (see `memcache.response.status` for binary protocol). ', + name: 'memcache.response.type', + type: 'keyword', + }, + 'memcache.response.error_msg': { + category: 'memcache', + description: 'The optional error message in the memcache response (text based protocol only). ', + name: 'memcache.response.error_msg', + type: 'keyword', + }, + 'memcache.request.opcode': { + category: 'memcache', + description: 'The binary protocol message opcode name. ', + name: 'memcache.request.opcode', + type: 'keyword', + }, + 'memcache.response.opcode': { + category: 'memcache', + description: 'The binary protocol message opcode name. ', + name: 'memcache.response.opcode', + type: 'keyword', + }, + 'memcache.request.opcode_value': { + category: 'memcache', + description: 'The binary protocol message opcode value. ', + name: 'memcache.request.opcode_value', + type: 'long', + }, + 'memcache.response.opcode_value': { + category: 'memcache', + description: 'The binary protocol message opcode value. ', + name: 'memcache.response.opcode_value', + type: 'long', + }, + 'memcache.request.opaque': { + category: 'memcache', + description: + 'The binary protocol opaque header value used for correlating request with response messages. ', + name: 'memcache.request.opaque', + type: 'long', + }, + 'memcache.response.opaque': { + category: 'memcache', + description: + 'The binary protocol opaque header value used for correlating request with response messages. ', + name: 'memcache.response.opaque', + type: 'long', + }, + 'memcache.request.vbucket': { + category: 'memcache', + description: 'The vbucket index sent in the binary message. ', + name: 'memcache.request.vbucket', + type: 'long', + }, + 'memcache.response.status': { + category: 'memcache', + description: 'The textual representation of the response error code (binary protocol only). ', + name: 'memcache.response.status', + type: 'keyword', + }, + 'memcache.response.status_code': { + category: 'memcache', + description: 'The status code value returned in the response (binary protocol only). ', + name: 'memcache.response.status_code', + type: 'long', + }, + 'memcache.request.keys': { + category: 'memcache', + description: 'The list of keys sent in the store or load commands. ', + name: 'memcache.request.keys', + type: 'array', + }, + 'memcache.response.keys': { + category: 'memcache', + description: 'The list of keys returned for the load command (if present). ', + name: 'memcache.response.keys', + type: 'array', + }, + 'memcache.request.count_values': { + category: 'memcache', + description: + 'The number of values found in the memcache request message. If the command does not send any data, this field is missing. ', + name: 'memcache.request.count_values', + type: 'long', + }, + 'memcache.response.count_values': { + category: 'memcache', + description: + 'The number of values found in the memcache response message. If the command does not send any data, this field is missing. ', + name: 'memcache.response.count_values', + type: 'long', + }, + 'memcache.request.values': { + category: 'memcache', + description: 'The list of base64 encoded values sent with the request (if present). ', + name: 'memcache.request.values', + type: 'array', + }, + 'memcache.response.values': { + category: 'memcache', + description: 'The list of base64 encoded values sent with the response (if present). ', + name: 'memcache.response.values', + type: 'array', + }, + 'memcache.request.bytes': { + category: 'memcache', + description: 'The byte count of the values being transferred. ', + name: 'memcache.request.bytes', + type: 'long', + format: 'bytes', + }, + 'memcache.response.bytes': { + category: 'memcache', + description: 'The byte count of the values being transferred. ', + name: 'memcache.response.bytes', + type: 'long', + format: 'bytes', + }, + 'memcache.request.delta': { + category: 'memcache', + description: 'The counter increment/decrement delta value. ', + name: 'memcache.request.delta', + type: 'long', + }, + 'memcache.request.initial': { + category: 'memcache', + description: 'The counter increment/decrement initial value parameter (binary protocol only). ', + name: 'memcache.request.initial', + type: 'long', + }, + 'memcache.request.verbosity': { + category: 'memcache', + description: 'The value of the memcache "verbosity" command. ', + name: 'memcache.request.verbosity', + type: 'long', + }, + 'memcache.request.raw_args': { + category: 'memcache', + description: + 'The text protocol raw arguments for the "stats ..." and "lru crawl ..." commands. ', + name: 'memcache.request.raw_args', + type: 'keyword', + }, + 'memcache.request.source_class': { + category: 'memcache', + description: "The source class id in 'slab reassign' command. ", + name: 'memcache.request.source_class', + type: 'long', + }, + 'memcache.request.dest_class': { + category: 'memcache', + description: "The destination class id in 'slab reassign' command. ", + name: 'memcache.request.dest_class', + type: 'long', + }, + 'memcache.request.automove': { + category: 'memcache', + description: + 'The automove mode in the \'slab automove\' command expressed as a string. This value can be "standby"(=0), "slow"(=1), "aggressive"(=2), or the raw value if the value is unknown. ', + name: 'memcache.request.automove', + type: 'keyword', + }, + 'memcache.request.flags': { + category: 'memcache', + description: 'The memcache command flags sent in the request (if present). ', + name: 'memcache.request.flags', + type: 'long', + }, + 'memcache.response.flags': { + category: 'memcache', + description: 'The memcache message flags sent in the response (if present). ', + name: 'memcache.response.flags', + type: 'long', + }, + 'memcache.request.exptime': { + category: 'memcache', + description: + 'The data expiry time in seconds sent with the memcache command (if present). If the value is <30 days, the expiry time is relative to "now", or else it is an absolute Unix time in seconds (32-bit). ', + name: 'memcache.request.exptime', + type: 'long', + }, + 'memcache.request.sleep_us': { + category: 'memcache', + description: "The sleep setting in microseconds for the 'lru_crawler sleep' command. ", + name: 'memcache.request.sleep_us', + type: 'long', + }, + 'memcache.response.value': { + category: 'memcache', + description: 'The counter value returned by a counter operation. ', + name: 'memcache.response.value', + type: 'long', + }, + 'memcache.request.noreply': { + category: 'memcache', + description: + 'Set to true if noreply was set in the request. The `memcache.response` field will be missing. ', + name: 'memcache.request.noreply', + type: 'boolean', + }, + 'memcache.request.quiet': { + category: 'memcache', + description: 'Set to true if the binary protocol message is to be treated as a quiet message. ', + name: 'memcache.request.quiet', + type: 'boolean', + }, + 'memcache.request.cas_unique': { + category: 'memcache', + description: 'The CAS (compare-and-swap) identifier if present. ', + name: 'memcache.request.cas_unique', + type: 'long', + }, + 'memcache.response.cas_unique': { + category: 'memcache', + description: + 'The CAS (compare-and-swap) identifier to be used with CAS-based updates (if present). ', + name: 'memcache.response.cas_unique', + type: 'long', + }, + 'memcache.response.stats': { + category: 'memcache', + description: + 'The list of statistic values returned. Each entry is a dictionary with the fields "name" and "value". ', + name: 'memcache.response.stats', + type: 'array', + }, + 'memcache.response.version': { + category: 'memcache', + description: 'The returned memcache version string. ', + name: 'memcache.response.version', + type: 'keyword', + }, + 'mongodb.error': { + category: 'mongodb', + description: + 'If the MongoDB request has resulted in an error, this field contains the error message returned by the server. ', + name: 'mongodb.error', + }, + 'mongodb.fullCollectionName': { + category: 'mongodb', + description: + 'The full collection name. The full collection name is the concatenation of the database name with the collection name, using a dot (.) for the concatenation. For example, for the database foo and the collection bar, the full collection name is foo.bar. ', + name: 'mongodb.fullCollectionName', + }, + 'mongodb.numberToSkip': { + category: 'mongodb', + description: + 'Sets the number of documents to omit - starting from the first document in the resulting dataset - when returning the result of the query. ', + name: 'mongodb.numberToSkip', + type: 'long', + }, + 'mongodb.numberToReturn': { + category: 'mongodb', + description: 'The requested maximum number of documents to be returned. ', + name: 'mongodb.numberToReturn', + type: 'long', + }, + 'mongodb.numberReturned': { + category: 'mongodb', + description: 'The number of documents in the reply. ', + name: 'mongodb.numberReturned', + type: 'long', + }, + 'mongodb.startingFrom': { + category: 'mongodb', + description: 'Where in the cursor this reply is starting. ', + name: 'mongodb.startingFrom', + }, + 'mongodb.query': { + category: 'mongodb', + description: + 'A JSON document that represents the query. The query will contain one or more elements, all of which must match for a document to be included in the result set. Possible elements include $query, $orderby, $hint, $explain, and $snapshot. ', + name: 'mongodb.query', + }, + 'mongodb.returnFieldsSelector': { + category: 'mongodb', + description: + 'A JSON document that limits the fields in the returned documents. The returnFieldsSelector contains one or more elements, each of which is the name of a field that should be returned, and the integer value 1. ', + name: 'mongodb.returnFieldsSelector', + }, + 'mongodb.selector': { + category: 'mongodb', + description: + 'A BSON document that specifies the query for selecting the document to update or delete. ', + name: 'mongodb.selector', + }, + 'mongodb.update': { + category: 'mongodb', + description: + 'A BSON document that specifies the update to be performed. For information on specifying updates, see the Update Operations documentation from the MongoDB Manual. ', + name: 'mongodb.update', + }, + 'mongodb.cursorId': { + category: 'mongodb', + description: + 'The cursor identifier returned in the OP_REPLY. This must be the value that was returned from the database. ', + name: 'mongodb.cursorId', + }, + 'mysql.affected_rows': { + category: 'mysql', + description: + 'If the MySQL command is successful, this field contains the affected number of rows of the last statement. ', + name: 'mysql.affected_rows', + type: 'long', + }, + 'mysql.insert_id': { + category: 'mysql', + description: + 'If the INSERT query is successful, this field contains the id of the newly inserted row. ', + name: 'mysql.insert_id', + }, + 'mysql.num_fields': { + category: 'mysql', + description: + 'If the SELECT query is successful, this field is set to the number of fields returned. ', + name: 'mysql.num_fields', + }, + 'mysql.num_rows': { + category: 'mysql', + description: + 'If the SELECT query is successful, this field is set to the number of rows returned. ', + name: 'mysql.num_rows', + }, + 'mysql.query': { + category: 'mysql', + description: "The row mysql query as read from the transaction's request. ", + name: 'mysql.query', + }, + 'mysql.error_code': { + category: 'mysql', + description: 'The error code returned by MySQL. ', + name: 'mysql.error_code', + type: 'long', + }, + 'mysql.error_message': { + category: 'mysql', + description: 'The error info message returned by MySQL. ', + name: 'mysql.error_message', + }, + 'nfs.version': { + category: 'nfs', + description: 'NFS protocol version number.', + name: 'nfs.version', + type: 'long', + }, + 'nfs.minor_version': { + category: 'nfs', + description: 'NFS protocol minor version number.', + name: 'nfs.minor_version', + type: 'long', + }, + 'nfs.tag': { + category: 'nfs', + description: 'NFS v4 COMPOUND operation tag.', + name: 'nfs.tag', + }, + 'nfs.opcode': { + category: 'nfs', + description: 'NFS operation name, or main operation name, in case of COMPOUND calls. ', + name: 'nfs.opcode', + }, + 'nfs.status': { + category: 'nfs', + description: 'NFS operation reply status.', + name: 'nfs.status', + }, + 'rpc.xid': { + category: 'rpc', + description: 'RPC message transaction identifier.', + name: 'rpc.xid', + }, + 'rpc.status': { + category: 'rpc', + description: 'RPC message reply status.', + name: 'rpc.status', + }, + 'rpc.auth_flavor': { + category: 'rpc', + description: 'RPC authentication flavor.', + name: 'rpc.auth_flavor', + }, + 'rpc.cred.uid': { + category: 'rpc', + description: "RPC caller's user id, in case of auth-unix.", + name: 'rpc.cred.uid', + type: 'long', + }, + 'rpc.cred.gid': { + category: 'rpc', + description: "RPC caller's group id, in case of auth-unix.", + name: 'rpc.cred.gid', + type: 'long', + }, + 'rpc.cred.gids': { + category: 'rpc', + description: "RPC caller's secondary group ids, in case of auth-unix.", + name: 'rpc.cred.gids', + }, + 'rpc.cred.stamp': { + category: 'rpc', + description: 'Arbitrary ID which the caller machine may generate.', + name: 'rpc.cred.stamp', + type: 'long', + }, + 'rpc.cred.machinename': { + category: 'rpc', + description: "The name of the caller's machine.", + name: 'rpc.cred.machinename', + }, + 'rpc.call_size': { + category: 'rpc', + description: 'RPC call size with argument.', + name: 'rpc.call_size', + type: 'alias', + }, + 'rpc.reply_size': { + category: 'rpc', + description: 'RPC reply size with argument.', + name: 'rpc.reply_size', + type: 'alias', + }, + 'pgsql.error_code': { + category: 'pgsql', + description: 'The PostgreSQL error code.', + name: 'pgsql.error_code', + type: 'long', + }, + 'pgsql.error_message': { + category: 'pgsql', + description: 'The PostgreSQL error message.', + name: 'pgsql.error_message', + }, + 'pgsql.error_severity': { + category: 'pgsql', + description: 'The PostgreSQL error severity.', + name: 'pgsql.error_severity', + }, + 'pgsql.num_fields': { + category: 'pgsql', + description: + 'If the SELECT query if successful, this field is set to the number of fields returned. ', + name: 'pgsql.num_fields', + }, + 'pgsql.num_rows': { + category: 'pgsql', + description: + 'If the SELECT query if successful, this field is set to the number of rows returned. ', + name: 'pgsql.num_rows', + }, + 'redis.return_value': { + category: 'redis', + description: 'The return value of the Redis command in a human readable format. ', + name: 'redis.return_value', + }, + 'redis.error': { + category: 'redis', + description: + 'If the Redis command has resulted in an error, this field contains the error message returned by the Redis server. ', + name: 'redis.error', + }, + 'thrift.params': { + category: 'thrift', + description: + 'The RPC method call parameters in a human readable format. If the IDL files are available, the parameters use names whenever possible. Otherwise, the IDs from the message are used. ', + name: 'thrift.params', + }, + 'thrift.service': { + category: 'thrift', + description: 'The name of the Thrift-RPC service as defined in the IDL files. ', + name: 'thrift.service', + }, + 'thrift.return_value': { + category: 'thrift', + description: + 'The value returned by the Thrift-RPC call. This is encoded in a human readable format. ', + name: 'thrift.return_value', + }, + 'thrift.exceptions': { + category: 'thrift', + description: + 'If the call resulted in exceptions, this field contains the exceptions in a human readable format. ', + name: 'thrift.exceptions', + }, + 'tls.client.x509.version': { + category: 'tls', + description: 'Version of x509 format.', + example: 3, + name: 'tls.client.x509.version', + type: 'keyword', + }, + 'tls.client.x509.version_number': { + category: 'tls', + description: 'Version of x509 format.', + example: 3, + name: 'tls.client.x509.version_number', + type: 'keyword', + }, + 'tls.client.x509.serial_number': { + category: 'tls', + description: + 'Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. ', + example: '55FBB9C7DEBF09809D12CCAA', + name: 'tls.client.x509.serial_number', + type: 'keyword', + }, + 'tls.client.x509.issuer.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of issuing certificate authority.', + example: 'C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA', + name: 'tls.client.x509.issuer.distinguished_name', + type: 'keyword', + }, + 'tls.client.x509.issuer.common_name': { + category: 'tls', + description: 'List of common name (CN) of issuing certificate authority.', + example: 'DigiCert SHA2 High Assurance Server CA', + name: 'tls.client.x509.issuer.common_name', + type: 'keyword', + }, + 'tls.client.x509.issuer.organizational_unit': { + category: 'tls', + description: 'List of organizational units (OU) of issuing certificate authority.', + example: 'www.digicert.com', + name: 'tls.client.x509.issuer.organizational_unit', + type: 'keyword', + }, + 'tls.client.x509.issuer.organization': { + category: 'tls', + description: 'List of organizations (O) of issuing certificate authority.', + example: 'DigiCert Inc', + name: 'tls.client.x509.issuer.organization', + type: 'keyword', + }, + 'tls.client.x509.issuer.locality': { + category: 'tls', + description: 'List of locality names (L)', + example: 'Mountain View', + name: 'tls.client.x509.issuer.locality', + type: 'keyword', + }, + 'tls.client.x509.issuer.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.client.x509.issuer.province', + type: 'keyword', + }, + 'tls.client.x509.issuer.state_or_province': { + category: 'tls', + description: 'List of state or province names (ST, S, or P)', + example: 'California', + name: 'tls.client.x509.issuer.state_or_province', + type: 'keyword', + }, + 'tls.client.x509.issuer.country': { + category: 'tls', + description: 'List of country (C) codes', + example: 'US', + name: 'tls.client.x509.issuer.country', + type: 'keyword', + }, + 'tls.client.x509.signature_algorithm': { + category: 'tls', + description: + 'Identifier for certificate signature algorithm. Recommend using names found in Go Lang Crypto library (See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353).', + example: 'SHA256-RSA', + name: 'tls.client.x509.signature_algorithm', + type: 'keyword', + }, + 'tls.client.x509.not_before': { + category: 'tls', + description: 'Time at which the certificate is first considered valid.', + example: '"2019-08-16T01:40:25.000Z"', + name: 'tls.client.x509.not_before', + type: 'date', + }, + 'tls.client.x509.not_after': { + category: 'tls', + description: 'Time at which the certificate is no longer considered valid.', + example: '"2020-07-16T03:15:39.000Z"', + name: 'tls.client.x509.not_after', + type: 'date', + }, + 'tls.client.x509.subject.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of the certificate subject entity.', + example: 'C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net', + name: 'tls.client.x509.subject.distinguished_name', + type: 'keyword', + }, + 'tls.client.x509.subject.common_name': { + category: 'tls', + description: 'List of common names (CN) of subject.', + example: 'r2.shared.global.fastly.net', + name: 'tls.client.x509.subject.common_name', + type: 'keyword', + }, + 'tls.client.x509.subject.organizational_unit': { + category: 'tls', + description: 'List of organizational units (OU) of subject.', + name: 'tls.client.x509.subject.organizational_unit', + type: 'keyword', + }, + 'tls.client.x509.subject.organization': { + category: 'tls', + description: 'List of organizations (O) of subject.', + example: 'Fastly, Inc.', + name: 'tls.client.x509.subject.organization', + type: 'keyword', + }, + 'tls.client.x509.subject.locality': { + category: 'tls', + description: 'List of locality names (L)', + example: 'San Francisco', + name: 'tls.client.x509.subject.locality', + type: 'keyword', + }, + 'tls.client.x509.subject.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.client.x509.subject.province', + type: 'keyword', + }, + 'tls.client.x509.subject.state_or_province': { + category: 'tls', + description: 'List of state or province names (ST, S, or P)', + example: 'California', + name: 'tls.client.x509.subject.state_or_province', + type: 'keyword', + }, + 'tls.client.x509.subject.country': { + category: 'tls', + description: 'List of country (C) code', + example: 'US', + name: 'tls.client.x509.subject.country', + type: 'keyword', + }, + 'tls.client.x509.public_key_algorithm': { + category: 'tls', + description: 'Algorithm used to generate the public key.', + example: 'RSA', + name: 'tls.client.x509.public_key_algorithm', + type: 'keyword', + }, + 'tls.client.x509.public_key_size': { + category: 'tls', + description: 'The size of the public key space in bits.', + example: 2048, + name: 'tls.client.x509.public_key_size', + type: 'long', + }, + 'tls.client.x509.alternative_names': { + category: 'tls', + description: + 'List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses.', + example: '*.elastic.co', + name: 'tls.client.x509.alternative_names', + type: 'keyword', + }, + 'tls.server.x509.version': { + category: 'tls', + description: 'Version of x509 format.', + example: 3, + name: 'tls.server.x509.version', + type: 'keyword', + }, + 'tls.server.x509.version_number': { + category: 'tls', + description: 'Version of x509 format.', + example: 3, + name: 'tls.server.x509.version_number', + type: 'keyword', + }, + 'tls.server.x509.serial_number': { + category: 'tls', + description: + 'Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. ', + example: '55FBB9C7DEBF09809D12CCAA', + name: 'tls.server.x509.serial_number', + type: 'keyword', + }, + 'tls.server.x509.issuer.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of issuing certificate authority.', + example: 'C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA', + name: 'tls.server.x509.issuer.distinguished_name', + type: 'keyword', + }, + 'tls.server.x509.issuer.common_name': { + category: 'tls', + description: 'List of common name (CN) of issuing certificate authority.', + example: 'DigiCert SHA2 High Assurance Server CA', + name: 'tls.server.x509.issuer.common_name', + type: 'keyword', + }, + 'tls.server.x509.issuer.organizational_unit': { + category: 'tls', + description: 'List of organizational units (OU) of issuing certificate authority.', + example: 'www.digicert.com', + name: 'tls.server.x509.issuer.organizational_unit', + type: 'keyword', + }, + 'tls.server.x509.issuer.organization': { + category: 'tls', + description: 'List of organizations (O) of issuing certificate authority.', + example: 'DigiCert Inc', + name: 'tls.server.x509.issuer.organization', + type: 'keyword', + }, + 'tls.server.x509.issuer.locality': { + category: 'tls', + description: 'List of locality names (L)', + example: 'Mountain View', + name: 'tls.server.x509.issuer.locality', + type: 'keyword', + }, + 'tls.server.x509.issuer.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.server.x509.issuer.province', + type: 'keyword', + }, + 'tls.server.x509.issuer.state_or_province': { + category: 'tls', + description: 'List of state or province names (ST, S, or P)', + example: 'California', + name: 'tls.server.x509.issuer.state_or_province', + type: 'keyword', + }, + 'tls.server.x509.issuer.country': { + category: 'tls', + description: 'List of country (C) codes', + example: 'US', + name: 'tls.server.x509.issuer.country', + type: 'keyword', + }, + 'tls.server.x509.signature_algorithm': { + category: 'tls', + description: + 'Identifier for certificate signature algorithm. Recommend using names found in Go Lang Crypto library (See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353).', + example: 'SHA256-RSA', + name: 'tls.server.x509.signature_algorithm', + type: 'keyword', + }, + 'tls.server.x509.not_before': { + category: 'tls', + description: 'Time at which the certificate is first considered valid.', + example: '"2019-08-16T01:40:25.000Z"', + name: 'tls.server.x509.not_before', + type: 'date', + }, + 'tls.server.x509.not_after': { + category: 'tls', + description: 'Time at which the certificate is no longer considered valid.', + example: '"2020-07-16T03:15:39.000Z"', + name: 'tls.server.x509.not_after', + type: 'date', + }, + 'tls.server.x509.subject.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of the certificate subject entity.', + example: 'C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net', + name: 'tls.server.x509.subject.distinguished_name', + type: 'keyword', + }, + 'tls.server.x509.subject.common_name': { + category: 'tls', + description: 'List of common names (CN) of subject.', + example: 'r2.shared.global.fastly.net', + name: 'tls.server.x509.subject.common_name', + type: 'keyword', + }, + 'tls.server.x509.subject.organizational_unit': { + category: 'tls', + description: 'List of organizational units (OU) of subject.', + name: 'tls.server.x509.subject.organizational_unit', + type: 'keyword', + }, + 'tls.server.x509.subject.organization': { + category: 'tls', + description: 'List of organizations (O) of subject.', + example: 'Fastly, Inc.', + name: 'tls.server.x509.subject.organization', + type: 'keyword', + }, + 'tls.server.x509.subject.locality': { + category: 'tls', + description: 'List of locality names (L)', + example: 'San Francisco', + name: 'tls.server.x509.subject.locality', + type: 'keyword', + }, + 'tls.server.x509.subject.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.server.x509.subject.province', + type: 'keyword', + }, + 'tls.server.x509.subject.state_or_province': { + category: 'tls', + description: 'List of state or province names (ST, S, or P)', + example: 'California', + name: 'tls.server.x509.subject.state_or_province', + type: 'keyword', + }, + 'tls.server.x509.subject.country': { + category: 'tls', + description: 'List of country (C) code', + example: 'US', + name: 'tls.server.x509.subject.country', + type: 'keyword', + }, + 'tls.server.x509.public_key_algorithm': { + category: 'tls', + description: 'Algorithm used to generate the public key.', + example: 'RSA', + name: 'tls.server.x509.public_key_algorithm', + type: 'keyword', + }, + 'tls.server.x509.public_key_size': { + category: 'tls', + description: 'The size of the public key space in bits.', + example: 2048, + name: 'tls.server.x509.public_key_size', + type: 'long', + }, + 'tls.server.x509.alternative_names': { + category: 'tls', + description: + 'List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses.', + example: '*.elastic.co', + name: 'tls.server.x509.alternative_names', + type: 'keyword', + }, + 'tls.detailed.version': { + category: 'tls', + description: 'The version of the TLS protocol used. ', + example: 'TLS 1.3', + name: 'tls.detailed.version', + type: 'keyword', + }, + 'tls.detailed.resumption_method': { + category: 'tls', + description: + 'If the session has been resumed, the underlying method used. One of "id" for TLS session ID or "ticket" for TLS ticket extension. ', + name: 'tls.detailed.resumption_method', + type: 'keyword', + }, + 'tls.detailed.client_certificate_requested': { + category: 'tls', + description: + 'Whether the server has requested the client to authenticate itself using a client certificate. ', + name: 'tls.detailed.client_certificate_requested', + type: 'boolean', + }, + 'tls.detailed.client_hello.version': { + category: 'tls', + description: + 'The version of the TLS protocol by which the client wishes to communicate during this session. ', + name: 'tls.detailed.client_hello.version', + type: 'keyword', + }, + 'tls.detailed.client_hello.session_id': { + category: 'tls', + description: + 'Unique number to identify the session for the corresponding connection with the client. ', + name: 'tls.detailed.client_hello.session_id', + type: 'keyword', + }, + 'tls.detailed.client_hello.supported_compression_methods': { + category: 'tls', + description: + 'The list of compression methods the client supports. See https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml ', + name: 'tls.detailed.client_hello.supported_compression_methods', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.server_name_indication': { + category: 'tls', + description: 'List of hostnames', + name: 'tls.detailed.client_hello.extensions.server_name_indication', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.application_layer_protocol_negotiation': { + category: 'tls', + description: 'List of application-layer protocols the client is willing to use. ', + name: 'tls.detailed.client_hello.extensions.application_layer_protocol_negotiation', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.session_ticket': { + category: 'tls', + description: + 'Length of the session ticket, if provided, or an empty string to advertise support for tickets. ', + name: 'tls.detailed.client_hello.extensions.session_ticket', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.supported_versions': { + category: 'tls', + description: 'List of TLS versions that the client is willing to use. ', + name: 'tls.detailed.client_hello.extensions.supported_versions', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.supported_groups': { + category: 'tls', + description: 'List of Elliptic Curve Cryptography (ECC) curve groups supported by the client. ', + name: 'tls.detailed.client_hello.extensions.supported_groups', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.signature_algorithms': { + category: 'tls', + description: 'List of signature algorithms that may be use in digital signatures. ', + name: 'tls.detailed.client_hello.extensions.signature_algorithms', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions.ec_points_formats': { + category: 'tls', + description: + 'List of Elliptic Curve (EC) point formats. Indicates the set of point formats that the client can parse. ', + name: 'tls.detailed.client_hello.extensions.ec_points_formats', + type: 'keyword', + }, + 'tls.detailed.client_hello.extensions._unparsed_': { + category: 'tls', + description: 'List of extensions that were left unparsed by Packetbeat. ', + name: 'tls.detailed.client_hello.extensions._unparsed_', + type: 'keyword', + }, + 'tls.detailed.server_hello.version': { + category: 'tls', + description: + 'The version of the TLS protocol that is used for this session. It is the highest version supported by the server not exceeding the version requested in the client hello. ', + name: 'tls.detailed.server_hello.version', + type: 'keyword', + }, + 'tls.detailed.server_hello.selected_compression_method': { + category: 'tls', + description: + 'The compression method selected by the server from the list provided in the client hello. ', + name: 'tls.detailed.server_hello.selected_compression_method', + type: 'keyword', + }, + 'tls.detailed.server_hello.session_id': { + category: 'tls', + description: + 'Unique number to identify the session for the corresponding connection with the client. ', + name: 'tls.detailed.server_hello.session_id', + type: 'keyword', + }, + 'tls.detailed.server_hello.extensions.application_layer_protocol_negotiation': { + category: 'tls', + description: 'Negotiated application layer protocol', + name: 'tls.detailed.server_hello.extensions.application_layer_protocol_negotiation', + type: 'keyword', + }, + 'tls.detailed.server_hello.extensions.session_ticket': { + category: 'tls', + description: + 'Used to announce that a session ticket will be provided by the server. Always an empty string. ', + name: 'tls.detailed.server_hello.extensions.session_ticket', + type: 'keyword', + }, + 'tls.detailed.server_hello.extensions.supported_versions': { + category: 'tls', + description: 'Negotiated TLS version to be used. ', + name: 'tls.detailed.server_hello.extensions.supported_versions', + type: 'keyword', + }, + 'tls.detailed.server_hello.extensions.ec_points_formats': { + category: 'tls', + description: + 'List of Elliptic Curve (EC) point formats. Indicates the set of point formats that the server can parse. ', + name: 'tls.detailed.server_hello.extensions.ec_points_formats', + type: 'keyword', + }, + 'tls.detailed.server_hello.extensions._unparsed_': { + category: 'tls', + description: 'List of extensions that were left unparsed by Packetbeat. ', + name: 'tls.detailed.server_hello.extensions._unparsed_', + type: 'keyword', + }, + 'tls.detailed.client_certificate.version': { + category: 'tls', + description: 'X509 format version.', + name: 'tls.detailed.client_certificate.version', + type: 'long', + }, + 'tls.detailed.client_certificate.version_number': { + category: 'tls', + description: 'Version of x509 format.', + example: 3, + name: 'tls.detailed.client_certificate.version_number', + type: 'keyword', + }, + 'tls.detailed.client_certificate.serial_number': { + category: 'tls', + description: "The certificate's serial number.", + name: 'tls.detailed.client_certificate.serial_number', + type: 'keyword', + }, + 'tls.detailed.client_certificate.not_before': { + category: 'tls', + description: 'Date before which the certificate is not valid.', + name: 'tls.detailed.client_certificate.not_before', + type: 'date', + }, + 'tls.detailed.client_certificate.not_after': { + category: 'tls', + description: 'Date after which the certificate expires.', + name: 'tls.detailed.client_certificate.not_after', + type: 'date', + }, + 'tls.detailed.client_certificate.public_key_algorithm': { + category: 'tls', + description: "The algorithm used for this certificate's public key. One of RSA, DSA or ECDSA. ", + name: 'tls.detailed.client_certificate.public_key_algorithm', + type: 'keyword', + }, + 'tls.detailed.client_certificate.public_key_size': { + category: 'tls', + description: 'Size of the public key.', + name: 'tls.detailed.client_certificate.public_key_size', + type: 'long', + }, + 'tls.detailed.client_certificate.signature_algorithm': { + category: 'tls', + description: "The algorithm used for the certificate's signature. ", + name: 'tls.detailed.client_certificate.signature_algorithm', + type: 'keyword', + }, + 'tls.detailed.client_certificate.alternative_names': { + category: 'tls', + description: 'Subject Alternative Names for this certificate.', + name: 'tls.detailed.client_certificate.alternative_names', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.country': { + category: 'tls', + description: 'Country code.', + name: 'tls.detailed.client_certificate.subject.country', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.organization': { + category: 'tls', + description: 'Organization name.', + name: 'tls.detailed.client_certificate.subject.organization', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.organizational_unit': { + category: 'tls', + description: 'Unit within organization.', + name: 'tls.detailed.client_certificate.subject.organizational_unit', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.detailed.client_certificate.subject.province', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.common_name': { + category: 'tls', + description: 'Name or host name identified by the certificate.', + name: 'tls.detailed.client_certificate.subject.common_name', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.locality': { + category: 'tls', + description: 'Locality.', + name: 'tls.detailed.client_certificate.subject.locality', + type: 'keyword', + }, + 'tls.detailed.client_certificate.subject.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of the certificate subject entity.', + example: 'C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net', + name: 'tls.detailed.client_certificate.subject.distinguished_name', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.country': { + category: 'tls', + description: 'Country code.', + name: 'tls.detailed.client_certificate.issuer.country', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.organization': { + category: 'tls', + description: 'Organization name.', + name: 'tls.detailed.client_certificate.issuer.organization', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.organizational_unit': { + category: 'tls', + description: 'Unit within organization.', + name: 'tls.detailed.client_certificate.issuer.organizational_unit', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.detailed.client_certificate.issuer.province', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.common_name': { + category: 'tls', + description: 'Name or host name identified by the certificate.', + name: 'tls.detailed.client_certificate.issuer.common_name', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.locality': { + category: 'tls', + description: 'Locality.', + name: 'tls.detailed.client_certificate.issuer.locality', + type: 'keyword', + }, + 'tls.detailed.client_certificate.issuer.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of the certificate issuer entity.', + example: 'C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net', + name: 'tls.detailed.client_certificate.issuer.distinguished_name', + type: 'keyword', + }, + 'tls.detailed.server_certificate.version': { + category: 'tls', + description: 'X509 format version.', + name: 'tls.detailed.server_certificate.version', + type: 'long', + }, + 'tls.detailed.server_certificate.version_number': { + category: 'tls', + description: 'Version of x509 format.', + example: 3, + name: 'tls.detailed.server_certificate.version_number', + type: 'keyword', + }, + 'tls.detailed.server_certificate.serial_number': { + category: 'tls', + description: "The certificate's serial number.", + name: 'tls.detailed.server_certificate.serial_number', + type: 'keyword', + }, + 'tls.detailed.server_certificate.not_before': { + category: 'tls', + description: 'Date before which the certificate is not valid.', + name: 'tls.detailed.server_certificate.not_before', + type: 'date', + }, + 'tls.detailed.server_certificate.not_after': { + category: 'tls', + description: 'Date after which the certificate expires.', + name: 'tls.detailed.server_certificate.not_after', + type: 'date', + }, + 'tls.detailed.server_certificate.public_key_algorithm': { + category: 'tls', + description: "The algorithm used for this certificate's public key. One of RSA, DSA or ECDSA. ", + name: 'tls.detailed.server_certificate.public_key_algorithm', + type: 'keyword', + }, + 'tls.detailed.server_certificate.public_key_size': { + category: 'tls', + description: 'Size of the public key.', + name: 'tls.detailed.server_certificate.public_key_size', + type: 'long', + }, + 'tls.detailed.server_certificate.signature_algorithm': { + category: 'tls', + description: "The algorithm used for the certificate's signature. ", + name: 'tls.detailed.server_certificate.signature_algorithm', + type: 'keyword', + }, + 'tls.detailed.server_certificate.alternative_names': { + category: 'tls', + description: 'Subject Alternative Names for this certificate.', + name: 'tls.detailed.server_certificate.alternative_names', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.country': { + category: 'tls', + description: 'Country code.', + name: 'tls.detailed.server_certificate.subject.country', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.organization': { + category: 'tls', + description: 'Organization name.', + name: 'tls.detailed.server_certificate.subject.organization', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.organizational_unit': { + category: 'tls', + description: 'Unit within organization.', + name: 'tls.detailed.server_certificate.subject.organizational_unit', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.detailed.server_certificate.subject.province', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.state_or_province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.detailed.server_certificate.subject.state_or_province', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.common_name': { + category: 'tls', + description: 'Name or host name identified by the certificate.', + name: 'tls.detailed.server_certificate.subject.common_name', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.locality': { + category: 'tls', + description: 'Locality.', + name: 'tls.detailed.server_certificate.subject.locality', + type: 'keyword', + }, + 'tls.detailed.server_certificate.subject.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of the certificate subject entity.', + example: 'C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net', + name: 'tls.detailed.server_certificate.subject.distinguished_name', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.country': { + category: 'tls', + description: 'Country code.', + name: 'tls.detailed.server_certificate.issuer.country', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.organization': { + category: 'tls', + description: 'Organization name.', + name: 'tls.detailed.server_certificate.issuer.organization', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.organizational_unit': { + category: 'tls', + description: 'Unit within organization.', + name: 'tls.detailed.server_certificate.issuer.organizational_unit', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.detailed.server_certificate.issuer.province', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.state_or_province': { + category: 'tls', + description: 'Province or region within country.', + name: 'tls.detailed.server_certificate.issuer.state_or_province', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.common_name': { + category: 'tls', + description: 'Name or host name identified by the certificate.', + name: 'tls.detailed.server_certificate.issuer.common_name', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.locality': { + category: 'tls', + description: 'Locality.', + name: 'tls.detailed.server_certificate.issuer.locality', + type: 'keyword', + }, + 'tls.detailed.server_certificate.issuer.distinguished_name': { + category: 'tls', + description: 'Distinguished name (DN) of the certificate issuer entity.', + example: 'C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net', + name: 'tls.detailed.server_certificate.issuer.distinguished_name', + type: 'keyword', + }, + 'tls.detailed.server_certificate_chain': { + category: 'tls', + description: 'Chain of trust for the server certificate.', + name: 'tls.detailed.server_certificate_chain', + type: 'array', + }, + 'tls.detailed.client_certificate_chain': { + category: 'tls', + description: 'Chain of trust for the client certificate.', + name: 'tls.detailed.client_certificate_chain', + type: 'array', + }, + 'tls.detailed.alert_types': { + category: 'tls', + description: 'An array containing the TLS alert type for every alert received. ', + name: 'tls.detailed.alert_types', + type: 'keyword', + }, + 'tls.handshake_completed': { + category: 'tls', + name: 'tls.handshake_completed', + type: 'alias', + }, + 'tls.client_hello.supported_ciphers': { + category: 'tls', + name: 'tls.client_hello.supported_ciphers', + type: 'alias', + }, + 'tls.server_hello.selected_cipher': { + category: 'tls', + name: 'tls.server_hello.selected_cipher', + type: 'alias', + }, + 'tls.fingerprints.ja3': { + category: 'tls', + name: 'tls.fingerprints.ja3', + type: 'alias', + }, + 'tls.resumption_method': { + category: 'tls', + name: 'tls.resumption_method', + type: 'alias', + }, + 'tls.client_certificate_requested': { + category: 'tls', + name: 'tls.client_certificate_requested', + type: 'alias', + }, + 'tls.client_hello.version': { + category: 'tls', + name: 'tls.client_hello.version', + type: 'alias', + }, + 'tls.client_hello.session_id': { + category: 'tls', + name: 'tls.client_hello.session_id', + type: 'alias', + }, + 'tls.client_hello.supported_compression_methods': { + category: 'tls', + name: 'tls.client_hello.supported_compression_methods', + type: 'alias', + }, + 'tls.client_hello.extensions.server_name_indication': { + category: 'tls', + name: 'tls.client_hello.extensions.server_name_indication', + type: 'alias', + }, + 'tls.client_hello.extensions.application_layer_protocol_negotiation': { + category: 'tls', + name: 'tls.client_hello.extensions.application_layer_protocol_negotiation', + type: 'alias', + }, + 'tls.client_hello.extensions.session_ticket': { + category: 'tls', + name: 'tls.client_hello.extensions.session_ticket', + type: 'alias', + }, + 'tls.client_hello.extensions.supported_versions': { + category: 'tls', + name: 'tls.client_hello.extensions.supported_versions', + type: 'alias', + }, + 'tls.client_hello.extensions.supported_groups': { + category: 'tls', + name: 'tls.client_hello.extensions.supported_groups', + type: 'alias', + }, + 'tls.client_hello.extensions.signature_algorithms': { + category: 'tls', + name: 'tls.client_hello.extensions.signature_algorithms', + type: 'alias', + }, + 'tls.client_hello.extensions.ec_points_formats': { + category: 'tls', + name: 'tls.client_hello.extensions.ec_points_formats', + type: 'alias', + }, + 'tls.client_hello.extensions._unparsed_': { + category: 'tls', + name: 'tls.client_hello.extensions._unparsed_', + type: 'alias', + }, + 'tls.server_hello.version': { + category: 'tls', + name: 'tls.server_hello.version', + type: 'alias', + }, + 'tls.server_hello.selected_compression_method': { + category: 'tls', + name: 'tls.server_hello.selected_compression_method', + type: 'alias', + }, + 'tls.server_hello.session_id': { + category: 'tls', + name: 'tls.server_hello.session_id', + type: 'alias', + }, + 'tls.server_hello.extensions.application_layer_protocol_negotiation': { + category: 'tls', + name: 'tls.server_hello.extensions.application_layer_protocol_negotiation', + type: 'alias', + }, + 'tls.server_hello.extensions.session_ticket': { + category: 'tls', + name: 'tls.server_hello.extensions.session_ticket', + type: 'alias', + }, + 'tls.server_hello.extensions.supported_versions': { + category: 'tls', + name: 'tls.server_hello.extensions.supported_versions', + type: 'alias', + }, + 'tls.server_hello.extensions.ec_points_formats': { + category: 'tls', + name: 'tls.server_hello.extensions.ec_points_formats', + type: 'alias', + }, + 'tls.server_hello.extensions._unparsed_': { + category: 'tls', + name: 'tls.server_hello.extensions._unparsed_', + type: 'alias', + }, + 'tls.client_certificate.version': { + category: 'tls', + name: 'tls.client_certificate.version', + type: 'alias', + }, + 'tls.client_certificate.serial_number': { + category: 'tls', + name: 'tls.client_certificate.serial_number', + type: 'alias', + }, + 'tls.client_certificate.not_before': { + category: 'tls', + name: 'tls.client_certificate.not_before', + type: 'alias', + }, + 'tls.client_certificate.not_after': { + category: 'tls', + name: 'tls.client_certificate.not_after', + type: 'alias', + }, + 'tls.client_certificate.public_key_algorithm': { + category: 'tls', + name: 'tls.client_certificate.public_key_algorithm', + type: 'alias', + }, + 'tls.client_certificate.public_key_size': { + category: 'tls', + name: 'tls.client_certificate.public_key_size', + type: 'alias', + }, + 'tls.client_certificate.signature_algorithm': { + category: 'tls', + name: 'tls.client_certificate.signature_algorithm', + type: 'alias', + }, + 'tls.client_certificate.alternative_names': { + category: 'tls', + name: 'tls.client_certificate.alternative_names', + type: 'alias', + }, + 'tls.client_certificate.subject.country': { + category: 'tls', + name: 'tls.client_certificate.subject.country', + type: 'alias', + }, + 'tls.client_certificate.subject.organization': { + category: 'tls', + name: 'tls.client_certificate.subject.organization', + type: 'alias', + }, + 'tls.client_certificate.subject.organizational_unit': { + category: 'tls', + name: 'tls.client_certificate.subject.organizational_unit', + type: 'alias', + }, + 'tls.client_certificate.subject.province': { + category: 'tls', + name: 'tls.client_certificate.subject.province', + type: 'alias', + }, + 'tls.client_certificate.subject.common_name': { + category: 'tls', + name: 'tls.client_certificate.subject.common_name', + type: 'alias', + }, + 'tls.client_certificate.subject.locality': { + category: 'tls', + name: 'tls.client_certificate.subject.locality', + type: 'alias', + }, + 'tls.client_certificate.issuer.country': { + category: 'tls', + name: 'tls.client_certificate.issuer.country', + type: 'alias', + }, + 'tls.client_certificate.issuer.organization': { + category: 'tls', + name: 'tls.client_certificate.issuer.organization', + type: 'alias', + }, + 'tls.client_certificate.issuer.organizational_unit': { + category: 'tls', + name: 'tls.client_certificate.issuer.organizational_unit', + type: 'alias', + }, + 'tls.client_certificate.issuer.province': { + category: 'tls', + name: 'tls.client_certificate.issuer.province', + type: 'alias', + }, + 'tls.client_certificate.issuer.common_name': { + category: 'tls', + name: 'tls.client_certificate.issuer.common_name', + type: 'alias', + }, + 'tls.client_certificate.issuer.locality': { + category: 'tls', + name: 'tls.client_certificate.issuer.locality', + type: 'alias', + }, + 'tls.server_certificate.version': { + category: 'tls', + name: 'tls.server_certificate.version', + type: 'alias', + }, + 'tls.server_certificate.serial_number': { + category: 'tls', + name: 'tls.server_certificate.serial_number', + type: 'alias', + }, + 'tls.server_certificate.not_before': { + category: 'tls', + name: 'tls.server_certificate.not_before', + type: 'alias', + }, + 'tls.server_certificate.not_after': { + category: 'tls', + name: 'tls.server_certificate.not_after', + type: 'alias', + }, + 'tls.server_certificate.public_key_algorithm': { + category: 'tls', + name: 'tls.server_certificate.public_key_algorithm', + type: 'alias', + }, + 'tls.server_certificate.public_key_size': { + category: 'tls', + name: 'tls.server_certificate.public_key_size', + type: 'alias', + }, + 'tls.server_certificate.signature_algorithm': { + category: 'tls', + name: 'tls.server_certificate.signature_algorithm', + type: 'alias', + }, + 'tls.server_certificate.alternative_names': { + category: 'tls', + name: 'tls.server_certificate.alternative_names', + type: 'alias', + }, + 'tls.server_certificate.subject.country': { + category: 'tls', + name: 'tls.server_certificate.subject.country', + type: 'alias', + }, + 'tls.server_certificate.subject.organization': { + category: 'tls', + name: 'tls.server_certificate.subject.organization', + type: 'alias', + }, + 'tls.server_certificate.subject.organizational_unit': { + category: 'tls', + name: 'tls.server_certificate.subject.organizational_unit', + type: 'alias', + }, + 'tls.server_certificate.subject.province': { + category: 'tls', + name: 'tls.server_certificate.subject.province', + type: 'alias', + }, + 'tls.server_certificate.subject.common_name': { + category: 'tls', + name: 'tls.server_certificate.subject.common_name', + type: 'alias', + }, + 'tls.server_certificate.subject.locality': { + category: 'tls', + name: 'tls.server_certificate.subject.locality', + type: 'alias', + }, + 'tls.server_certificate.issuer.country': { + category: 'tls', + name: 'tls.server_certificate.issuer.country', + type: 'alias', + }, + 'tls.server_certificate.issuer.organization': { + category: 'tls', + name: 'tls.server_certificate.issuer.organization', + type: 'alias', + }, + 'tls.server_certificate.issuer.organizational_unit': { + category: 'tls', + name: 'tls.server_certificate.issuer.organizational_unit', + type: 'alias', + }, + 'tls.server_certificate.issuer.province': { + category: 'tls', + name: 'tls.server_certificate.issuer.province', + type: 'alias', + }, + 'tls.server_certificate.issuer.common_name': { + category: 'tls', + name: 'tls.server_certificate.issuer.common_name', + type: 'alias', + }, + 'tls.server_certificate.issuer.locality': { + category: 'tls', + name: 'tls.server_certificate.issuer.locality', + type: 'alias', + }, + 'tls.alert_types': { + category: 'tls', + name: 'tls.alert_types', + type: 'alias', + }, + 'winlog.api': { + category: 'winlog', + description: + 'The event log API type used to read the record. The possible values are "wineventlog" for the Windows Event Log API or "eventlogging" for the Event Logging API. The Event Logging API was designed for Windows Server 2003 or Windows 2000 operating systems. In Windows Vista, the event logging infrastructure was redesigned. On Windows Vista or later operating systems, the Windows Event Log API is used. Winlogbeat automatically detects which API to use for reading event logs. ', + name: 'winlog.api', + }, + 'winlog.activity_id': { + category: 'winlog', + description: + 'A globally unique identifier that identifies the current activity. The events that are published with this identifier are part of the same activity. ', + name: 'winlog.activity_id', + type: 'keyword', + }, + 'winlog.computer_name': { + category: 'winlog', + description: + 'The name of the computer that generated the record. When using Windows event forwarding, this name can differ from `agent.hostname`. ', + name: 'winlog.computer_name', + type: 'keyword', + }, + 'winlog.event_data': { + category: 'winlog', + description: + 'The event-specific data. This field is mutually exclusive with `user_data`. If you are capturing event data on versions prior to Windows Vista, the parameters in `event_data` are named `param1`, `param2`, and so on, because event log parameters are unnamed in earlier versions of Windows. ', + name: 'winlog.event_data', + type: 'object', + }, + 'winlog.event_data.AuthenticationPackageName': { + category: 'winlog', + name: 'winlog.event_data.AuthenticationPackageName', + type: 'keyword', + }, + 'winlog.event_data.Binary': { + category: 'winlog', + name: 'winlog.event_data.Binary', + type: 'keyword', + }, + 'winlog.event_data.BitlockerUserInputTime': { + category: 'winlog', + name: 'winlog.event_data.BitlockerUserInputTime', + type: 'keyword', + }, + 'winlog.event_data.BootMode': { + category: 'winlog', + name: 'winlog.event_data.BootMode', + type: 'keyword', + }, + 'winlog.event_data.BootType': { + category: 'winlog', + name: 'winlog.event_data.BootType', + type: 'keyword', + }, + 'winlog.event_data.BuildVersion': { + category: 'winlog', + name: 'winlog.event_data.BuildVersion', + type: 'keyword', + }, + 'winlog.event_data.Company': { + category: 'winlog', + name: 'winlog.event_data.Company', + type: 'keyword', + }, + 'winlog.event_data.CorruptionActionState': { + category: 'winlog', + name: 'winlog.event_data.CorruptionActionState', + type: 'keyword', + }, + 'winlog.event_data.CreationUtcTime': { + category: 'winlog', + name: 'winlog.event_data.CreationUtcTime', + type: 'keyword', + }, + 'winlog.event_data.Description': { + category: 'winlog', + name: 'winlog.event_data.Description', + type: 'keyword', + }, + 'winlog.event_data.Detail': { + category: 'winlog', + name: 'winlog.event_data.Detail', + type: 'keyword', + }, + 'winlog.event_data.DeviceName': { + category: 'winlog', + name: 'winlog.event_data.DeviceName', + type: 'keyword', + }, + 'winlog.event_data.DeviceNameLength': { + category: 'winlog', + name: 'winlog.event_data.DeviceNameLength', + type: 'keyword', + }, + 'winlog.event_data.DeviceTime': { + category: 'winlog', + name: 'winlog.event_data.DeviceTime', + type: 'keyword', + }, + 'winlog.event_data.DeviceVersionMajor': { + category: 'winlog', + name: 'winlog.event_data.DeviceVersionMajor', + type: 'keyword', + }, + 'winlog.event_data.DeviceVersionMinor': { + category: 'winlog', + name: 'winlog.event_data.DeviceVersionMinor', + type: 'keyword', + }, + 'winlog.event_data.DriveName': { + category: 'winlog', + name: 'winlog.event_data.DriveName', + type: 'keyword', + }, + 'winlog.event_data.DriverName': { + category: 'winlog', + name: 'winlog.event_data.DriverName', + type: 'keyword', + }, + 'winlog.event_data.DriverNameLength': { + category: 'winlog', + name: 'winlog.event_data.DriverNameLength', + type: 'keyword', + }, + 'winlog.event_data.DwordVal': { + category: 'winlog', + name: 'winlog.event_data.DwordVal', + type: 'keyword', + }, + 'winlog.event_data.EntryCount': { + category: 'winlog', + name: 'winlog.event_data.EntryCount', + type: 'keyword', + }, + 'winlog.event_data.ExtraInfo': { + category: 'winlog', + name: 'winlog.event_data.ExtraInfo', + type: 'keyword', + }, + 'winlog.event_data.FailureName': { + category: 'winlog', + name: 'winlog.event_data.FailureName', + type: 'keyword', + }, + 'winlog.event_data.FailureNameLength': { + category: 'winlog', + name: 'winlog.event_data.FailureNameLength', + type: 'keyword', + }, + 'winlog.event_data.FileVersion': { + category: 'winlog', + name: 'winlog.event_data.FileVersion', + type: 'keyword', + }, + 'winlog.event_data.FinalStatus': { + category: 'winlog', + name: 'winlog.event_data.FinalStatus', + type: 'keyword', + }, + 'winlog.event_data.Group': { + category: 'winlog', + name: 'winlog.event_data.Group', + type: 'keyword', + }, + 'winlog.event_data.IdleImplementation': { + category: 'winlog', + name: 'winlog.event_data.IdleImplementation', + type: 'keyword', + }, + 'winlog.event_data.IdleStateCount': { + category: 'winlog', + name: 'winlog.event_data.IdleStateCount', + type: 'keyword', + }, + 'winlog.event_data.ImpersonationLevel': { + category: 'winlog', + name: 'winlog.event_data.ImpersonationLevel', + type: 'keyword', + }, + 'winlog.event_data.IntegrityLevel': { + category: 'winlog', + name: 'winlog.event_data.IntegrityLevel', + type: 'keyword', + }, + 'winlog.event_data.IpAddress': { + category: 'winlog', + name: 'winlog.event_data.IpAddress', + type: 'keyword', + }, + 'winlog.event_data.IpPort': { + category: 'winlog', + name: 'winlog.event_data.IpPort', + type: 'keyword', + }, + 'winlog.event_data.KeyLength': { + category: 'winlog', + name: 'winlog.event_data.KeyLength', + type: 'keyword', + }, + 'winlog.event_data.LastBootGood': { + category: 'winlog', + name: 'winlog.event_data.LastBootGood', + type: 'keyword', + }, + 'winlog.event_data.LastShutdownGood': { + category: 'winlog', + name: 'winlog.event_data.LastShutdownGood', + type: 'keyword', + }, + 'winlog.event_data.LmPackageName': { + category: 'winlog', + name: 'winlog.event_data.LmPackageName', + type: 'keyword', + }, + 'winlog.event_data.LogonGuid': { + category: 'winlog', + name: 'winlog.event_data.LogonGuid', + type: 'keyword', + }, + 'winlog.event_data.LogonId': { + category: 'winlog', + name: 'winlog.event_data.LogonId', + type: 'keyword', + }, + 'winlog.event_data.LogonProcessName': { + category: 'winlog', + name: 'winlog.event_data.LogonProcessName', + type: 'keyword', + }, + 'winlog.event_data.LogonType': { + category: 'winlog', + name: 'winlog.event_data.LogonType', + type: 'keyword', + }, + 'winlog.event_data.MajorVersion': { + category: 'winlog', + name: 'winlog.event_data.MajorVersion', + type: 'keyword', + }, + 'winlog.event_data.MaximumPerformancePercent': { + category: 'winlog', + name: 'winlog.event_data.MaximumPerformancePercent', + type: 'keyword', + }, + 'winlog.event_data.MemberName': { + category: 'winlog', + name: 'winlog.event_data.MemberName', + type: 'keyword', + }, + 'winlog.event_data.MemberSid': { + category: 'winlog', + name: 'winlog.event_data.MemberSid', + type: 'keyword', + }, + 'winlog.event_data.MinimumPerformancePercent': { + category: 'winlog', + name: 'winlog.event_data.MinimumPerformancePercent', + type: 'keyword', + }, + 'winlog.event_data.MinimumThrottlePercent': { + category: 'winlog', + name: 'winlog.event_data.MinimumThrottlePercent', + type: 'keyword', + }, + 'winlog.event_data.MinorVersion': { + category: 'winlog', + name: 'winlog.event_data.MinorVersion', + type: 'keyword', + }, + 'winlog.event_data.NewProcessId': { + category: 'winlog', + name: 'winlog.event_data.NewProcessId', + type: 'keyword', + }, + 'winlog.event_data.NewProcessName': { + category: 'winlog', + name: 'winlog.event_data.NewProcessName', + type: 'keyword', + }, + 'winlog.event_data.NewSchemeGuid': { + category: 'winlog', + name: 'winlog.event_data.NewSchemeGuid', + type: 'keyword', + }, + 'winlog.event_data.NewTime': { + category: 'winlog', + name: 'winlog.event_data.NewTime', + type: 'keyword', + }, + 'winlog.event_data.NominalFrequency': { + category: 'winlog', + name: 'winlog.event_data.NominalFrequency', + type: 'keyword', + }, + 'winlog.event_data.Number': { + category: 'winlog', + name: 'winlog.event_data.Number', + type: 'keyword', + }, + 'winlog.event_data.OldSchemeGuid': { + category: 'winlog', + name: 'winlog.event_data.OldSchemeGuid', + type: 'keyword', + }, + 'winlog.event_data.OldTime': { + category: 'winlog', + name: 'winlog.event_data.OldTime', + type: 'keyword', + }, + 'winlog.event_data.OriginalFileName': { + category: 'winlog', + name: 'winlog.event_data.OriginalFileName', + type: 'keyword', + }, + 'winlog.event_data.Path': { + category: 'winlog', + name: 'winlog.event_data.Path', + type: 'keyword', + }, + 'winlog.event_data.PerformanceImplementation': { + category: 'winlog', + name: 'winlog.event_data.PerformanceImplementation', + type: 'keyword', + }, + 'winlog.event_data.PreviousCreationUtcTime': { + category: 'winlog', + name: 'winlog.event_data.PreviousCreationUtcTime', + type: 'keyword', + }, + 'winlog.event_data.PreviousTime': { + category: 'winlog', + name: 'winlog.event_data.PreviousTime', + type: 'keyword', + }, + 'winlog.event_data.PrivilegeList': { + category: 'winlog', + name: 'winlog.event_data.PrivilegeList', + type: 'keyword', + }, + 'winlog.event_data.ProcessId': { + category: 'winlog', + name: 'winlog.event_data.ProcessId', + type: 'keyword', + }, + 'winlog.event_data.ProcessName': { + category: 'winlog', + name: 'winlog.event_data.ProcessName', + type: 'keyword', + }, + 'winlog.event_data.ProcessPath': { + category: 'winlog', + name: 'winlog.event_data.ProcessPath', + type: 'keyword', + }, + 'winlog.event_data.ProcessPid': { + category: 'winlog', + name: 'winlog.event_data.ProcessPid', + type: 'keyword', + }, + 'winlog.event_data.Product': { + category: 'winlog', + name: 'winlog.event_data.Product', + type: 'keyword', + }, + 'winlog.event_data.PuaCount': { + category: 'winlog', + name: 'winlog.event_data.PuaCount', + type: 'keyword', + }, + 'winlog.event_data.PuaPolicyId': { + category: 'winlog', + name: 'winlog.event_data.PuaPolicyId', + type: 'keyword', + }, + 'winlog.event_data.QfeVersion': { + category: 'winlog', + name: 'winlog.event_data.QfeVersion', + type: 'keyword', + }, + 'winlog.event_data.Reason': { + category: 'winlog', + name: 'winlog.event_data.Reason', + type: 'keyword', + }, + 'winlog.event_data.SchemaVersion': { + category: 'winlog', + name: 'winlog.event_data.SchemaVersion', + type: 'keyword', + }, + 'winlog.event_data.ScriptBlockText': { + category: 'winlog', + name: 'winlog.event_data.ScriptBlockText', + type: 'keyword', + }, + 'winlog.event_data.ServiceName': { + category: 'winlog', + name: 'winlog.event_data.ServiceName', + type: 'keyword', + }, + 'winlog.event_data.ServiceVersion': { + category: 'winlog', + name: 'winlog.event_data.ServiceVersion', + type: 'keyword', + }, + 'winlog.event_data.ShutdownActionType': { + category: 'winlog', + name: 'winlog.event_data.ShutdownActionType', + type: 'keyword', + }, + 'winlog.event_data.ShutdownEventCode': { + category: 'winlog', + name: 'winlog.event_data.ShutdownEventCode', + type: 'keyword', + }, + 'winlog.event_data.ShutdownReason': { + category: 'winlog', + name: 'winlog.event_data.ShutdownReason', + type: 'keyword', + }, + 'winlog.event_data.Signature': { + category: 'winlog', + name: 'winlog.event_data.Signature', + type: 'keyword', + }, + 'winlog.event_data.SignatureStatus': { + category: 'winlog', + name: 'winlog.event_data.SignatureStatus', + type: 'keyword', + }, + 'winlog.event_data.Signed': { + category: 'winlog', + name: 'winlog.event_data.Signed', + type: 'keyword', + }, + 'winlog.event_data.StartTime': { + category: 'winlog', + name: 'winlog.event_data.StartTime', + type: 'keyword', + }, + 'winlog.event_data.State': { + category: 'winlog', + name: 'winlog.event_data.State', + type: 'keyword', + }, + 'winlog.event_data.Status': { + category: 'winlog', + name: 'winlog.event_data.Status', + type: 'keyword', + }, + 'winlog.event_data.StopTime': { + category: 'winlog', + name: 'winlog.event_data.StopTime', + type: 'keyword', + }, + 'winlog.event_data.SubjectDomainName': { + category: 'winlog', + name: 'winlog.event_data.SubjectDomainName', + type: 'keyword', + }, + 'winlog.event_data.SubjectLogonId': { + category: 'winlog', + name: 'winlog.event_data.SubjectLogonId', + type: 'keyword', + }, + 'winlog.event_data.SubjectUserName': { + category: 'winlog', + name: 'winlog.event_data.SubjectUserName', + type: 'keyword', + }, + 'winlog.event_data.SubjectUserSid': { + category: 'winlog', + name: 'winlog.event_data.SubjectUserSid', + type: 'keyword', + }, + 'winlog.event_data.TSId': { + category: 'winlog', + name: 'winlog.event_data.TSId', + type: 'keyword', + }, + 'winlog.event_data.TargetDomainName': { + category: 'winlog', + name: 'winlog.event_data.TargetDomainName', + type: 'keyword', + }, + 'winlog.event_data.TargetInfo': { + category: 'winlog', + name: 'winlog.event_data.TargetInfo', + type: 'keyword', + }, + 'winlog.event_data.TargetLogonGuid': { + category: 'winlog', + name: 'winlog.event_data.TargetLogonGuid', + type: 'keyword', + }, + 'winlog.event_data.TargetLogonId': { + category: 'winlog', + name: 'winlog.event_data.TargetLogonId', + type: 'keyword', + }, + 'winlog.event_data.TargetServerName': { + category: 'winlog', + name: 'winlog.event_data.TargetServerName', + type: 'keyword', + }, + 'winlog.event_data.TargetUserName': { + category: 'winlog', + name: 'winlog.event_data.TargetUserName', + type: 'keyword', + }, + 'winlog.event_data.TargetUserSid': { + category: 'winlog', + name: 'winlog.event_data.TargetUserSid', + type: 'keyword', + }, + 'winlog.event_data.TerminalSessionId': { + category: 'winlog', + name: 'winlog.event_data.TerminalSessionId', + type: 'keyword', + }, + 'winlog.event_data.TokenElevationType': { + category: 'winlog', + name: 'winlog.event_data.TokenElevationType', + type: 'keyword', + }, + 'winlog.event_data.TransmittedServices': { + category: 'winlog', + name: 'winlog.event_data.TransmittedServices', + type: 'keyword', + }, + 'winlog.event_data.UserSid': { + category: 'winlog', + name: 'winlog.event_data.UserSid', + type: 'keyword', + }, + 'winlog.event_data.Version': { + category: 'winlog', + name: 'winlog.event_data.Version', + type: 'keyword', + }, + 'winlog.event_data.Workstation': { + category: 'winlog', + name: 'winlog.event_data.Workstation', + type: 'keyword', + }, + 'winlog.event_data.param1': { + category: 'winlog', + name: 'winlog.event_data.param1', + type: 'keyword', + }, + 'winlog.event_data.param2': { + category: 'winlog', + name: 'winlog.event_data.param2', + type: 'keyword', + }, + 'winlog.event_data.param3': { + category: 'winlog', + name: 'winlog.event_data.param3', + type: 'keyword', + }, + 'winlog.event_data.param4': { + category: 'winlog', + name: 'winlog.event_data.param4', + type: 'keyword', + }, + 'winlog.event_data.param5': { + category: 'winlog', + name: 'winlog.event_data.param5', + type: 'keyword', + }, + 'winlog.event_data.param6': { + category: 'winlog', + name: 'winlog.event_data.param6', + type: 'keyword', + }, + 'winlog.event_data.param7': { + category: 'winlog', + name: 'winlog.event_data.param7', + type: 'keyword', + }, + 'winlog.event_data.param8': { + category: 'winlog', + name: 'winlog.event_data.param8', + type: 'keyword', + }, + 'winlog.event_id': { + category: 'winlog', + description: 'The event identifier. The value is specific to the source of the event. ', + name: 'winlog.event_id', + type: 'keyword', + }, + 'winlog.keywords': { + category: 'winlog', + description: 'The keywords are used to classify an event. ', + name: 'winlog.keywords', + type: 'keyword', + }, + 'winlog.channel': { + category: 'winlog', + description: + 'The name of the channel from which this record was read. This value is one of the names from the `event_logs` collection in the configuration. ', + name: 'winlog.channel', + type: 'keyword', + }, + 'winlog.record_id': { + category: 'winlog', + description: + 'The record ID of the event log record. The first record written to an event log is record number 1, and other records are numbered sequentially. If the record number reaches the maximum value (2^32^ for the Event Logging API and 2^64^ for the Windows Event Log API), the next record number will be 0. ', + name: 'winlog.record_id', + type: 'keyword', + }, + 'winlog.related_activity_id': { + category: 'winlog', + description: + 'A globally unique identifier that identifies the activity to which control was transferred to. The related events would then have this identifier as their `activity_id` identifier. ', + name: 'winlog.related_activity_id', + type: 'keyword', + }, + 'winlog.opcode': { + category: 'winlog', + description: + 'The opcode defined in the event. Task and opcode are typically used to identify the location in the application from where the event was logged. ', + name: 'winlog.opcode', + type: 'keyword', + }, + 'winlog.provider_guid': { + category: 'winlog', + description: + 'A globally unique identifier that identifies the provider that logged the event. ', + name: 'winlog.provider_guid', + type: 'keyword', + }, + 'winlog.process.pid': { + category: 'winlog', + description: 'The process_id of the Client Server Runtime Process. ', + name: 'winlog.process.pid', + type: 'long', + }, + 'winlog.provider_name': { + category: 'winlog', + description: + 'The source of the event log record (the application or service that logged the record). ', + name: 'winlog.provider_name', + type: 'keyword', + }, + 'winlog.task': { + category: 'winlog', + description: + 'The task defined in the event. Task and opcode are typically used to identify the location in the application from where the event was logged. The category used by the Event Logging API (on pre Windows Vista operating systems) is written to this field. ', + name: 'winlog.task', + type: 'keyword', + }, + 'winlog.process.thread.id': { + category: 'winlog', + name: 'winlog.process.thread.id', + type: 'long', + }, + 'winlog.user_data': { + category: 'winlog', + description: 'The event specific data. This field is mutually exclusive with `event_data`. ', + name: 'winlog.user_data', + type: 'object', + }, + 'winlog.user.identifier': { + category: 'winlog', + description: + 'The Windows security identifier (SID) of the account associated with this event. If Winlogbeat cannot resolve the SID to a name, then the `user.name`, `user.domain`, and `user.type` fields will be omitted from the event. If you discover Winlogbeat not resolving SIDs, review the log for clues as to what the problem may be. ', + example: 'S-1-5-21-3541430928-2051711210-1391384369-1001', + name: 'winlog.user.identifier', + type: 'keyword', + }, + 'winlog.user.name': { + category: 'winlog', + description: 'Name of the user associated with this event. ', + name: 'winlog.user.name', + type: 'keyword', + }, + 'winlog.user.domain': { + category: 'winlog', + description: 'The domain that the account associated with this event is a member of. ', + name: 'winlog.user.domain', + type: 'keyword', + }, + 'winlog.user.type': { + category: 'winlog', + description: 'The type of account associated with this event. ', + name: 'winlog.user.type', + type: 'keyword', + }, + 'winlog.version': { + category: 'winlog', + description: "The version number of the event's definition.", + name: 'winlog.version', + type: 'long', + }, + activity_id: { + category: 'base', + name: 'activity_id', + type: 'alias', + }, + computer_name: { + category: 'base', + name: 'computer_name', + type: 'alias', + }, + event_id: { + category: 'base', + name: 'event_id', + type: 'alias', + }, + keywords: { + category: 'base', + name: 'keywords', + type: 'alias', + }, + log_name: { + category: 'base', + name: 'log_name', + type: 'alias', + }, + message_error: { + category: 'base', + name: 'message_error', + type: 'alias', + }, + record_number: { + category: 'base', + name: 'record_number', + type: 'alias', + }, + related_activity_id: { + category: 'base', + name: 'related_activity_id', + type: 'alias', + }, + opcode: { + category: 'base', + name: 'opcode', + type: 'alias', + }, + provider_guid: { + category: 'base', + name: 'provider_guid', + type: 'alias', + }, + process_id: { + category: 'base', + name: 'process_id', + type: 'alias', + }, + source_name: { + category: 'base', + name: 'source_name', + type: 'alias', + }, + task: { + category: 'base', + name: 'task', + type: 'alias', + }, + thread_id: { + category: 'base', + name: 'thread_id', + type: 'alias', + }, + 'user.identifier': { + category: 'user', + name: 'user.identifier', + type: 'alias', + }, + 'user.type': { + category: 'user', + name: 'user.type', + type: 'alias', + }, + version: { + category: 'base', + name: 'version', + type: 'alias', + }, + xml: { + category: 'base', + name: 'xml', + type: 'alias', + }, + 'powershell.id': { + category: 'powershell', + description: 'Shell Id.', + example: 'Microsoft Powershell', + name: 'powershell.id', + type: 'keyword', + }, + 'powershell.pipeline_id': { + category: 'powershell', + description: 'Pipeline id.', + example: '1', + name: 'powershell.pipeline_id', + type: 'keyword', + }, + 'powershell.runspace_id': { + category: 'powershell', + description: 'Runspace id.', + example: '4fa9074d-45ab-4e53-9195-e91981ac2bbb', + name: 'powershell.runspace_id', + type: 'keyword', + }, + 'powershell.sequence': { + category: 'powershell', + description: 'Sequence number of the powershell execution.', + example: 1, + name: 'powershell.sequence', + type: 'long', + }, + 'powershell.total': { + category: 'powershell', + description: 'Total number of messages in the sequence.', + example: 10, + name: 'powershell.total', + type: 'long', + }, + 'powershell.command.path': { + category: 'powershell', + description: 'Path of the executed command.', + example: 'C:\\Windows\\system32\\cmd.exe', + name: 'powershell.command.path', + type: 'keyword', + }, + 'powershell.command.name': { + category: 'powershell', + description: 'Name of the executed command.', + example: 'cmd.exe', + name: 'powershell.command.name', + type: 'keyword', + }, + 'powershell.command.type': { + category: 'powershell', + description: 'Type of the executed command.', + example: 'Application', + name: 'powershell.command.type', + type: 'keyword', + }, + 'powershell.command.value': { + category: 'powershell', + description: 'The invoked command.', + example: 'Import-LocalizedData LocalizedData -filename ArchiveResources', + name: 'powershell.command.value', + type: 'text', + }, + 'powershell.command.invocation_details': { + category: 'powershell', + description: 'An array of objects containing detailed information of the executed command. ', + name: 'powershell.command.invocation_details', + type: 'array', + }, + 'powershell.command.invocation_details.type': { + category: 'powershell', + description: 'The type of detail.', + example: 'CommandInvocation', + name: 'powershell.command.invocation_details.type', + type: 'keyword', + }, + 'powershell.command.invocation_details.related_command': { + category: 'powershell', + description: 'The command to which the detail is related to.', + example: 'Add-Type', + name: 'powershell.command.invocation_details.related_command', + type: 'keyword', + }, + 'powershell.command.invocation_details.name': { + category: 'powershell', + description: 'Only used for ParameterBinding detail type. Indicates the parameter name. ', + example: 'AssemblyName', + name: 'powershell.command.invocation_details.name', + type: 'keyword', + }, + 'powershell.command.invocation_details.value': { + category: 'powershell', + description: 'The value of the detail. The meaning of it will depend on the detail type. ', + example: 'System.IO.Compression.FileSystem', + name: 'powershell.command.invocation_details.value', + type: 'text', + }, + 'powershell.connected_user.domain': { + category: 'powershell', + description: 'User domain.', + example: 'VAGRANT', + name: 'powershell.connected_user.domain', + type: 'keyword', + }, + 'powershell.connected_user.name': { + category: 'powershell', + description: 'User name.', + example: 'vagrant', + name: 'powershell.connected_user.name', + type: 'keyword', + }, + 'powershell.engine.version': { + category: 'powershell', + description: 'Version of the PowerShell engine version used to execute the command.', + example: '5.1.17763.1007', + name: 'powershell.engine.version', + type: 'keyword', + }, + 'powershell.engine.previous_state': { + category: 'powershell', + description: 'Previous state of the PowerShell engine. ', + example: 'Available', + name: 'powershell.engine.previous_state', + type: 'keyword', + }, + 'powershell.engine.new_state': { + category: 'powershell', + description: 'New state of the PowerShell engine. ', + example: 'Stopped', + name: 'powershell.engine.new_state', + type: 'keyword', + }, + 'powershell.file.script_block_id': { + category: 'powershell', + description: 'Id of the executed script block.', + example: '50d2dbda-7361-4926-a94d-d9eadfdb43fa', + name: 'powershell.file.script_block_id', + type: 'keyword', + }, + 'powershell.file.script_block_text': { + category: 'powershell', + description: 'Text of the executed script block. ', + example: '.\\a_script.ps1', + name: 'powershell.file.script_block_text', + type: 'text', + }, + 'powershell.process.executable_version': { + category: 'powershell', + description: 'Version of the engine hosting process executable.', + example: '5.1.17763.1007', + name: 'powershell.process.executable_version', + type: 'keyword', + }, + 'powershell.provider.new_state': { + category: 'powershell', + description: 'New state of the PowerShell provider. ', + example: 'Active', + name: 'powershell.provider.new_state', + type: 'keyword', + }, + 'powershell.provider.name': { + category: 'powershell', + description: 'Provider name. ', + example: 'Variable', + name: 'powershell.provider.name', + type: 'keyword', + }, + 'winlog.logon.type': { + category: 'winlog', + description: + 'Logon type name. This is the descriptive version of the `winlog.event_data.LogonType` ordinal. This is an enrichment added by the Security module. ', + example: 'RemoteInteractive', + name: 'winlog.logon.type', + type: 'keyword', + }, + 'winlog.logon.id': { + category: 'winlog', + description: + 'Logon ID that can be used to associate this logon with other events related to the same logon session. ', + name: 'winlog.logon.id', + type: 'keyword', + }, + 'winlog.logon.failure.reason': { + category: 'winlog', + description: 'The reason the logon failed. ', + name: 'winlog.logon.failure.reason', + type: 'keyword', + }, + 'winlog.logon.failure.status': { + category: 'winlog', + description: + 'The reason the logon failed. This is textual description based on the value of the hexadecimal `Status` field. ', + name: 'winlog.logon.failure.status', + type: 'keyword', + }, + 'winlog.logon.failure.sub_status': { + category: 'winlog', + description: + 'Additional information about the logon failure. This is a textual description based on the value of the hexidecimal `SubStatus` field. ', + name: 'winlog.logon.failure.sub_status', + type: 'keyword', + }, + 'sysmon.dns.status': { + category: 'sysmon', + description: 'Windows status code returned for the DNS query.', + name: 'sysmon.dns.status', + type: 'keyword', + }, + 'sysmon.file.archived': { + category: 'sysmon', + description: 'Indicates if the deleted file was archived.', + name: 'sysmon.file.archived', + type: 'boolean', + }, + 'sysmon.file.is_executable': { + category: 'sysmon', + description: 'Indicates if the deleted file was an executable.', + name: 'sysmon.file.is_executable', + type: 'boolean', + }, +}; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/index.test.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/index.test.ts deleted file mode 100644 index 29944edf382f43..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/index.test.ts +++ /dev/null @@ -1,397 +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 { cloneDeep, isArray } from 'lodash/fp'; - -import { convertSchemaToAssociativeArray, getIndexSchemaDoc } from '.'; -import { auditbeatSchema, filebeatSchema, packetbeatSchema } from './8.0.0'; -import { Schema } from './type'; - -describe('Schema Beat', () => { - describe('Transform Schema documentation to an associative array', () => { - test('Auditbeat transformation', async () => { - const convertData: Schema = cloneDeep(auditbeatSchema).slice(0, 1); - convertData[0].fields = isArray(convertData[0].fields) - ? convertData[0].fields!.slice(0, 6) - : []; - - expect(convertSchemaToAssociativeArray(convertData)).toEqual({ - '@timestamp': { - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - name: '@timestamp', - type: 'date', - }, - labels: { - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - name: 'labels', - type: 'object', - }, - message: { - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - name: 'message', - type: 'text', - }, - tags: { - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - name: 'tags', - type: 'keyword', - }, - agent: { - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - name: 'agent', - type: 'group', - fields: { - 'agent.ephemeral_id': { - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - name: 'ephemeral_id', - type: 'keyword', - }, - 'agent.id': { - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - name: 'id', - type: 'keyword', - }, - 'agent.name': { - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - name: 'name', - type: 'keyword', - }, - 'agent.type': { - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - name: 'type', - type: 'keyword', - }, - 'agent.version': { - description: 'Version of the agent.', - example: '6.0.0-rc2', - name: 'version', - type: 'keyword', - }, - }, - }, - as: { - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - name: 'as', - type: 'group', - fields: { - 'as.number': { - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - name: 'number', - type: 'long', - }, - 'as.organization.name': { - description: 'Organization name.', - example: 'Google LLC', - name: 'organization.name', - type: 'keyword', - }, - }, - }, - }); - }); - - test('Filebeat transformation', async () => { - const convertData: Schema = cloneDeep(filebeatSchema).slice(0, 1); - convertData[0].fields = isArray(convertData[0].fields) - ? convertData[0].fields!.slice(0, 6) - : []; - - expect(convertSchemaToAssociativeArray(convertData)).toEqual({ - '@timestamp': { - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - name: '@timestamp', - type: 'date', - }, - labels: { - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - name: 'labels', - type: 'object', - }, - message: { - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - name: 'message', - type: 'text', - }, - tags: { - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - name: 'tags', - type: 'keyword', - }, - agent: { - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - name: 'agent', - type: 'group', - fields: { - 'agent.ephemeral_id': { - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - name: 'ephemeral_id', - type: 'keyword', - }, - 'agent.id': { - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - name: 'id', - type: 'keyword', - }, - 'agent.name': { - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - name: 'name', - type: 'keyword', - }, - 'agent.type': { - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - name: 'type', - type: 'keyword', - }, - 'agent.version': { - description: 'Version of the agent.', - example: '6.0.0-rc2', - name: 'version', - type: 'keyword', - }, - }, - }, - as: { - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - name: 'as', - type: 'group', - fields: { - 'as.number': { - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - name: 'number', - type: 'long', - }, - 'as.organization.name': { - description: 'Organization name.', - example: 'Google LLC', - name: 'organization.name', - type: 'keyword', - }, - }, - }, - }); - }); - - test('Packetbeat transformation', async () => { - const convertData: Schema = cloneDeep(packetbeatSchema).slice(0, 1); - convertData[0].fields = isArray(convertData[0].fields) - ? convertData[0].fields!.slice(0, 6) - : []; - - expect(convertSchemaToAssociativeArray(convertData)).toEqual({ - '@timestamp': { - description: - 'Date/time when the event originated.\n\nThis is the date/time extracted from the event, typically representing when\nthe event was generated by the source.\n\nIf the event source has no original timestamp, this value is typically populated\nby the first time the event was received by the pipeline.\n\nRequired field for all events.', - example: '2016-05-23T08:05:34.853Z', - name: '@timestamp', - type: 'date', - }, - labels: { - description: - 'Custom key/value pairs.\n\nCan be used to add meta information to events. Should not contain nested objects.\nAll values are stored as keyword.\n\nExample: `docker` and `k8s` labels.', - example: '{"application": "foo-bar", "env": "production"}', - name: 'labels', - type: 'object', - }, - message: { - description: - 'For log events the message field contains the log message, optimized\nfor viewing in a log viewer.\n\nFor structured logs without an original message field, other fields can be concatenated\nto form a human-readable summary of the event.\n\nIf multiple messages exist, they can be combined into one message.', - example: 'Hello World', - name: 'message', - type: 'text', - }, - tags: { - description: 'List of keywords used to tag each event.', - example: '["production", "env2"]', - name: 'tags', - type: 'keyword', - }, - agent: { - description: - 'The agent fields contain the data about the software entity, if\nany, that collects, detects, or observes events on a host, or takes measurements\non a host.\n\nExamples include Beats. Agents may also run on observers. ECS agent.* fields\nshall be populated with details of the agent running on the host or observer\nwhere the event happened or the measurement was taken.', - name: 'agent', - type: 'group', - fields: { - 'agent.ephemeral_id': { - description: - 'Ephemeral identifier of this agent (if one exists).\n\nThis id normally changes across restarts, but `agent.id` does not.', - example: '8a4f500f', - name: 'ephemeral_id', - type: 'keyword', - }, - 'agent.id': { - description: - 'Unique identifier of this agent (if one exists).\n\nExample: For Beats this would be beat.id.', - example: '8a4f500d', - name: 'id', - type: 'keyword', - }, - 'agent.name': { - description: - 'Custom name of the agent.\n\nThis is a name that can be given to an agent. This can be helpful if for example\ntwo Filebeat instances are running on the same host but a human readable separation\nis needed on which Filebeat instance data is coming from.\n\nIf no name is given, the name is often left empty.', - example: 'foo', - name: 'name', - type: 'keyword', - }, - 'agent.type': { - description: - 'Type of the agent.\n\nThe agent type stays always the same and should be given by the agent used.\nIn case of Filebeat the agent would always be Filebeat also if two Filebeat\ninstances are run on the same machine.', - example: 'filebeat', - name: 'type', - type: 'keyword', - }, - 'agent.version': { - description: 'Version of the agent.', - example: '6.0.0-rc2', - name: 'version', - type: 'keyword', - }, - }, - }, - as: { - description: - 'An autonomous system (AS) is a collection of connected Internet Protocol\n(IP) routing prefixes under the control of one or more network operators on\nbehalf of a single administrative entity or domain that presents a common, clearly\ndefined routing policy to the internet.', - name: 'as', - type: 'group', - fields: { - 'as.number': { - description: - 'Unique number allocated to the autonomous system. The autonomous\nsystem number (ASN) uniquely identifies each network on the Internet.', - example: 15169, - name: 'number', - type: 'long', - }, - 'as.organization.name': { - description: 'Organization name.', - example: 'Google LLC', - name: 'organization.name', - type: 'keyword', - }, - }, - }, - }); - }); - }); - - describe('GetIndexSchemaDoc', () => { - test('Filebeat transformation', async () => { - expect(Object.keys(getIndexSchemaDoc('auditbeat'))).toEqual([ - '_id', - '_index', - '@timestamp', - 'labels', - 'message', - 'tags', - 'agent', - 'as', - 'client', - 'cloud', - 'code_signature', - 'container', - 'destination', - 'dll', - 'dns', - 'ecs', - 'error', - 'event', - 'file', - 'geo', - 'group', - 'hash', - 'host', - 'http', - 'interface', - 'log', - 'network', - 'observer', - 'organization', - 'os', - 'package', - 'pe', - 'process', - 'registry', - 'related', - 'rule', - 'server', - 'service', - 'source', - 'threat', - 'tls', - 'tracing', - 'url', - 'user', - 'user_agent', - 'vlan', - 'vulnerability', - 'agent.hostname', - 'beat.timezone', - 'fields', - 'beat.name', - 'beat.hostname', - 'timeseries.instance', - 'cloud.project.id', - 'cloud.image.id', - 'meta.cloud.provider', - 'meta.cloud.instance_id', - 'meta.cloud.instance_name', - 'meta.cloud.machine_type', - 'meta.cloud.availability_zone', - 'meta.cloud.project_id', - 'meta.cloud.region', - 'docker', - 'kubernetes', - 'jolokia.agent.version', - 'jolokia.agent.id', - 'jolokia.server.product', - 'jolokia.server.version', - 'jolokia.server.vendor', - 'jolokia.url', - 'jolokia.secured', - 'auditd', - 'geoip', - 'socket', - 'system.audit', - ]); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/index.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/index.ts deleted file mode 100644 index 58627a199a1814..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/index.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get, has, isArray, isEmpty, isNumber, isString, memoize, pick } from 'lodash/fp'; - -import { - auditbeatSchema, - baseCategoryFields, - ecsSchema, - extraSchemaField, - filebeatSchema, - packetbeatSchema, - winlogbeatSchema, -} from './8.0.0'; -import { OutputSchema, Schema, SchemaFields, SchemaItem } from './type'; - -export * from './type'; -export { baseCategoryFields }; -export const convertSchemaToAssociativeArray = (schema: Schema): OutputSchema => - schema.reduce((accumulator: OutputSchema, item: Partial) => { - if (item.fields != null && !isEmpty(item.fields)) { - return { - ...accumulator, - ...convertFieldsToAssociativeArray(item), - }; - } - return accumulator; - }, {}); - -const paramsToPick = ['description', 'example', 'name', 'type', 'format']; - -const onlyStringOrNumber = (fields: object) => - Object.keys(fields).reduce((acc, item) => { - const value = get(item, fields); - return { - ...acc, - [item]: isString(value) || isNumber(value) ? value : JSON.stringify(value), - }; - }, {}); - -const convertFieldsToAssociativeArray = ( - schemaFields: Partial, - path: string = '' -): OutputSchema => - schemaFields.fields && isArray(schemaFields.fields) - ? schemaFields.fields.reduce((accumulator: OutputSchema, item: Partial) => { - if (item.name) { - const attr = isEmpty(path) ? item.name : `${path}.${item.name}`; - if (!isEmpty(item.fields) && isEmpty(path)) { - return { - ...accumulator, - [attr]: { - ...onlyStringOrNumber(pick(paramsToPick, item)), - fields: { - ...convertFieldsToAssociativeArray(item, attr), - }, - }, - }; - } else if (!isEmpty(item.fields) && !isEmpty(path)) { - return { - ...accumulator, - [attr]: onlyStringOrNumber(pick(paramsToPick, item)), - ...convertFieldsToAssociativeArray(item, attr), - }; - } else { - return { - ...accumulator, - [attr]: onlyStringOrNumber(pick(paramsToPick, item)), - }; - } - } - return accumulator; - }, {}) - : {}; - -export const getIndexSchemaDoc = memoize((index: string) => { - if (index.match('auditbeat') != null) { - return { - ...extraSchemaField, - ...convertSchemaToAssociativeArray(auditbeatSchema), - }; - } else if (index.match('filebeat') != null) { - return { - ...extraSchemaField, - ...convertSchemaToAssociativeArray(filebeatSchema), - }; - } else if (index.match('packetbeat') != null) { - return { - ...extraSchemaField, - ...convertSchemaToAssociativeArray(packetbeatSchema), - }; - } else if (index.match('winlogbeat') != null) { - return { - ...extraSchemaField, - ...convertSchemaToAssociativeArray(winlogbeatSchema), - }; - } - return { - ...extraSchemaField, - ...convertSchemaToAssociativeArray(ecsSchema), - }; -}); - -export const hasDocumentation = (index: string, path: string): boolean => { - const splitPath = path.split('.'); - const category = splitPath.length > 0 ? splitPath[0] : null; - if (category === null) { - return false; - } - if (splitPath.length > 1) { - return has([category, 'fields', path], getIndexSchemaDoc(index)); - } - return has(category, getIndexSchemaDoc(index)); -}; - -export const getDocumentation = (index: string, path: string) => { - const splitPath = path.split('.'); - const category = splitPath.length > 0 ? splitPath[0] : null; - if (category === null) { - return {}; - } - if (splitPath.length > 1) { - return get([category, 'fields', path], getIndexSchemaDoc(index)) || {}; - } - return get(category, getIndexSchemaDoc(index)) || {}; -}; diff --git a/x-pack/plugins/security_solution/server/utils/beat_schema/type.ts b/x-pack/plugins/security_solution/server/utils/beat_schema/type.ts deleted file mode 100644 index 722589ce7e2bb4..00000000000000 --- a/x-pack/plugins/security_solution/server/utils/beat_schema/type.ts +++ /dev/null @@ -1,73 +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. - */ - -/* - * BEAT Interface - * - */ - -export interface SchemaFields { - default_field: boolean; - default_fields: boolean; - definition: string; - deprecated: string; - description: string; - doc_values: boolean; - example: string | number | object | boolean; - footnote: string; - format: string; - group: number; - index: boolean; - ignore_above: number; - input_format: string; - level: string; - migration: boolean; - multi_fields: object[]; - name: string; - norms: boolean; - object_type: string; - object_type_mapping_type: string; - output_format: string; - output_precision: number; - overwrite: boolean; - path: string; - possible_values: string[] | number[]; - release: string; - required: boolean; - reusable: object; - short: string; - title: string; - type: string; - fields: Array>; -} - -export interface SchemaItem { - anchor: string; - key: string; - title: string; - description: string; - short_config: boolean; - release: string; - fields: Array>; -} - -export type Schema = Array>; - -/* - * Associative Array Output Interface - * - */ - -export interface RequiredSchemaField { - description: string; - example: string | number; - name: string; - type: string; - format: string; - fields: Readonly>>; -} - -export type OutputSchema = Readonly>>; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 680f8933b03737..ed66d56d552a5c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -12574,7 +12574,6 @@ "xpack.monitoring.cluster.overview.esPanel.versionLabel": "バージョン", "xpack.monitoring.cluster.overview.esPanel.versionNotAvailableDescription": "N/A", "xpack.monitoring.cluster.overview.esPanel.warnLogsTooltipText": "警告ログの数です", - "xpack.monitoring.cluster.overview.healthStatusDescription": "ヘルス: {status}", "xpack.monitoring.cluster.overview.kibanaPanel.connectionsLabel": "接続", "xpack.monitoring.cluster.overview.kibanaPanel.instancesCountLinkAriaLabel": "Kibana インスタンス: {instancesCount}", "xpack.monitoring.cluster.overview.kibanaPanel.instancesCountLinkLabel": "インスタンス: {instancesCount}", @@ -12693,8 +12692,6 @@ "xpack.monitoring.elasticsearch.nodeDetailStatus.transportAddress": "トランスポートアドレス", "xpack.monitoring.elasticsearch.nodeDetailStatus.typeLabel": "タイプ", "xpack.monitoring.elasticsearch.nodes.alertsColumnTitle": "アラート", - "xpack.monitoring.elasticsearch.nodes.cells.maxText": "最高 {metric}", - "xpack.monitoring.elasticsearch.nodes.cells.minText": "最低 {metric}", "xpack.monitoring.elasticsearch.nodes.cpuThrottlingColumnTitle": "CPU スロットル", "xpack.monitoring.elasticsearch.nodes.cpuUsageColumnTitle": "CPU 使用状況", "xpack.monitoring.elasticsearch.nodes.diskFreeSpaceColumnTitle": "ディスクの空き容量", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6e11dabd9843c8..103ff4ab146a4b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -12583,7 +12583,6 @@ "xpack.monitoring.cluster.overview.esPanel.versionLabel": "版本", "xpack.monitoring.cluster.overview.esPanel.versionNotAvailableDescription": "不适用", "xpack.monitoring.cluster.overview.esPanel.warnLogsTooltipText": "警告日志数", - "xpack.monitoring.cluster.overview.healthStatusDescription": "运行状况为{status}", "xpack.monitoring.cluster.overview.kibanaPanel.connectionsLabel": "连接", "xpack.monitoring.cluster.overview.kibanaPanel.instancesCountLinkAriaLabel": "Kibana 实例:{instancesCount}", "xpack.monitoring.cluster.overview.kibanaPanel.instancesCountLinkLabel": "实例:{instancesCount}", @@ -12702,8 +12701,6 @@ "xpack.monitoring.elasticsearch.nodeDetailStatus.transportAddress": "传输地址", "xpack.monitoring.elasticsearch.nodeDetailStatus.typeLabel": "类型", "xpack.monitoring.elasticsearch.nodes.alertsColumnTitle": "告警", - "xpack.monitoring.elasticsearch.nodes.cells.maxText": "{metric} 最大值", - "xpack.monitoring.elasticsearch.nodes.cells.minText": "{metric} 最小值", "xpack.monitoring.elasticsearch.nodes.cpuThrottlingColumnTitle": "CPU 限制", "xpack.monitoring.elasticsearch.nodes.cpuUsageColumnTitle": "CPU 使用", "xpack.monitoring.elasticsearch.nodes.diskFreeSpaceColumnTitle": "磁盘可用空间", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/delete_modal_confirmation.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/delete_modal_confirmation.tsx index 5862a567f71bae..a093b9c5119706 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/delete_modal_confirmation.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/delete_modal_confirmation.tsx @@ -5,7 +5,7 @@ */ import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { HttpSetup } from 'kibana/public'; import { useAppDependencies } from '../app_context'; @@ -17,6 +17,7 @@ export const DeleteModalConfirmation = ({ onErrors, singleTitle, multipleTitle, + setIsLoadingState, }: { idsToDelete: string[]; apiDeleteCall: ({ @@ -31,10 +32,17 @@ export const DeleteModalConfirmation = ({ onErrors: () => void; singleTitle: string; multipleTitle: string; + setIsLoadingState: (isLoading: boolean) => void; }) => { + const [deleteModalFlyoutVisible, setDeleteModalVisibility] = useState(false); + + useEffect(() => { + setDeleteModalVisibility(idsToDelete.length > 0); + }, [idsToDelete]); + const { http, toastNotifications } = useAppDependencies(); const numIdsToDelete = idsToDelete.length; - if (!numIdsToDelete) { + if (!deleteModalFlyoutVisible) { return null; } const confirmModalText = i18n.translate( @@ -65,12 +73,18 @@ export const DeleteModalConfirmation = ({ buttonColor="danger" data-test-subj="deleteIdsConfirmation" title={confirmButtonText} - onCancel={() => onCancel()} + onCancel={() => { + setDeleteModalVisibility(false); + onCancel(); + }} onConfirm={async () => { + setDeleteModalVisibility(false); + setIsLoadingState(true); const { successes, errors } = await apiDeleteCall({ ids: idsToDelete, http }); + setIsLoadingState(false); + const numSuccesses = successes.length; const numErrors = errors.length; - onDeleted(successes); if (numSuccesses > 0) { toastNotifications.addSuccess( i18n.translate( @@ -95,8 +109,9 @@ export const DeleteModalConfirmation = ({ } ) ); - onErrors(); + await onErrors(); } + await onDeleted(successes); }} cancelButtonText={cancelButtonText} confirmButtonText={confirmButtonText} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 352c9a67bbee2a..6bc9fd8e7e5a80 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -335,6 +335,7 @@ export const ActionsConnectorsList: React.FunctionComponent = () => { 'xpack.triggersActionsUI.sections.actionsConnectorsList.multipleTitle', { defaultMessage: 'connectors' } )} + setIsLoadingState={(isLoading: boolean) => setIsLoadingActionTypes(isLoading)} /> {/* Render the view based on if there's data or if they can save */} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx index 3d55c51e452813..7d0354589ecb83 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx @@ -404,16 +404,16 @@ export const AlertsList: React.FunctionComponent = () => {
{ - loadAlertsData(); - setSelectedIds([]); setAlertsToDelete([]); + setSelectedIds([]); + await loadAlertsData(); }} onErrors={async () => { // Refresh the alerts from the server, some alerts may have beend deleted await loadAlertsData(); setAlertsToDelete([]); }} - onCancel={async () => { + onCancel={() => { setAlertsToDelete([]); }} apiDeleteCall={deleteAlerts} @@ -424,6 +424,9 @@ export const AlertsList: React.FunctionComponent = () => { multipleTitle={i18n.translate('xpack.triggersActionsUI.sections.alertsList.multipleTitle', { defaultMessage: 'alerts', })} + setIsLoadingState={(isLoading: boolean) => { + setAlertsState({ ...alertsState, isLoading }); + }} /> {loadedItems.length || isFilterApplied ? ( diff --git a/x-pack/test/api_integration/apis/lens/existing_fields.ts b/x-pack/test/api_integration/apis/lens/existing_fields.ts index 92336f2892f433..10ee7bc9b48ea1 100644 --- a/x-pack/test/api_integration/apis/lens/existing_fields.ts +++ b/x-pack/test/api_integration/apis/lens/existing_fields.ts @@ -20,6 +20,9 @@ const fieldsWithData = [ '@tags', '@tags.raw', '@timestamp', + '_id', + '_index', + '_source', 'agent', 'agent.raw', 'bytes', @@ -96,6 +99,9 @@ const fieldsWithData = [ const metricBeatData = [ '@timestamp', + '_id', + '_index', + '_source', 'agent.ephemeral_id', 'agent.hostname', 'agent.id', @@ -185,6 +191,9 @@ export default ({ getService }: FtrProviderContext) => { '@tags', '@tags.raw', '@timestamp', + '_id', + '_index', + '_source', 'agent', 'agent.raw', 'bytes', diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js new file mode 100644 index 00000000000000..3eee56c962a274 --- /dev/null +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export default function ({ getService }) { + const supertest = getService('supertest'); + + describe('getGridTile', () => { + it('should validate params', async () => { + await supertest + .get( + `/api/maps/mvt/getGridTile?x=0&y=0&z=0&geometryFieldName=coordinates&index=logstash*&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:coordinates))),geotile_grid:(bounds:!n,field:coordinates,precision:!n,shard_size:65535,size:65535))),docvalue_fields:!((field:%27@timestamp%27,format:date_time),(field:timestamp,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(timestamp:(format:strict_date_optional_time,gte:%272020-09-16T13:57:36.734Z%27,lte:%272020-09-23T13:57:36.734Z%27)))),must:!(),must_not:!(),should:!())),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))&requestType=point&geoFieldType=geo_point` + ) + .set('kbn-xsrf', 'kibana') + .expect(200); + }); + + it('should not validate when required params are missing', async () => { + await supertest + .get( + `/api/maps/mvt/getGridTile?x=0&y=0&z=0&geometryFieldName=coordinates&index=logstash*&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:coordinates))),geotile_grid:(bounds:!n,field:coordinates,precision:!n,shard_size:65535,size:65535))),docvalue_fields:!((field:%27@timestamp%27,format:date_time),(field:timestamp,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(timestamp:(format:strict_date_optional_time,gte:%272020-09-16T13:57:36.734Z%27,lte:%272020-09-23T13:57:36.734Z%27)))),must:!(),must_not:!(),should:!())),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))&requestType=point` + ) + .set('kbn-xsrf', 'kibana') + .expect(400); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/maps/index.js b/x-pack/test/api_integration/apis/maps/index.js index 6c213380dd64e1..9f1fe96c5637bc 100644 --- a/x-pack/test/api_integration/apis/maps/index.js +++ b/x-pack/test/api_integration/apis/maps/index.js @@ -17,6 +17,7 @@ export default function ({ loadTestFile, getService }) { loadTestFile(require.resolve('./index_settings')); loadTestFile(require.resolve('./migrations')); loadTestFile(require.resolve('./get_tile')); + loadTestFile(require.resolve('./get_grid_tile')); }); }); } diff --git a/x-pack/test/api_integration/apis/security_solution/index.js b/x-pack/test/api_integration/apis/security_solution/index.js index e4204ae295653c..a143d94dde1726 100644 --- a/x-pack/test/api_integration/apis/security_solution/index.js +++ b/x-pack/test/api_integration/apis/security_solution/index.js @@ -12,16 +12,16 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./kpi_hosts')); loadTestFile(require.resolve('./network_dns')); loadTestFile(require.resolve('./network_top_n_flow')); - loadTestFile(require.resolve('./overview_host')); + // loadTestFile(require.resolve('./overview_host')); loadTestFile(require.resolve('./saved_objects/notes')); loadTestFile(require.resolve('./saved_objects/pinned_events')); loadTestFile(require.resolve('./saved_objects/timeline')); loadTestFile(require.resolve('./sources')); - loadTestFile(require.resolve('./overview_network')); + // loadTestFile(require.resolve('./overview_network')); loadTestFile(require.resolve('./timeline')); loadTestFile(require.resolve('./timeline_details')); - loadTestFile(require.resolve('./uncommon_processes')); - loadTestFile(require.resolve('./users')); + // loadTestFile(require.resolve('./uncommon_processes')); + // loadTestFile(require.resolve('./users')); // loadTestFile(require.resolve('./tls')); loadTestFile(require.resolve('./feature_controls')); }); diff --git a/x-pack/test/api_integration/apis/security_solution/network_details.ts b/x-pack/test/api_integration/apis/security_solution/network_details.ts index cffcd790fa19cf..7b851e875454de 100644 --- a/x-pack/test/api_integration/apis/security_solution/network_details.ts +++ b/x-pack/test/api_integration/apis/security_solution/network_details.ts @@ -5,7 +5,9 @@ */ import expect from '@kbn/expect'; +// @ts-expect-error import { ipOverviewQuery } from '../../../../plugins/security_solution/public/network/containers/details/index.gql_query'; +// @ts-expect-error import { GetIpOverviewQuery } from '../../../../plugins/security_solution/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/security_solution/overview_host.ts b/x-pack/test/api_integration/apis/security_solution/overview_host.ts index ffbf9d89fc112e..0d648e665a9a9e 100644 --- a/x-pack/test/api_integration/apis/security_solution/overview_host.ts +++ b/x-pack/test/api_integration/apis/security_solution/overview_host.ts @@ -7,7 +7,9 @@ import expect from '@kbn/expect'; import { DEFAULT_INDEX_PATTERN } from '../../../../plugins/security_solution/common/constants'; +// @ts-expect-error import { overviewHostQuery } from '../../../../plugins/security_solution/public/overview/containers//overview_host/index.gql_query'; +// @ts-expect-error import { GetOverviewHostQuery } from '../../../../plugins/security_solution/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/security_solution/overview_network.ts b/x-pack/test/api_integration/apis/security_solution/overview_network.ts index 6976b225a4d2ad..60d300e168e4ad 100644 --- a/x-pack/test/api_integration/apis/security_solution/overview_network.ts +++ b/x-pack/test/api_integration/apis/security_solution/overview_network.ts @@ -5,7 +5,9 @@ */ import expect from '@kbn/expect'; +// @ts-expect-error import { overviewNetworkQuery } from '../../../../plugins/security_solution/public/overview/containers/overview_network/index.gql_query'; +// @ts-expect-error import { GetOverviewNetworkQuery } from '../../../../plugins/security_solution/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/security_solution/sources.ts b/x-pack/test/api_integration/apis/security_solution/sources.ts index f99dd4c65fc83e..1ec4bfda8492de 100644 --- a/x-pack/test/api_integration/apis/security_solution/sources.ts +++ b/x-pack/test/api_integration/apis/security_solution/sources.ts @@ -5,110 +5,107 @@ */ import expect from '@kbn/expect'; -import { sourceQuery } from '../../../../plugins/security_solution/public/common/containers/source/index.gql_query'; -import { SourceQuery } from '../../../../plugins/security_solution/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); - const client = getService('securitySolutionGraphQLClient'); + const supertest = getService('supertest'); describe('sources', () => { before(() => esArchiver.load('auditbeat/default')); after(() => esArchiver.unload('auditbeat/default')); it('Make sure that we get source information when auditbeat indices is there', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - // test data in x-pack/test/functional/es_archives/auditbeat_test_data/data.json.gz - expect(sourceStatus.indexFields.length).to.be(397); - expect(sourceStatus.indicesExist).to.be(true); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: ['auditbeat-*'], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indexFields.length).to.be(351); + expect(sourceStatus.indicesExist).to.eql(['auditbeat-*']); }); it('should find indexes as being available when they exist', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - expect(sourceStatus.indicesExist).to.be(true); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indicesExist).to.eql(['auditbeat-*', 'winlogbeat-*']); }); it('should not find indexes as existing when there is an empty array of them', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: [], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - expect(sourceStatus.indicesExist).to.be(false); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: [], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indicesExist).to.eql([]); }); it('should not find indexes as existing when there is a _all within it', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: ['_all'], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - expect(sourceStatus.indicesExist).to.be(false); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: ['_all'], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indicesExist).to.eql([]); }); it('should not find indexes as existing when there are empty strings within it', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: [''], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - expect(sourceStatus.indicesExist).to.be(false); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: [''], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indicesExist).to.eql([]); }); it('should not find indexes as existing when there are blank spaces within it', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: [' '], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - expect(sourceStatus.indicesExist).to.be(false); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: [' '], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indicesExist).to.eql([]); }); it('should find indexes when one is an empty index but the others are valid', async () => { - const resp = await client.query({ - query: sourceQuery, - variables: { - sourceId: 'default', - defaultIndex: ['', 'auditbeat-*'], - docValueFields: [], - }, - }); - const sourceStatus = resp.data.source.status; - expect(sourceStatus.indicesExist).to.be(true); + const { body: sourceStatus } = await supertest + .post('/internal/search/securitySolutionIndexFields/') + .set('kbn-xsrf', 'true') + .send({ + indices: ['', 'auditbeat-*'], + onlyCheckIfIndicesExist: false, + }) + .expect(200); + + expect(sourceStatus.indicesExist).to.eql(['auditbeat-*']); }); }); } diff --git a/x-pack/test/api_integration/apis/security_solution/uncommon_processes.ts b/x-pack/test/api_integration/apis/security_solution/uncommon_processes.ts index f1e064bcc37bb3..1ed9a03ecf87ea 100644 --- a/x-pack/test/api_integration/apis/security_solution/uncommon_processes.ts +++ b/x-pack/test/api_integration/apis/security_solution/uncommon_processes.ts @@ -6,7 +6,9 @@ import expect from '@kbn/expect'; +// @ts-expect-error import { uncommonProcessesQuery } from '../../../../plugins/security_solution/public/hosts/containers/uncommon_processes/index.gql_query'; +// @ts-expect-error import { GetUncommonProcessesQuery } from '../../../../plugins/security_solution/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/security_solution/users.ts b/x-pack/test/api_integration/apis/security_solution/users.ts index abb2c5b2f5bbdd..9d42fc0b9788ba 100644 --- a/x-pack/test/api_integration/apis/security_solution/users.ts +++ b/x-pack/test/api_integration/apis/security_solution/users.ts @@ -5,11 +5,14 @@ */ import expect from '@kbn/expect'; +// @ts-expect-error import { usersQuery } from '../../../../plugins/security_solution/public/network/containers/users/index.gql_query'; import { Direction, + // @ts-expect-error UsersFields, FlowTarget, + // @ts-expect-error GetUsersQuery, } from '../../../../plugins/security_solution/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/functional/apps/maps/index.js b/x-pack/test/functional/apps/maps/index.js index 03b75601ec2a87..2d2d2f9d3cf9b8 100644 --- a/x-pack/test/functional/apps/maps/index.js +++ b/x-pack/test/functional/apps/maps/index.js @@ -47,6 +47,7 @@ export default function ({ loadTestFile, getService }) { loadTestFile(require.resolve('./es_pew_pew_source')); loadTestFile(require.resolve('./joins')); loadTestFile(require.resolve('./mvt_scaling')); + loadTestFile(require.resolve('./mvt_super_fine')); loadTestFile(require.resolve('./add_layer_panel')); loadTestFile(require.resolve('./import_geojson')); loadTestFile(require.resolve('./layer_errors')); diff --git a/x-pack/test/functional/apps/maps/mvt_super_fine.js b/x-pack/test/functional/apps/maps/mvt_super_fine.js new file mode 100644 index 00000000000000..b5a7935a81eb55 --- /dev/null +++ b/x-pack/test/functional/apps/maps/mvt_super_fine.js @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +const MB_VECTOR_SOURCE_ID = 'g1xkv'; + +export default function ({ getPageObjects, getService }) { + const PageObjects = getPageObjects(['maps']); + const inspector = getService('inspector'); + const security = getService('security'); + + describe('mvt grid layer', () => { + before(async () => { + await security.testUser.setRoles( + ['global_maps_all', 'test_logstash_reader', 'geoshape_data_reader'], + false + ); + await PageObjects.maps.loadSavedMap('geo grid vector grid example (SUPER_FINE resolution)'); + }); + + after(async () => { + await inspector.close(); + await security.testUser.restoreDefaults(); + }); + + it('should render with mvt-source', async () => { + const mapboxStyle = await PageObjects.maps.getMapboxStyle(); + + //Source should be correct + expect(mapboxStyle.sources[MB_VECTOR_SOURCE_ID].tiles[0]).to.equal( + "/api/maps/mvt/getGridTile?x={x}&y={y}&z={z}&geometryFieldName=geo.coordinates&index=logstash-*&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:geo.coordinates)),max_of_bytes:(max:(field:bytes))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),docvalue_fields:!((field:'@timestamp',format:date_time),(field:'relatedContent.article:modified_time',format:date_time),(field:'relatedContent.article:published_time',format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:('@timestamp':(format:strict_date_optional_time,gte:'2015-09-20T00:00:00.000Z',lte:'2015-09-20T01:00:00.000Z')))),must:!(),must_not:!(),should:!())),script_fields:(hour_of_day:(script:(lang:painless,source:'doc[!'@timestamp!'].value.getHour()'))),size:0,stored_fields:!('*'))&requestType=grid&geoFieldType=geo_point" + ); + + //Should correctly load meta for style-rule (sigma is set to 1, opacity to 1) + const fillLayer = mapboxStyle.layers.find( + (layer) => layer.id === MB_VECTOR_SOURCE_ID + '_fill' + ); + + expect(fillLayer.paint).to.eql({ + 'fill-color': [ + 'interpolate', + ['linear'], + [ + 'coalesce', + [ + 'case', + ['==', ['get', 'max_of_bytes'], null], + 1622, + ['max', ['min', ['to-number', ['get', 'max_of_bytes']], 9790], 1623], + ], + 1622, + ], + 1622, + 'rgba(0,0,0,0)', + 1623, + '#ecf1f7', + 2643.875, + '#d9e3ef', + 3664.75, + '#c5d5e7', + 4685.625, + '#b2c7df', + 5706.5, + '#9eb9d8', + 6727.375, + '#8bacd0', + 7748.25, + '#769fc8', + 8769.125, + '#6092c0', + ], + 'fill-opacity': 0.75, + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/monitoring/cluster/overview.js b/x-pack/test/functional/apps/monitoring/cluster/overview.js index 0e608e9a055fa4..e30280802e8c85 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/overview.js +++ b/x-pack/test/functional/apps/monitoring/cluster/overview.js @@ -30,7 +30,7 @@ export default function ({ getService, getPageObjects }) { }); it('shows elasticsearch panel with data', async () => { - expect(await overview.getEsStatus()).to.be('Health is green'); + expect(await overview.getEsStatus()).to.be('Healthy'); expect(await overview.getEsVersion()).to.be('7.0.0-alpha1'); expect(await overview.getEsUptime()).to.be('20 minutes'); expect(await overview.getEsNumberOfNodes()).to.be('Nodes: 2'); @@ -44,7 +44,7 @@ export default function ({ getService, getPageObjects }) { }); it('shows kibana panel', async () => { - expect(await overview.getEsStatus()).to.be('Health is green'); + expect(await overview.getEsStatus()).to.be('Healthy'); expect(await overview.getKbnRequests()).to.be('914'); expect(await overview.getKbnMaxResponseTime()).to.be('2873 ms'); expect(await overview.getKbnInstances()).to.be('Instances: 1'); @@ -81,7 +81,7 @@ export default function ({ getService, getPageObjects }) { }); it('shows elasticsearch panel with data', async () => { - expect(await overview.getEsStatus()).to.be('Health is yellow'); + expect(await overview.getEsStatus()).to.be('Missing replica shards'); expect(await overview.getEsVersion()).to.be('7.0.0-alpha1'); expect(await overview.getEsUptime()).to.be('5 minutes'); expect(await overview.getEsNumberOfNodes()).to.be('Nodes: 1'); @@ -95,7 +95,7 @@ export default function ({ getService, getPageObjects }) { }); it('shows kibana panel', async () => { - expect(await overview.getKbnStatus()).to.be('Health is green'); + expect(await overview.getKbnStatus()).to.be('Healthy'); expect(await overview.getKbnRequests()).to.be('174'); expect(await overview.getKbnMaxResponseTime()).to.be('2203 ms'); expect(await overview.getKbnInstances()).to.be('Instances: 1'); @@ -131,7 +131,7 @@ export default function ({ getService, getPageObjects }) { }); it('shows elasticsearch panel with data', async () => { - expect(await overview.getEsStatus()).to.be('Health is yellow'); + expect(await overview.getEsStatus()).to.be('Missing replica shards'); expect(await overview.getEsVersion()).to.be('7.0.0-alpha1'); expect(await overview.getEsUptime()).to.be('8 minutes'); expect(await overview.getEsNumberOfNodes()).to.be('Nodes: 1'); diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js index 569447df0533fb..8ae1f89c2f3b4f 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js @@ -56,23 +56,39 @@ export default function ({ getService, getPageObjects }) { expect(rows.length).to.be(3); const nodesAll = await nodesList.getNodesAll(); + console.log(JSON.stringify(nodesAll, null, 2)); const tableData = [ { name: 'whatever-01', status: 'Status: Online', - cpu: '0% \n3% max\n0% min', - load: '3.28 \n3.71 max\n2.19 min', - memory: '39% \n52% max\n25% min', - disk: '173.9 GB \n173.9 GB max\n173.9 GB min', + cpu: '0%', + cpuText: 'Trending\nup\nMax value\n3%\nMin value\n0%\nApplies to current time period', + load: '3.28', + loadText: + 'Trending\nup\nMax value\n3.71\nMin value\n2.19\nApplies to current time period', + memory: '39%', + memoryText: + 'Trending\ndown\nMax value\n52%\nMin value\n25%\nApplies to current time period', + disk: '173.9 GB', + diskText: + 'Trending\ndown\nMax value\n173.9 GB\nMin value\n173.9 GB\nApplies to current time period', shards: '38', }, { name: 'whatever-02', status: 'Status: Online', - cpu: '2% \n3% max\n0% min', - load: '3.28 \n3.73 max\n2.29 min', - memory: '25% \n49% max\n25% min', - disk: '173.9 GB \n173.9 GB max\n173.9 GB min', + cpu: '2%', + cpuText: + 'Trending\ndown\nMax value\n3%\nMin value\n0%\nApplies to current time period', + load: '3.28', + loadText: + 'Trending\nup\nMax value\n3.73\nMin value\n2.29\nApplies to current time period', + memory: '25%', + memoryText: + 'Trending\ndown\nMax value\n49%\nMin value\n25%\nApplies to current time period', + disk: '173.9 GB', + diskText: + 'Trending\ndown\nMax value\n173.9 GB\nMin value\n173.9 GB\nApplies to current time period', shards: '38', }, { name: 'whatever-03', status: 'Status: Offline' }, @@ -81,9 +97,13 @@ export default function ({ getService, getPageObjects }) { expect(nodesAll[node].name).to.be(tableData[node].name); expect(nodesAll[node].status).to.be(tableData[node].status); expect(nodesAll[node].cpu).to.be(tableData[node].cpu); + expect(nodesAll[node].cpuText).to.be(tableData[node].cpuText); expect(nodesAll[node].load).to.be(tableData[node].load); + expect(nodesAll[node].loadText).to.be(tableData[node].loadText); expect(nodesAll[node].memory).to.be(tableData[node].memory); + expect(nodesAll[node].memoryText).to.be(tableData[node].memoryText); expect(nodesAll[node].disk).to.be(tableData[node].disk); + expect(nodesAll[node].diskText).to.be(tableData[node].diskText); expect(nodesAll[node].shards).to.be(tableData[node].shards); }); }); @@ -94,12 +114,20 @@ export default function ({ getService, getPageObjects }) { const nodesAll = await nodesList.getNodesAll(); const tableData = [ - { cpu: '2% \n3% max\n0% min' }, - { cpu: '0% \n3% max\n0% min' }, - { cpu: undefined }, + { + cpu: '2%', + cpuText: + 'Trending\ndown\nMax value\n3%\nMin value\n0%\nApplies to current time period', + }, + { + cpu: '0%', + cpuText: 'Trending\nup\nMax value\n3%\nMin value\n0%\nApplies to current time period', + }, + { cpu: undefined, cpuText: undefined }, ]; nodesAll.forEach((obj, node) => { expect(nodesAll[node].cpu).to.be(tableData[node].cpu); + expect(nodesAll[node].cpuText).to.be(tableData[node].cpuText); }); }); @@ -109,12 +137,21 @@ export default function ({ getService, getPageObjects }) { const nodesAll = await nodesList.getNodesAll(); const tableData = [ - { load: '3.28 \n3.71 max\n2.19 min' }, - { load: '3.28 \n3.73 max\n2.29 min' }, + { + load: '3.28', + loadText: + 'Trending\nup\nMax value\n3.71\nMin value\n2.19\nApplies to current time period', + }, + { + load: '3.28', + loadText: + 'Trending\nup\nMax value\n3.73\nMin value\n2.29\nApplies to current time period', + }, { load: undefined }, ]; nodesAll.forEach((obj, node) => { expect(nodesAll[node].load).to.be(tableData[node].load); + expect(nodesAll[node].loadText).to.be(tableData[node].loadText); }); }); }); @@ -155,12 +192,21 @@ export default function ({ getService, getPageObjects }) { const nodesAll = await nodesList.getNodesAll(); const tableData = [ - { memory: '39% \n52% max\n25% min' }, - { memory: '25% \n49% max\n25% min' }, - { memory: undefined }, + { + memory: '39%', + memoryText: + 'Trending\ndown\nMax value\n52%\nMin value\n25%\nApplies to current time period', + }, + { + memory: '25%', + memoryText: + 'Trending\ndown\nMax value\n49%\nMin value\n25%\nApplies to current time period', + }, + { memory: undefined, memoryText: undefined }, ]; nodesAll.forEach((obj, node) => { expect(nodesAll[node].memory).to.be(tableData[node].memory); + expect(nodesAll[node].memoryText).to.be(tableData[node].memoryText); }); }); @@ -170,12 +216,21 @@ export default function ({ getService, getPageObjects }) { const nodesAll = await nodesList.getNodesAll(); const tableData = [ - { disk: '173.9 GB \n173.9 GB max\n173.9 GB min' }, - { disk: '173.9 GB \n173.9 GB max\n173.9 GB min' }, + { + disk: '173.9 GB', + diskText: + 'Trending\ndown\nMax value\n173.9 GB\nMin value\n173.9 GB\nApplies to current time period', + }, + { + disk: '173.9 GB', + diskText: + 'Trending\ndown\nMax value\n173.9 GB\nMin value\n173.9 GB\nApplies to current time period', + }, { disk: undefined }, ]; nodesAll.forEach((obj, node) => { expect(nodesAll[node].disk).to.be(tableData[node].disk); + expect(nodesAll[node].diskText).to.be(tableData[node].diskText); }); }); diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index f756d73484198f..e3a8743e60897b 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -615,6 +615,37 @@ } } +{ + "type": "doc", + "value": { + "id": "map:78116c8c-fd2a-11ea-adc1-0242ac120002", + "index": ".kibana", + "source": { + "map": { + "bounds": { + "coordinates": [ + [ + -140.62361, + 54.11832 + ], + [ + -55.49169, + 18.17193 + ] + ], + "type": "envelope" + }, + "description": "", + "layerListJSON": "[{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"SUPER_FINE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"TILED_VECTOR\"}]", + "mapStateJSON": "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}", + "title": "geo grid vector grid example (SUPER_FINE resolution)", + "uiStateJSON": "{\"isDarkMode\":false}" + }, + "type": "map" + } + } +} + { "type": "doc", "value": { diff --git a/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js b/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js index 0cae469e016974..55c34615373a93 100644 --- a/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js +++ b/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js @@ -6,6 +6,10 @@ import { range } from 'lodash'; +function trimAll(data) { + return data.map((item) => item.trim()); +} + export function MonitoringElasticsearchNodesProvider({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['monitoring']); @@ -35,6 +39,9 @@ export function MonitoringElasticsearchNodesProvider({ getService, getPageObject const SUBJ_NODES_DISKS = `${SUBJ_TABLE_BODY} > diskFreeSpace`; const SUBJ_NODES_SHARDS = `${SUBJ_TABLE_BODY} > shards`; + const SUBJ_NODES_ICON_PREFIX = `monitoringCellIcon`; + const SUBJ_NODES_POPOVER_PREFIX = `monitoringCellPopover`; + const SUBJ_NODE_LINK_PREFIX = `${SUBJ_TABLE_BODY} > nodeLink-`; return new (class ElasticsearchIndices { @@ -77,7 +84,6 @@ export function MonitoringElasticsearchNodesProvider({ getService, getPageObject await find.clickByCssSelector(`[data-test-subj="${SUBJ_TABLE_SORT_MEM_COL}"] > button`); await this.waitForTableToFinishLoading(); } - async clickDiskCol() { await find.clickByCssSelector(`[data-test-subj="${SUBJ_TABLE_SORT_DISK_COL}"] > button`); } @@ -108,12 +114,35 @@ export function MonitoringElasticsearchNodesProvider({ getService, getPageObject async getNodesAll() { const names = await testSubjects.getVisibleTextAll(SUBJ_NODES_NAMES); const statuses = await testSubjects.getAttributeAll(SUBJ_NODES_STATUSES, 'alt'); - const cpus = await testSubjects.getVisibleTextAll(SUBJ_NODES_CPUS); - const loads = await testSubjects.getVisibleTextAll(SUBJ_NODES_LOADS); - const memories = await testSubjects.getVisibleTextAll(SUBJ_NODES_MEMS); - const disks = await testSubjects.getVisibleTextAll(SUBJ_NODES_DISKS); + const cpus = trimAll(await testSubjects.getVisibleTextAll(SUBJ_NODES_CPUS)); + const loads = trimAll(await testSubjects.getVisibleTextAll(SUBJ_NODES_LOADS)); + const memories = trimAll(await testSubjects.getVisibleTextAll(SUBJ_NODES_MEMS)); + const disks = trimAll(await testSubjects.getVisibleTextAll(SUBJ_NODES_DISKS)); const shards = await testSubjects.getVisibleTextAll(SUBJ_NODES_SHARDS); + const areasWithText = { + cpuUsage: [], + loadAverage: [], + jvmMemory: [], + diskFreeSpace: [], + }; + + const table = await testSubjects.find(SUBJ_TABLE_BODY); + for (const key of Object.keys(areasWithText)) { + const text = areasWithText[key]; + const icons = await testSubjects.findAllDescendant( + `${SUBJ_NODES_ICON_PREFIX}-${key}`, + table + ); + for (const icon of icons) { + await icon.moveMouseTo(); + await icon.click(); + const _text = await testSubjects.getVisibleTextAll(`${SUBJ_NODES_POPOVER_PREFIX}-${key}`); + text.push(_text[0]); + await icon.click(); + } + } + // tuple-ize the icons and texts together into an array of objects const tableRows = await this.getRows(); const iterator = range(tableRows.length); @@ -124,9 +153,13 @@ export function MonitoringElasticsearchNodesProvider({ getService, getPageObject name: names[current], status: statuses[current], cpu: cpus[current], + cpuText: areasWithText.cpuUsage[current], load: loads[current], + loadText: areasWithText.loadAverage[current], memory: memories[current], + memoryText: areasWithText.jvmMemory[current], disk: disks[current], + diskText: areasWithText.diskFreeSpace[current], shards: shards[current], }, ]; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts index 67672cb54c21b8..359be662b0216b 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts @@ -40,8 +40,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { return createdAlert; } - // FLAKY: https://github.com/elastic/kibana/issues/77401 - describe.skip('alerts', function () { + describe('alerts', function () { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); await testSubjects.click('alertsTab'); @@ -385,9 +384,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('deleteAll'); await testSubjects.existOrFail('deleteIdsConfirmation'); await testSubjects.click('deleteIdsConfirmation > confirmModalConfirmButton'); - await testSubjects.missingOrFail('deleteIdsConfirmation', { timeout: 5000 }); + await testSubjects.missingOrFail('deleteIdsConfirmation'); - await pageObjects.common.closeToast(); + await retry.try(async () => { + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql('Deleted 10 alerts'); + }); await pageObjects.common.navigateToApp('triggersActions'); await pageObjects.triggersActionsUI.searchAlerts(namePrefix); diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts index 198c129b7482fa..492af399d5e308 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts @@ -29,7 +29,8 @@ export default function (providerContext: FtrProviderContext) { .send({ force: true }); }; - describe('installs and uninstalls all assets', async () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/72102 + describe.skip('installs and uninstalls all assets', async () => { describe('installs all assets when installing a package for the first time', async () => { skipIfNoDockerRegistry(providerContext); before(async () => { diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts index 9af27f5f985582..8203b4d1838716 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts @@ -32,7 +32,8 @@ export default function (providerContext: FtrProviderContext) { .send({ force: true }); }; - describe('updates all assets when updating a package to a different version', async () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/72102 + describe.skip('updates all assets when updating a package to a different version', async () => { skipIfNoDockerRegistry(providerContext); before(async () => { await installPackage(pkgKey); diff --git a/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/acks.ts b/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/acks.ts index 1613ca9d11ee66..360b91203dfc87 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/acks.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/acks.ts @@ -13,6 +13,7 @@ export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const esArchiver = getService('esArchiver'); const esClient = getService('es'); + const kibanaServer = getService('kibanaServer'); const supertest = getSupertestWithoutAuth(providerContext); let apiKey: { id: string; api_key: string }; @@ -205,5 +206,50 @@ export default function (providerContext: FtrProviderContext) { 'ACTION not allowed for acknowledgment only ACTION_RESULT' ); }); + + it('ack upgrade should update fleet-agent SO', async () => { + const { body: actionRes } = await supertest + .post(`/api/ingest_manager/fleet/agents/agent1/actions`) + .set('kbn-xsrf', 'xx') + .set( + 'Authorization', + `ApiKey ${Buffer.from(`${apiKey.id}:${apiKey.api_key}`).toString('base64')}` + ) + .send({ + action: { + type: 'UPGRADE', + ack_data: { version: '8.0.0', source_uri: 'http://localhost:8000' }, + }, + }) + .expect(200); + const actionId = actionRes.item.id; + await supertest + .post(`/api/ingest_manager/fleet/agents/agent1/acks`) + .set('kbn-xsrf', 'xx') + .set( + 'Authorization', + `ApiKey ${Buffer.from(`${apiKey.id}:${apiKey.api_key}`).toString('base64')}` + ) + .send({ + events: [ + { + type: 'ACTION_RESULT', + subtype: 'ACKNOWLEDGED', + timestamp: '2020-09-21T13:25:29.02838-04:00', + action_id: actionId, + agent_id: 'agent1', + message: + "Action '70d97288-ffd9-4549-8c49-2423a844f67f' of type 'UPGRADE' acknowledged.", + }, + ], + }) + .expect(200); + + const res = await kibanaServer.savedObjects.get({ + type: 'fleet-agents', + id: 'agent1', + }); + expect(res.attributes.upgraded_at).to.be.ok(); + }); }); } diff --git a/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts b/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts new file mode 100644 index 00000000000000..a783f806c03ee8 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect/expect.js'; +import { FtrProviderContext } from '../../../../api_integration/ftr_provider_context'; +import { setupIngest } from './services'; +import { skipIfNoDockerRegistry } from '../../../helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + + describe('fleet upgrade agent', () => { + skipIfNoDockerRegistry(providerContext); + setupIngest(providerContext); + before(async () => { + await esArchiver.loadIfNeeded('fleet/agents'); + }); + after(async () => { + await esArchiver.unload('fleet/agents'); + }); + + it('should respond 200 to upgrade agent and update the agent SO', async () => { + const kibanaVersionAccessor = kibanaServer.version; + const kibanaVersion = await kibanaVersionAccessor.get(); + await supertest + .post(`/api/ingest_manager/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: kibanaVersion, + source_uri: 'http://path/to/download', + }) + .expect(200); + const res = await kibanaServer.savedObjects.get({ + type: 'fleet-agents', + id: 'agent1', + }); + expect(res.attributes.upgrade_started_at).to.be.ok(); + }); + + it('should respond 400 if trying to upgrade to a version that does not match installed kibana version', async () => { + await supertest + .post(`/api/ingest_manager/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: '8.0.1', + source_uri: 'http://path/to/download', + }) + .expect(400); + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/fleet/index.js b/x-pack/test/ingest_manager_api_integration/apis/fleet/index.js index 96b9ffd1b04c09..9eb51bee3c7dde 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/fleet/index.js +++ b/x-pack/test/ingest_manager_api_integration/apis/fleet/index.js @@ -18,6 +18,7 @@ export default function loadTests({ loadTestFile }) { loadTestFile(require.resolve('./enrollment_api_keys/crud')); loadTestFile(require.resolve('./install')); loadTestFile(require.resolve('./agents/actions')); + loadTestFile(require.resolve('./agents/upgrade')); loadTestFile(require.resolve('./agents/reassign')); }); } diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index d46171bbaa49f5..c9d2b7a21d0da3 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -65,7 +65,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ], ]; - describe('endpoint list', function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/72102 + describe.skip('endpoint list', function () { this.tags('ciGroup7'); const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms)); @@ -86,7 +87,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.exists('emptyPolicyTable'); }); - it.skip('finds data after load and polling', async () => { + it('finds data after load and polling', async () => { await esArchiver.load('endpoint/metadata/destination_index', { useCreate: true }); await pageObjects.endpoint.waitForTableToHaveData('endpointListTable', 1100); const tableData = await pageObjects.endpointPageUtils.tableData('endpointListTable'); @@ -94,7 +95,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - describe.skip('when there is data,', () => { + describe('when there is data,', () => { before(async () => { await esArchiver.load('endpoint/metadata/destination_index', { useCreate: true }); await pageObjects.endpoint.navigateToEndpointList(); @@ -212,7 +213,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - describe.skip('displays the correct table data for the kql queries', () => { + describe('displays the correct table data for the kql queries', () => { before(async () => { await esArchiver.load('endpoint/metadata/destination_index', { useCreate: true }); await pageObjects.endpoint.navigateToEndpointList(); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts index 620eab37f9b46e..3e9726bf40073d 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts @@ -13,7 +13,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const queryBar = getService('queryBar'); - describe('Endpoint Event Resolver', function () { + // FLAKY: https://github.com/elastic/kibana/issues/78375 + describe.skip('Endpoint Event Resolver', function () { before(async () => { await esArchiver.load('endpoint/resolver_tree', { useCreate: true }); await pageObjects.hosts.navigateToSecurityHostsPage(); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts index 6c225dea5430f8..5a4053ee6f0a9a 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts @@ -18,6 +18,7 @@ export default function (providerContext: FtrProviderContext) { const supertestWithoutAuth = getSupertestWithoutAuth(providerContext); let agentAccessAPIKey: string; + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/72102 describe.skip('artifact download', () => { before(async () => { await esArchiver.load('endpoint/artifacts/api_feature', { useCreate: true }); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts index d1e98876596e50..2ab12e1ff3aae3 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts @@ -23,6 +23,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/72102 describe.skip('test metadata api', () => { describe(`POST ${METADATA_REQUEST_ROUTE} when index is empty`, () => { it('metadata api should return empty result when index is empty', async () => {