diff --git a/.buildkite/pipelines/pull_request/fleet_cypress.yml b/.buildkite/pipelines/pull_request/fleet_cypress.yml new file mode 100644 index 0000000000000..bfaa3faae7783 --- /dev/null +++ b/.buildkite/pipelines/pull_request/fleet_cypress.yml @@ -0,0 +1,11 @@ +steps: + - command: .buildkite/scripts/steps/functional/fleet_cypress.sh + label: 'Fleet Cypress Tests' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.js b/.buildkite/scripts/pipelines/pull_request/pipeline.js index c5ed216042b68..d0f38dc773357 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.js +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.js @@ -76,6 +76,16 @@ const uploadPipeline = (pipelineContent) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/apm_cypress.yml')); } + if ( + (await doAnyChangesMatch([ + /^x-pack\/plugins\/fleet/, + /^x-pack\/test\/fleet_cypress/, + ])) || + process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + ) { + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/fleet_cypress.yml')); + } + if (await doAnyChangesMatch([/^x-pack\/plugins\/uptime/])) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/uptime.yml')); } diff --git a/.buildkite/scripts/steps/functional/fleet_cypress.sh b/.buildkite/scripts/steps/functional/fleet_cypress.sh new file mode 100755 index 0000000000000..3847ffda08822 --- /dev/null +++ b/.buildkite/scripts/steps/functional/fleet_cypress.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +.buildkite/scripts/bootstrap.sh +.buildkite/scripts/download_build_artifacts.sh + +export JOB=kibana-fleet-cypress + +echo "--- Fleet Cypress tests" + +cd "$XPACK_DIR" + +checks-reporter-with-killswitch "Fleet Cypress Tests" \ + node scripts/functional_tests \ + --debug --bail \ + --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ + --config test/fleet_cypress/cli_config.ts diff --git a/.gitignore b/.gitignore index 32c77b20ef204..c08ae529c2c36 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,8 @@ report.asciidoc /bazel /bazel-* .bazelrc.user + +elastic-agent-* +fleet-server-* +elastic-agent.yml +fleet-server.yml \ No newline at end of file diff --git a/docs/concepts/index-patterns.asciidoc b/docs/concepts/data-views.asciidoc similarity index 55% rename from docs/concepts/index-patterns.asciidoc rename to docs/concepts/data-views.asciidoc index b8a10572fd8eb..7eb95405db6bc 100644 --- a/docs/concepts/index-patterns.asciidoc +++ b/docs/concepts/data-views.asciidoc @@ -1,45 +1,45 @@ -[[index-patterns]] -=== Create an index pattern +[[data-views]] +=== Create a data view -{kib} requires an index pattern to access the {es} data that you want to explore. -An index pattern selects the data to use and allows you to define properties of the fields. +{kib} requires a data view to access the {es} data that you want to explore. +A data view selects the data to use and allows you to define properties of the fields. -An index pattern can point to one or more indices, {ref}/data-streams.html[data stream], or {ref}/alias.html[index aliases]. -For example, an index pattern can point to your log data from yesterday, +A data view can point to one or more indices, {ref}/data-streams.html[data stream], or {ref}/alias.html[index aliases]. +For example, a data view can point to your log data from yesterday, or all indices that contain your data. [float] -[[index-patterns-read-only-access]] +[[data-views-read-only-access]] === Required permissions -* Access to *Index Patterns* requires the <> -`Index Pattern Management`. +* Access to *Data Views* requires the <> +`Data View Management`. -* To create an index pattern, you must have the <> +* To create a data view, you must have the <> `view_index_metadata`. * If a read-only indicator appears in {kib}, you have insufficient privileges -to create or save index patterns. The buttons to create new index patterns or -save existing index patterns are not visible. For more information, +to create or save data views. The buttons to create new data views or +save existing data views are not visible. For more information, refer to <>. [float] [[settings-create-pattern]] -=== Create an index pattern +=== Create a data view If you collected data using one of the {kib} <>, uploaded a file, or added sample data, -you get an index pattern for free, and can start exploring your data. -If you loaded your own data, follow these steps to create an index pattern. +you get a data view for free, and can start exploring your data. +If you loaded your own data, follow these steps to create a data view. -. Open the main menu, then click to *Stack Management > Index Patterns*. +. Open the main menu, then click to *Stack Management > Data Views*. + +. Click *Create data view*. -. Click *Create index pattern*. -+ [role="screenshot"] -image:management/index-patterns/images/create-index-pattern.png["Create index pattern"] +image:management/index-patterns/images/create-index-pattern.png["Create data view"] -. Start typing in the *Index pattern* field, and {kib} looks for the names of +. Start typing in the *name* field, and {kib} looks for the names of indices, data streams, and aliases that match your input. + ** To match multiple sources, use a wildcard (*). For example, `filebeat-*` matches @@ -61,21 +61,21 @@ global time filters on your dashboards. This is useful if you have multiple time fields and want to create dashboards that combine visualizations based on different timestamps. -. Click *Create index pattern*. +. Click *Create data view*. + [[reload-fields]] {kib} is now configured to use your {es} data. When a new field is added to an index, -the index pattern field list is updated -the next time the index pattern is loaded, for example, when you load the page or +the data view field list is updated +the next time the data view is loaded, for example, when you load the page or move between {kib} apps. -. Select this index pattern when you search and visualize your data. +. Select this data view when you search and visualize your data. [float] -[[rollup-index-pattern]] -==== Create an index pattern for rolled up data +[[rollup-data-view]] +==== Create a data view for rolled up data -An index pattern can match one rollup index. For a combination rollup -index pattern with both raw and rolled up data, use the standard notation: +A data view can match one rollup index. For a combination rollup +data view with both raw and rolled up data, use the standard notation: ```ts rollup_logstash,kibana_sample_data_logs @@ -84,7 +84,7 @@ For an example, refer to < Index Patterns*. +. Open the main menu, then click *Stack Management > Data Views*. -. Click the index pattern to delete. +. Click the data view to delete. -. Delete (image:management/index-patterns/images/delete.png[Delete icon]) the index pattern. +. Delete (image:management/index-patterns/images/delete.png[Delete icon]) the data view. diff --git a/docs/concepts/index.asciidoc b/docs/concepts/index.asciidoc index 20d7103f021cd..eac26beee1f9b 100644 --- a/docs/concepts/index.asciidoc +++ b/docs/concepts/index.asciidoc @@ -35,19 +35,19 @@ Open the search bar using the keyboard shortcut Ctrl+/ on Windows and Linux, Com image:concepts/images/global-search.png["Global search showing matches to apps and saved objects for the word visualize"] [float] -=== Accessing data with index patterns +=== Accessing data with data views -{kib} requires an index pattern to tell it which {es} data you want to access, -and whether the data is time-based. An index pattern can point to one or more {es} +{kib} requires a data view to tell it which {es} data you want to access, +and whether the data is time-based. A data view can point to one or more {es} data streams, indices, or index aliases by name. For example, `logs-elasticsearch-prod-*` is an index pattern, and it is time-based with a time field of `@timestamp`. The time field is not editable. -Index patterns are typically created by an administrator when sending data to {es}. -You can <> in *Stack Management*, or by using a script +Data views are typically created by an administrator when sending data to {es}. +You can <> in *Stack Management*, or by using a script that accesses the {kib} API. -{kib} uses the index pattern to show you a list of fields, such as +{kib} uses the data view to show you a list of fields, such as `event.duration`. You can customize the display name and format for each field. For example, you can tell {kib} to display `event.duration` in seconds. {kib} has <> for strings, @@ -75,7 +75,7 @@ and can optionally contain the time filter and extra filters. ==== Time filter The <> limits the time range of data displayed. -In most cases, the time filter applies to the time field in the index pattern, +In most cases, the time filter applies to the time field in the data view, but some apps allow you to use a different time field. Using the time filter, you can configure a refresh rate to periodically @@ -159,7 +159,7 @@ Use the global search to quickly open a saved object. * Go to <> for instructions on searching your data. -include::index-patterns.asciidoc[] +include::data-views.asciidoc[] include::set-time-filter.asciidoc[] diff --git a/docs/concepts/set-time-filter.asciidoc b/docs/concepts/set-time-filter.asciidoc index e4784a97e816b..116bcd6f91f77 100644 --- a/docs/concepts/set-time-filter.asciidoc +++ b/docs/concepts/set-time-filter.asciidoc @@ -2,7 +2,7 @@ === Set the time range Display data within a specified time range when your index contains time-based events, and a time-field is configured for the -selected <>. +selected <>. The default time range is 15 minutes, but you can customize it in <>. diff --git a/docs/development/core/public/kibana-plugin-core-public.httpresponse.md b/docs/development/core/public/kibana-plugin-core-public.httpresponse.md index 80a1cb8f02634..dcbfa556da65d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.httpresponse.md +++ b/docs/development/core/public/kibana-plugin-core-public.httpresponse.md @@ -8,7 +8,7 @@ Signature: ```typescript -export interface HttpResponse +export interface HttpResponse ``` ## Properties diff --git a/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.body.md b/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.body.md index 2a5b5067e0301..d053a5a9d360c 100644 --- a/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.body.md +++ b/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.body.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly body?: any; +readonly body?: TResponseBody; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.md b/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.md index 779cb4d3e59e5..8c21d1636711f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.md +++ b/docs/development/core/public/kibana-plugin-core-public.ihttpfetcherror.md @@ -8,14 +8,14 @@ Signature: ```typescript -export interface IHttpFetchError extends Error +export interface IHttpFetchError extends Error ``` ## Properties | Property | Type | Description | | --- | --- | --- | -| [body](./kibana-plugin-core-public.ihttpfetcherror.body.md) | any | | +| [body](./kibana-plugin-core-public.ihttpfetcherror.body.md) | TResponseBody | | | [name](./kibana-plugin-core-public.ihttpfetcherror.name.md) | string | | | [req](./kibana-plugin-core-public.ihttpfetcherror.req.md) | Request | | | [request](./kibana-plugin-core-public.ihttpfetcherror.request.md) | Request | | diff --git a/docs/development/core/public/kibana-plugin-core-public.ihttpresponseinterceptoroverrides.md b/docs/development/core/public/kibana-plugin-core-public.ihttpresponseinterceptoroverrides.md index 1e862bc4ae808..4b55cec8f3a2f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.ihttpresponseinterceptoroverrides.md +++ b/docs/development/core/public/kibana-plugin-core-public.ihttpresponseinterceptoroverrides.md @@ -9,7 +9,7 @@ Properties that can be returned by HttpInterceptor.request to override the respo Signature: ```typescript -export interface IHttpResponseInterceptorOverrides +export interface IHttpResponseInterceptorOverrides ``` ## Properties diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index e5fbe7c3524ed..a32dceafd74a9 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -97,6 +97,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [Plugin](./kibana-plugin-core-public.plugin.md) | The interface that should be returned by a PluginInitializer. | | [PluginInitializerContext](./kibana-plugin-core-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer | | [ResolvedSimpleSavedObject](./kibana-plugin-core-public.resolvedsimplesavedobject.md) | This interface is a very simple wrapper for SavedObjects resolved from the server with the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md). | +| [ResponseErrorBody](./kibana-plugin-core-public.responseerrorbody.md) | | | [SavedObject](./kibana-plugin-core-public.savedobject.md) | | | [SavedObjectAttributes](./kibana-plugin-core-public.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | | [SavedObjectError](./kibana-plugin-core-public.savedobjecterror.md) | | diff --git a/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.attributes.md b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.attributes.md new file mode 100644 index 0000000000000..bf64b25c04f92 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.attributes.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ResponseErrorBody](./kibana-plugin-core-public.responseerrorbody.md) > [attributes](./kibana-plugin-core-public.responseerrorbody.attributes.md) + +## ResponseErrorBody.attributes property + +Signature: + +```typescript +attributes?: Record; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.md b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.md new file mode 100644 index 0000000000000..8a990909fac3e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ResponseErrorBody](./kibana-plugin-core-public.responseerrorbody.md) + +## ResponseErrorBody interface + + +Signature: + +```typescript +export interface ResponseErrorBody +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [attributes](./kibana-plugin-core-public.responseerrorbody.attributes.md) | Record<string, unknown> | | +| [message](./kibana-plugin-core-public.responseerrorbody.message.md) | string | | +| [statusCode](./kibana-plugin-core-public.responseerrorbody.statuscode.md) | number | | + diff --git a/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.message.md b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.message.md new file mode 100644 index 0000000000000..a3355ddafde1e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.message.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ResponseErrorBody](./kibana-plugin-core-public.responseerrorbody.md) > [message](./kibana-plugin-core-public.responseerrorbody.message.md) + +## ResponseErrorBody.message property + +Signature: + +```typescript +message: string; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.statuscode.md b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.statuscode.md new file mode 100644 index 0000000000000..a342bb0187d72 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.responseerrorbody.statuscode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ResponseErrorBody](./kibana-plugin-core-public.responseerrorbody.md) > [statusCode](./kibana-plugin-core-public.responseerrorbody.statuscode.md) + +## ResponseErrorBody.statusCode property + +Signature: + +```typescript +statusCode: number; +``` diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index 0306be3eb670d..4f4f8f5b48d10 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -3,7 +3,7 @@ You can search your data in any app that has a query bar, or by clicking on elements in a visualization. A search matches indices in the current -<> and in the current <>. +<> and in the current <>. [float] diff --git a/docs/maps/search.asciidoc b/docs/maps/search.asciidoc index 08624e4ddff57..a170bcc414d3b 100644 --- a/docs/maps/search.asciidoc +++ b/docs/maps/search.asciidoc @@ -43,7 +43,7 @@ To prevent the global search from applying to a layer, configure the following: [[maps-narrow-layer-by-global-time]] ==== Narrow layers by global time -Layers that request data from {es} using an <> with a configured time field are narrowed by the <>. +Layers that request data from {es} using a <> with a configured time field are narrowed by the <>. These layers contain the clock icon image:maps/images/clock_icon.png[clock icon] next to the layer name in the legend. Use the time slider to quickly select time slices within the global time range: diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index d5bc2ccd8ef7d..4010083d601b5 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -358,3 +358,8 @@ This content has moved. Refer to <>. == Rendering pre-captured profiler JSON This content has moved. Refer to <>. + +[role="exclude",id="index-patterns"] +== Index patterns has been renamed to data views. + +This content has moved. Refer to <>. diff --git a/docs/setup/connect-to-elasticsearch.asciidoc b/docs/setup/connect-to-elasticsearch.asciidoc index ad38ac1710fd5..b1d9d3ea2ea18 100644 --- a/docs/setup/connect-to-elasticsearch.asciidoc +++ b/docs/setup/connect-to-elasticsearch.asciidoc @@ -84,7 +84,7 @@ You can manage your roles, privileges, and spaces in **{stack-manage-app}** in If the {kib} ingest options don't work for you, you can index your data into Elasticsearch with {ref}/getting-started-index.html[REST APIs] or https://www.elastic.co/guide/en/elasticsearch/client/index.html[client libraries]. -After you add your data, you're required to create an <> to tell +After you add your data, you're required to create a <> to tell {kib} where to find the data. * To add data for Elastic Observability, refer to {observability-guide}/add-observability-data.html[Send data to Elasticsearch]. diff --git a/docs/user/canvas.asciidoc b/docs/user/canvas.asciidoc index 1cd8eacc456c7..1f469b697c218 100644 --- a/docs/user/canvas.asciidoc +++ b/docs/user/canvas.asciidoc @@ -43,7 +43,7 @@ To create workpads, you must meet the minimum requirements. * If you need to set up {kib}, use https://www.elastic.co/cloud/elasticsearch-service/signup?baymax=docs-body&elektra=docs[our free trial]. -* Make sure you have {ref}/getting-started-index.html[data indexed into {es}] and an <>. +* Make sure you have {ref}/getting-started-index.html[data indexed into {es}] and a <>. * Have an understanding of {ref}/documents-indices.html[{es} documents and indices]. diff --git a/docs/user/dashboard/dashboard.asciidoc b/docs/user/dashboard/dashboard.asciidoc index a2e0eb6bf92e9..474b45f4989fb 100644 --- a/docs/user/dashboard/dashboard.asciidoc +++ b/docs/user/dashboard/dashboard.asciidoc @@ -5,7 +5,7 @@ -- **_Visualize your data with dashboards._** -The best way to understand your data is to visualize it. With dashboards, you can turn your data from one or more <> into a collection of panels +The best way to understand your data is to visualize it. With dashboards, you can turn your data from one or more <> into a collection of panels that bring clarity to your data, tell a story about your data, and allow you to focus on only the data that's important to you. [role="screenshot"] @@ -53,7 +53,7 @@ To create dashboards, you must meet the minimum requirements. * If you need to set up {kib}, use https://www.elastic.co/cloud/elasticsearch-service/signup?baymax=docs-body&elektra=docs[our free trial]. -* Make sure you have {ref}/getting-started-index.html[data indexed into {es}] and an <>. +* Make sure you have {ref}/getting-started-index.html[data indexed into {es}] and a <>. * When the read-only indicator appears, you have insufficient privileges to create or save dashboards, and the options to create and save dashboards are not visible. For more information, diff --git a/docs/user/dashboard/lens-advanced.asciidoc b/docs/user/dashboard/lens-advanced.asciidoc index d5a52428cff36..02e0afd2c0311 100644 --- a/docs/user/dashboard/lens-advanced.asciidoc +++ b/docs/user/dashboard/lens-advanced.asciidoc @@ -33,7 +33,7 @@ Open *Lens*, then make sure the correct fields appear. . Make sure the *kibana_sample_data_ecommerce* index appears. + -If you are using your own data, select the <> that contains your data. +If you are using your own data, select the <> that contains your data. [discrete] [[custom-time-interval]] diff --git a/docs/user/dashboard/tsvb.asciidoc b/docs/user/dashboard/tsvb.asciidoc index 9fe6af2d3da6d..c944ec2c9e083 100644 --- a/docs/user/dashboard/tsvb.asciidoc +++ b/docs/user/dashboard/tsvb.asciidoc @@ -8,7 +8,7 @@ With *TSVB*, you can: * Combine an infinite number of <> to display your data. * Annotate time series data with timestamped events from an {es} index. * View the data in several types of visualizations, including charts, data tables, and markdown panels. -* Display multiple <> in each visualization. +* Display multiple <> in each visualization. * Use custom functions and some math on aggregations. * Customize the data with labels and colors. diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc index e52531f9decdc..a485bb4c96efe 100644 --- a/docs/user/discover.asciidoc +++ b/docs/user/discover.asciidoc @@ -64,7 +64,7 @@ Tell {kib} where to find the data you want to explore, and then specify the time . Select the data you want to work with. + -{kib} uses an <> to tell it where to find +{kib} uses a <> to tell it where to find your {es} data. To view the ecommerce sample data, make sure the index pattern is set to **kibana_sample_data_ecommerce**. + diff --git a/docs/user/graph/getting-started.asciidoc b/docs/user/graph/getting-started.asciidoc index 086c0707b3c2c..5e87efc5e8aca 100644 --- a/docs/user/graph/getting-started.asciidoc +++ b/docs/user/graph/getting-started.asciidoc @@ -3,7 +3,7 @@ == Create a graph You must index data into {es} before you can create a graph. -<> or get started with a <>. +<> or get started with a <>. [float] [[exploring-connections]] diff --git a/examples/preboot_example/public/app.tsx b/examples/preboot_example/public/app.tsx index 364b7d5bfe8d3..d95df8cf72164 100644 --- a/examples/preboot_example/public/app.tsx +++ b/examples/preboot_example/public/app.tsx @@ -17,7 +17,7 @@ import { EuiText, } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; -import type { HttpSetup, IHttpFetchError } from 'src/core/public'; +import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from 'src/core/public'; export const App = ({ http, token }: { http: HttpSetup; token?: string }) => { const onCompleteSetup = async ({ shouldReloadConfig }: { shouldReloadConfig: boolean }) => { @@ -41,7 +41,8 @@ export const App = ({ http, token }: { http: HttpSetup; token?: string }) => { .post('/api/preboot/connect_to_es', { body: JSON.stringify(elasticsearchConfig) }) .then( (response) => setConnectResponse(JSON.stringify(response)), - (err: IHttpFetchError) => setConnectResponse(err?.body?.message || 'ERROR') + (err: IHttpFetchError) => + setConnectResponse(err?.body?.message || 'ERROR') ); }; diff --git a/packages/elastic-apm-synthtrace/src/index.ts b/packages/elastic-apm-synthtrace/src/index.ts index 97cde3e2c4f7d..70105438ff5ae 100644 --- a/packages/elastic-apm-synthtrace/src/index.ts +++ b/packages/elastic-apm-synthtrace/src/index.ts @@ -7,10 +7,12 @@ */ export { service } from './lib/service'; +export { browser } from './lib/browser'; export { timerange } from './lib/timerange'; export { getTransactionMetrics } from './lib/utils/get_transaction_metrics'; export { getSpanDestinationMetrics } from './lib/utils/get_span_destination_metrics'; export { getObserverDefaults } from './lib/defaults/get_observer_defaults'; +export { getChromeUserAgentDefaults } from './lib/defaults/get_chrome_user_agent_defaults'; export { toElasticsearchOutput } from './lib/output/to_elasticsearch_output'; export { getBreakdownMetrics } from './lib/utils/get_breakdown_metrics'; export { cleanWriteTargets } from './lib/utils/clean_write_targets'; diff --git a/packages/elastic-apm-synthtrace/src/lib/browser.ts b/packages/elastic-apm-synthtrace/src/lib/browser.ts new file mode 100644 index 0000000000000..0fd8b44b69851 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/lib/browser.ts @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Entity, UserAgentFields } from './entity'; +import { RumSpan } from './rum_span'; +import { RumTransaction } from './rum_transaction'; + +export class Browser extends Entity { + transaction(transactionName: string, transactionType: string = 'page-load') { + return new RumTransaction({ + ...this.fields, + 'transaction.name': transactionName, + 'transaction.type': transactionType, + }); + } + + span(spanName: string, spanType: string, spanSubtype: string) { + return new RumSpan({ + ...this.fields, + 'span.name': spanName, + 'span.type': spanType, + 'span.subtype': spanSubtype, + }); + } +} + +export function browser(serviceName: string, production: string, userAgent: UserAgentFields) { + return new Browser({ + 'agent.name': 'rum-js', + 'service.name': serviceName, + 'service.environment': production, + ...userAgent, + }); +} diff --git a/packages/elastic-apm-synthtrace/src/lib/defaults/get_chrome_user_agent_defaults.ts b/packages/elastic-apm-synthtrace/src/lib/defaults/get_chrome_user_agent_defaults.ts new file mode 100644 index 0000000000000..0031456248c1a --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/lib/defaults/get_chrome_user_agent_defaults.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { UserAgentFields } from '../entity'; + +export function getChromeUserAgentDefaults(): UserAgentFields { + return { + 'user_agent.original': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36', + 'user_agent.device.name': 'MacBook', + 'user_agent.name': 'Chrome', + 'user_agent.version': 95, + 'user_agent.os.name': 'MacOS', + }; +} diff --git a/packages/elastic-apm-synthtrace/src/lib/entity.ts b/packages/elastic-apm-synthtrace/src/lib/entity.ts index bf8fc10efd3a7..c6e0c7193f8ba 100644 --- a/packages/elastic-apm-synthtrace/src/lib/entity.ts +++ b/packages/elastic-apm-synthtrace/src/lib/entity.ts @@ -15,6 +15,14 @@ export type ApplicationMetricFields = Partial<{ 'system.process.cpu.total.norm.pct': number; }>; +export type UserAgentFields = Partial<{ + 'user_agent.original': string; + 'user_agent.os.name': string; + 'user_agent.name': string; + 'user_agent.device.name': string; + 'user_agent.version': number; +}>; + export interface Exception { message: string; } @@ -32,6 +40,7 @@ export type Fields = Partial<{ 'error.grouping_name': string; 'error.grouping_key': string; 'host.name': string; + 'kubernetes.pod.uid': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; diff --git a/packages/elastic-apm-synthtrace/src/lib/instance.ts b/packages/elastic-apm-synthtrace/src/lib/instance.ts index 3570f497c9055..08444fde48ba6 100644 --- a/packages/elastic-apm-synthtrace/src/lib/instance.ts +++ b/packages/elastic-apm-synthtrace/src/lib/instance.ts @@ -38,6 +38,11 @@ export class Instance extends Entity { }); } + podId(podId: string) { + this.fields['kubernetes.pod.uid'] = podId; + return this; + } + appMetrics(metrics: ApplicationMetricFields) { return new Metricset({ ...this.fields, diff --git a/packages/elastic-apm-synthtrace/src/lib/rum_span.ts b/packages/elastic-apm-synthtrace/src/lib/rum_span.ts new file mode 100644 index 0000000000000..620da9041ddd8 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/lib/rum_span.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Span } from './span'; + +export class RumSpan extends Span {} diff --git a/packages/elastic-apm-synthtrace/src/lib/rum_transaction.ts b/packages/elastic-apm-synthtrace/src/lib/rum_transaction.ts new file mode 100644 index 0000000000000..8452887410179 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/lib/rum_transaction.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Transaction } from './transaction'; + +export class RumTransaction extends Transaction {} diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/create_logger.ts b/packages/elastic-apm-synthtrace/src/lib/utils/create_logger.ts index 4afdda74105cf..88d0d4af3a66b 100644 --- a/packages/elastic-apm-synthtrace/src/lib/utils/create_logger.ts +++ b/packages/elastic-apm-synthtrace/src/lib/utils/create_logger.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ -import { isPromise } from 'util/types'; +function isPromise(val: any): val is Promise { + return val && typeof val === 'object' && 'then' in val && typeof val.then === 'function'; +} export enum LogLevel { trace = 0, diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 571b564f90329..a16c15555f5e5 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -425,7 +425,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` } > - diff --git a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap index e73d5e8002a02..d2b1078641437 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/header.test.tsx.snap @@ -1272,45 +1272,7 @@ exports[`Header renders 1`] = ` "closed": false, "hasError": false, "isStopped": false, - "observers": Array [ - Subscriber { - "_parentOrParents": null, - "_subscriptions": Array [ - SubjectSubscription { - "_parentOrParents": [Circular], - "_subscriptions": null, - "closed": false, - "subject": [Circular], - "subscriber": [Circular], - }, - ], - "closed": false, - "destination": SafeSubscriber { - "_complete": undefined, - "_context": [Circular], - "_error": undefined, - "_next": [Function], - "_parentOrParents": null, - "_parentSubscriber": [Circular], - "_subscriptions": null, - "closed": false, - "destination": Object { - "closed": true, - "complete": [Function], - "error": [Function], - "next": [Function], - }, - "isStopped": false, - "syncErrorThrowable": false, - "syncErrorThrown": false, - "syncErrorValue": null, - }, - "isStopped": false, - "syncErrorThrowable": true, - "syncErrorThrown": false, - "syncErrorValue": null, - }, - ], + "observers": Array [], "thrownError": null, } } @@ -4338,7 +4300,6 @@ exports[`Header renders 1`] = ` } homeHref="/" id="generated-id" - isLocked={true} isNavOpen={false} navLinks$={ BehaviorSubject { diff --git a/src/core/public/chrome/ui/header/collapsible_nav.scss b/src/core/public/chrome/ui/header/collapsible_nav.scss index d72775d374d47..5f84863ad7309 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.scss +++ b/src/core/public/chrome/ui/header/collapsible_nav.scss @@ -3,3 +3,24 @@ max-height: $euiSize * 10; margin-right: -$euiSizeS; } + +/** + * 1. Increase the hit area of the link (anchor) + * 2. Only show the text underline when hovering on the text/anchor portion + */ + +.kbnCollapsibleNav__solutionGroupButton { + display: block; /* 1 */ + + &:hover { + text-decoration: none; /* 2 */ + } +} + +.kbnCollapsibleNav__solutionGroupLink { + display: block; /* 1 */ + + &:hover { + text-decoration: underline; /* 2 */ + } +} diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx index ccc0e17b655b1..ef380ee47e235 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx @@ -14,13 +14,12 @@ import { EuiHorizontalRule, EuiListGroup, EuiListGroupItem, - EuiShowFor, EuiCollapsibleNavProps, EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { groupBy, sortBy } from 'lodash'; -import React, { Fragment, useMemo, useRef } from 'react'; +import React, { Fragment, useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; import * as Rx from 'rxjs'; import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../..'; @@ -33,6 +32,7 @@ import { createRecentNavLink, isModifiedOrPrevented, createEuiButtonItem, + createOverviewLink, } from './nav_link'; function getAllCategories(allCategorizedLinks: Record) { const allCategories = {} as Record; @@ -72,7 +72,6 @@ interface Props { appId$: InternalApplicationStart['currentAppId$']; basePath: HttpStart['basePath']; id: string; - isLocked: boolean; isNavOpen: boolean; homeHref: string; navLinks$: Rx.Observable; @@ -86,10 +85,17 @@ interface Props { button: EuiCollapsibleNavProps['button']; } +const overviewIDsToHide = ['kibanaOverview', 'enterpriseSearch']; +const overviewIDs = [ + ...overviewIDsToHide, + 'observability-overview', + 'securitySolutionUI:overview', + 'management', +]; + export function CollapsibleNav({ basePath, id, - isLocked, isNavOpen, homeHref, storage = window.localStorage, @@ -104,23 +110,29 @@ export function CollapsibleNav({ const allowedLinks = useMemo( () => allLinks.filter( - // Filterting out hidden links and the integrations one in favor of a specific Add Data button at the bottom - (link) => !link.hidden && link.id !== 'integrations' + (link) => + // Filterting out hidden links, + !link.hidden && + // integrations link in favor of a specific Add Data button at the bottom, + link.id !== 'integrations' && + // and non-data overview pages + !overviewIDsToHide.includes(link.id) ), [allLinks] ); + // Find just the integrations link const integrationsLink = useMemo( - () => - allLinks.find( - // Find just the integrations link - (link) => link.id === 'integrations' - ), + () => allLinks.find((link) => link.id === 'integrations'), + [allLinks] + ); + // Find all the overview (landing page) links + const overviewLinks = useMemo( + () => allLinks.filter((link) => overviewIDs.includes(link.id)), [allLinks] ); const recentlyAccessed = useObservable(observables.recentlyAccessed$, []); const customNavLink = useObservable(observables.customNavLink$, undefined); const appId = useObservable(observables.appId$, ''); - const lockRef = useRef(null); const groupedNavLinks = groupBy(allowedLinks, (link) => link?.category?.id); const { undefined: unknowns = [], ...allCategorizedLinks } = groupedNavLinks; const categoryDictionary = getAllCategories(allCategorizedLinks); @@ -153,7 +165,7 @@ export function CollapsibleNav({ @@ -166,12 +178,13 @@ export function CollapsibleNav({ dataTestSubj: 'collapsibleNavCustomNavLink', onClick: closeNav, externalLink: true, + iconProps: { color: 'ghost' }, }), ]} maxWidth="none" - color="text" gutterSize="none" size="s" + color="ghost" /> @@ -270,13 +283,31 @@ export function CollapsibleNav({ {/* Kibana, Observability, Security, and Management sections */} {orderedCategories.map((categoryName) => { const category = categoryDictionary[categoryName]!; + const overviewLink = overviewLinks.find((link) => link.category === category); return ( + {category.label} + + ) : ( + category.label + ) + } isCollapsible={true} initialIsOpen={getIsCategoryOpen(category.id, storage)} onToggle={(isCategoryOpen) => setIsCategoryOpen(category.id, isCategoryOpen, storage)} @@ -305,45 +336,6 @@ export function CollapsibleNav({ ))} - - {/* Docking button only for larger screens that can support it*/} - - - - { - onIsLockedUpdate(!isLocked); - if (lockRef.current) { - lockRef.current.focus(); - } - }} - iconType={isLocked ? 'lock' : 'lockOpen'} - /> - - - {integrationsLink && ( @@ -355,7 +347,6 @@ export function CollapsibleNav({ link: integrationsLink, navigateToUrl, onClick: closeNav, - dataTestSubj: `collapsibleNavAppButton-${integrationsLink.id}`, })} fill fullWidth diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 578c87411e543..40108760cc0be 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -84,7 +84,6 @@ export function Header({ ...observables }: HeaderProps) { const isVisible = useObservable(observables.isVisible$, false); - const isLocked = useObservable(observables.isLocked$, false); const [isNavOpen, setIsNavOpen] = useState(false); const [navId] = useState(htmlIdGenerator()()); const breadcrumbsAppendExtension = useObservable(breadcrumbsAppendExtension$); @@ -160,7 +159,6 @@ export function Header({ : undefined, }), @@ -77,7 +80,7 @@ export function createEuiButtonItem({ navigateToUrl, dataTestSubj, }: Omit) { - const { href, disabled, url } = link; + const { href, disabled, url, id } = link; return { href, @@ -90,7 +93,30 @@ export function createEuiButtonItem({ navigateToUrl(url); }, isDisabled: disabled, - 'data-test-subj': dataTestSubj, + dataTestSubj: `collapsibleNavAppButton-${id}`, + }; +} + +export function createOverviewLink({ + link, + onClick = () => {}, + navigateToUrl, +}: Omit) { + const { href, url } = link; + + return { + href, + /* Use href and onClick to support "open in new tab" and SPA navigation in the same link */ + onClick(event: React.MouseEvent) { + // Prevent the accordions from opening or closing when clicking just the link + event.stopPropagation(); + if (!isModifiedOrPrevented(event)) { + onClick(); + } + event.preventDefault(); + navigateToUrl(url); + }, + 'data-test-subj': `collapsibleNavAppLink-overview`, }; } diff --git a/src/core/public/http/external_url_service.test.ts b/src/core/public/http/external_url_service.test.ts index dcd99280151bf..ee757c5046760 100644 --- a/src/core/public/http/external_url_service.test.ts +++ b/src/core/public/http/external_url_service.test.ts @@ -155,6 +155,40 @@ describe('External Url Service', () => { }); }); + internalRequestScenarios.forEach(({ description, policy, allowExternal }) => { + describe(description, () => { + it('allows relative URLs without absolute path replacing last path segment', () => { + const { setup } = setupService({ location, serverBasePath, policy }); + const urlCandidate = `my_other_app?foo=bar`; + const result = setup.validateUrl(urlCandidate); + + expect(result).toBeInstanceOf(URL); + expect(result?.toString()).toEqual(`${kibanaRoot}/app/${urlCandidate}`); + }); + + it('allows relative URLs without absolute path replacing multiple path segments', () => { + const { setup } = setupService({ location, serverBasePath, policy }); + const urlCandidate = `/api/my_other_app?foo=bar`; + const result = setup.validateUrl(`..${urlCandidate}`); + + expect(result).toBeInstanceOf(URL); + expect(result?.toString()).toEqual(`${kibanaRoot}${urlCandidate}`); + }); + + if (!allowExternal) { + describe('handles bypass of base path via relative URL', () => { + it('does not allow relative URLs that escape base path', () => { + const { setup } = setupService({ location, serverBasePath, policy: [] }); + const urlCandidate = `../../base_path_escape`; + const result = setup.validateUrl(urlCandidate); + + expect(result).toBeNull(); + }); + }); + } + }); + }); + describe('handles protocol resolution bypass', () => { it('does not allow relative URLs that include a host', () => { const { setup } = setupService({ location, serverBasePath, policy: [] }); @@ -194,7 +228,7 @@ describe('External Url Service', () => { internalRequestScenarios.forEach(({ description, policy }) => { describe(description, () => { - it('allows relative URLs', () => { + it('allows relative URLs with absolute path', () => { const { setup } = setupService({ location, serverBasePath, policy }); const urlCandidate = `/some/path?foo=bar`; const result = setup.validateUrl(`${serverBasePath}${urlCandidate}`); @@ -214,6 +248,28 @@ describe('External Url Service', () => { }); }); + internalRequestScenarios.forEach(({ description, policy }) => { + describe(description, () => { + it('allows relative URLs without absolute path replacing last path segment', () => { + const { setup } = setupService({ location, serverBasePath, policy }); + const urlCandidate = `my_other_app?foo=bar`; + const result = setup.validateUrl(urlCandidate); + + expect(result).toBeInstanceOf(URL); + expect(result?.toString()).toEqual(`${kibanaRoot}/app/${urlCandidate}`); + }); + + it('allows relative URLs without absolute path replacing multiple path segments', () => { + const { setup } = setupService({ location, serverBasePath, policy }); + const urlCandidate = `/api/my_other_app?foo=bar`; + const result = setup.validateUrl(`..${urlCandidate}`); + + expect(result).toBeInstanceOf(URL); + expect(result?.toString()).toEqual(`${kibanaRoot}${urlCandidate}`); + }); + }); + }); + describe('handles protocol resolution bypass', () => { it('does not allow relative URLs that include a host', () => { const { setup } = setupService({ location, serverBasePath, policy: [] }); diff --git a/src/core/public/http/external_url_service.ts b/src/core/public/http/external_url_service.ts index dbd7313b65059..166e167b3b994 100644 --- a/src/core/public/http/external_url_service.ts +++ b/src/core/public/http/external_url_service.ts @@ -14,7 +14,7 @@ import { InjectedMetadataSetup } from '../injected_metadata'; import { Sha256 } from '../utils'; interface SetupDeps { - location: Pick; + location: Pick; injectedMetadata: InjectedMetadataSetup; } @@ -52,11 +52,11 @@ function normalizeProtocol(protocol: string) { const createExternalUrlValidation = ( rules: IExternalUrlPolicy[], - location: Pick, + location: Pick, serverBasePath: string ) => { - const base = new URL(location.origin + serverBasePath); return function validateExternalUrl(next: string) { + const base = new URL(location.href); const url = new URL(next, base); const isInternalURL = diff --git a/src/core/public/http/fetch.test.ts b/src/core/public/http/fetch.test.ts index d1af183e9e180..e897d69057e02 100644 --- a/src/core/public/http/fetch.test.ts +++ b/src/core/public/http/fetch.test.ts @@ -438,7 +438,7 @@ describe('Fetch', () => { headers: { 'Content-Type': 'application/ndjson' }, }); - const data = await fetchInstance.post('/my/path', { + const data = await fetchInstance.post('/my/path', { body, headers: { 'Content-Type': undefined, diff --git a/src/core/public/http/fetch.ts b/src/core/public/http/fetch.ts index 372445b2b0902..4ee81f4b47aa0 100644 --- a/src/core/public/http/fetch.ts +++ b/src/core/public/http/fetch.ts @@ -92,9 +92,9 @@ export class Fetch { ); if (optionsWithPath.asResponse) { - resolve(interceptedResponse); + resolve(interceptedResponse as HttpResponse); } else { - resolve(interceptedResponse.body); + resolve(interceptedResponse.body as TResponseBody); } } catch (error) { if (!(error instanceof HttpInterceptHaltError)) { @@ -142,7 +142,9 @@ export class Fetch { return new Request(url, fetchOptions as RequestInit); } - private async fetchResponse(fetchOptions: HttpFetchOptionsWithPath): Promise> { + private async fetchResponse( + fetchOptions: HttpFetchOptionsWithPath + ): Promise> { const request = this.createRequest(fetchOptions); let response: Response; let body = null; @@ -181,9 +183,15 @@ export class Fetch { } private shorthand(method: string): HttpHandler { - return (pathOrOptions: string | HttpFetchOptionsWithPath, options?: HttpFetchOptions) => { - const optionsWithPath = validateFetchArguments(pathOrOptions, options); - return this.fetch({ ...optionsWithPath, method }); + return ( + pathOrOptions: string | HttpFetchOptionsWithPath, + options?: HttpFetchOptions + ) => { + const optionsWithPath: HttpFetchOptionsWithPath = validateFetchArguments( + pathOrOptions, + options + ); + return this.fetch>({ ...optionsWithPath, method }); }; } } diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts index 4d59c52813e18..876799765ea1c 100644 --- a/src/core/public/http/types.ts +++ b/src/core/public/http/types.ts @@ -296,18 +296,19 @@ export interface HttpFetchOptionsWithPath extends HttpFetchOptions { * @public */ export interface HttpHandler { - (path: string, options: HttpFetchOptions & { asResponse: true }): Promise< + ( + path: string, + options: HttpFetchOptions & { asResponse: true } + ): Promise>; + (options: HttpFetchOptionsWithPath & { asResponse: true }): Promise< HttpResponse >; - (options: HttpFetchOptionsWithPath & { asResponse: true }): Promise< - HttpResponse - >; - (path: string, options?: HttpFetchOptions): Promise; - (options: HttpFetchOptionsWithPath): Promise; + (path: string, options?: HttpFetchOptions): Promise; + (options: HttpFetchOptionsWithPath): Promise; } /** @public */ -export interface HttpResponse { +export interface HttpResponse { /** The original {@link HttpFetchOptionsWithPath} used to send this request. */ readonly fetchOptions: Readonly; /** Raw request sent to Kibana server. */ @@ -322,7 +323,7 @@ export interface HttpResponse { * Properties that can be returned by HttpInterceptor.request to override the response. * @public */ -export interface IHttpResponseInterceptorOverrides { +export interface IHttpResponseInterceptorOverrides { /** Raw response received, may be undefined if there was an error. */ readonly response?: Readonly; /** Parsed body received, may be undefined if there was an error. */ @@ -330,7 +331,14 @@ export interface IHttpResponseInterceptorOverrides { } /** @public */ -export interface IHttpFetchError extends Error { +export interface ResponseErrorBody { + message: string; + statusCode: number; + attributes?: Record; +} + +/** @public */ +export interface IHttpFetchError extends Error { readonly name: string; readonly request: Request; readonly response?: Response; @@ -342,7 +350,7 @@ export interface IHttpFetchError extends Error { * @deprecated Provided for legacy compatibility. Prefer the `response` property instead. */ readonly res?: Response; - readonly body?: any; // TODO: this should be unknown + readonly body?: TResponseBody; } /** @public */ diff --git a/src/core/public/index.ts b/src/core/public/index.ts index b2d3d21a09999..40326d9c67606 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -157,6 +157,7 @@ export type { IAnonymousPaths, IExternalUrl, IHttpInterceptController, + ResponseErrorBody, IHttpFetchError, IHttpResponseInterceptorOverrides, } from './http'; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 5d63d2b6f77ce..6c377bd2870ae 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -805,17 +805,17 @@ export interface HttpFetchQuery { // @public export interface HttpHandler { // (undocumented) - (path: string, options: HttpFetchOptions & { + (path: string, options: HttpFetchOptions & { asResponse: true; }): Promise>; // (undocumented) - (options: HttpFetchOptionsWithPath & { + (options: HttpFetchOptionsWithPath & { asResponse: true; }): Promise>; // (undocumented) - (path: string, options?: HttpFetchOptions): Promise; + (path: string, options?: HttpFetchOptions): Promise; // (undocumented) - (options: HttpFetchOptionsWithPath): Promise; + (options: HttpFetchOptionsWithPath): Promise; } // @public @@ -867,7 +867,7 @@ export interface HttpRequestInit { } // @public (undocumented) -export interface HttpResponse { +export interface HttpResponse { readonly body?: TResponseBody; readonly fetchOptions: Readonly; readonly request: Readonly; @@ -934,9 +934,9 @@ export interface IExternalUrlPolicy { } // @public (undocumented) -export interface IHttpFetchError extends Error { +export interface IHttpFetchError extends Error { // (undocumented) - readonly body?: any; + readonly body?: TResponseBody; // (undocumented) readonly name: string; // @deprecated (undocumented) @@ -956,7 +956,7 @@ export interface IHttpInterceptController { } // @public -export interface IHttpResponseInterceptorOverrides { +export interface IHttpResponseInterceptorOverrides { readonly body?: TResponseBody; readonly response?: Readonly; } @@ -1188,6 +1188,16 @@ export interface ResolvedSimpleSavedObject { saved_object: SimpleSavedObject; } +// @public (undocumented) +export interface ResponseErrorBody { + // (undocumented) + attributes?: Record; + // (undocumented) + message: string; + // (undocumented) + statusCode: number; +} + // Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index d3810d8932f1a..c19233809a94b 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -292,7 +292,7 @@ export class SavedObjectsClient { overwrite: options.overwrite, }; - const createRequest: Promise> = this.savedObjectsFetch(path, { + const createRequest = this.savedObjectsFetch>(path, { method: 'POST', query, body: JSON.stringify({ @@ -571,10 +571,10 @@ export class SavedObjectsClient { upsert, }; - return this.savedObjectsFetch(path, { + return this.savedObjectsFetch>(path, { method: 'PUT', body: JSON.stringify(body), - }).then((resp: SavedObject) => { + }).then((resp) => { return this.createSavedObject(resp); }); } @@ -588,11 +588,11 @@ export class SavedObjectsClient { public bulkUpdate(objects: SavedObjectsBulkUpdateObject[] = []) { const path = this.getPath(['_bulk_update']); - return this.savedObjectsFetch(path, { + return this.savedObjectsFetch<{ saved_objects: Array> }>(path, { method: 'PUT', body: JSON.stringify(objects), }).then((resp) => { - resp.saved_objects = resp.saved_objects.map((d: SavedObject) => this.createSavedObject(d)); + resp.saved_objects = resp.saved_objects.map((d) => this.createSavedObject(d)); return renameKeys< PromiseType>, SavedObjectsBatchResponse @@ -624,8 +624,8 @@ export class SavedObjectsClient { * the old kfetch error format of `{res: {status: number}}` whereas `http.fetch` * uses `{response: {status: number}}`. */ - private savedObjectsFetch(path: string, { method, query, body }: HttpFetchOptions) { - return this.http.fetch(path, { method, query, body }); + private savedObjectsFetch(path: string, { method, query, body }: HttpFetchOptions) { + return this.http.fetch(path, { method, query, body }); } } diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index de432b51c0bbf..e5657dd4663a3 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -63,6 +63,9 @@ export const PROJECTS = [ name: 'apm/ftr_e2e', disableTypeCheck: true, }), + createProject('x-pack/plugins/fleet/cypress/tsconfig.json', { + name: 'fleet/cypress', + }), createProject('x-pack/plugins/uptime/e2e/tsconfig.json', { name: 'uptime/synthetics-e2e-tests', diff --git a/src/plugins/charts/server/plugin.ts b/src/plugins/charts/server/plugin.ts index c7559b525cd22..86c90c73c38b0 100644 --- a/src/plugins/charts/server/plugin.ts +++ b/src/plugins/charts/server/plugin.ts @@ -37,7 +37,8 @@ export class ChartsServerPlugin implements Plugin { message: i18n.translate( 'charts.advancedSettings.visualization.colorMappingTextDeprecation', { - defaultMessage: 'This setting is deprecated and will not be supported as of 8.0.', + defaultMessage: + 'This setting is deprecated and will not be supported in a future version.', } ), docLinksKey: 'visualizationSettings', diff --git a/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts b/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts index 0c98d0733c647..588bac4739c53 100644 --- a/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts +++ b/src/plugins/data/public/autocomplete/providers/value_suggestion_provider.ts @@ -56,7 +56,7 @@ export const setupValueSuggestionProvider = ( } const requestSuggestions = memoize( - ( + ( index: string, field: IFieldType, query: string, @@ -68,7 +68,7 @@ export const setupValueSuggestionProvider = ( ) => { usageCollector?.trackRequest(); return core.http - .fetch(`/api/kibana/suggestions/values/${index}`, { + .fetch(`/api/kibana/suggestions/values/${index}`, { method: 'POST', body: JSON.stringify({ query, diff --git a/src/plugins/data/public/query/saved_query/saved_query_service.ts b/src/plugins/data/public/query/saved_query/saved_query_service.ts index 8ec9167a3a0c2..17b47c78c7000 100644 --- a/src/plugins/data/public/query/saved_query/saved_query_service.ts +++ b/src/plugins/data/public/query/saved_query/saved_query_service.ts @@ -12,14 +12,14 @@ import { SavedQueryAttributes } from '../../../common'; export const createSavedQueryService = (http: HttpStart) => { const createQuery = async (attributes: SavedQueryAttributes, { overwrite = false } = {}) => { - const savedQuery = await http.post('/api/saved_query/_create', { + const savedQuery = await http.post('/api/saved_query/_create', { body: JSON.stringify(attributes), }); return savedQuery; }; const updateQuery = async (id: string, attributes: SavedQueryAttributes) => { - const savedQuery = await http.put(`/api/saved_query/${id}`, { + const savedQuery = await http.put(`/api/saved_query/${id}`, { body: JSON.stringify(attributes), }); return savedQuery; @@ -27,9 +27,10 @@ export const createSavedQueryService = (http: HttpStart) => { // we have to tell the saved objects client how many to fetch, otherwise it defaults to fetching 20 per page const getAllSavedQueries = async (): Promise => { - const { savedQueries } = await http.post('/api/saved_query/_find', { - body: JSON.stringify({ perPage: 10000 }), - }); + const { savedQueries } = await http.post<{ savedQueries: SavedQuery[] }>( + '/api/saved_query/_find', + { body: JSON.stringify({ perPage: 10000 }) } + ); return savedQueries; }; @@ -39,7 +40,10 @@ export const createSavedQueryService = (http: HttpStart) => { perPage: number = 50, page: number = 1 ): Promise<{ total: number; queries: SavedQuery[] }> => { - const { total, savedQueries: queries } = await http.post('/api/saved_query/_find', { + const { total, savedQueries: queries } = await http.post<{ + savedQueries: SavedQuery[]; + total: number; + }>('/api/saved_query/_find', { body: JSON.stringify({ page, perPage, search }), }); @@ -47,15 +51,15 @@ export const createSavedQueryService = (http: HttpStart) => { }; const getSavedQuery = (id: string): Promise => { - return http.get(`/api/saved_query/${id}`); + return http.get(`/api/saved_query/${id}`); }; const deleteSavedQuery = (id: string) => { - return http.delete(`/api/saved_query/${id}`); + return http.delete<{}>(`/api/saved_query/${id}`); }; const getSavedQueryCount = async (): Promise => { - return http.get('/api/saved_query/_count'); + return http.get('/api/saved_query/_count'); }; return { diff --git a/src/plugins/data_views/public/data_views/data_views_api_client.ts b/src/plugins/data_views/public/data_views/data_views_api_client.ts index d4da9a55c25d1..90cc82f2a1ec0 100644 --- a/src/plugins/data_views/public/data_views/data_views_api_client.ts +++ b/src/plugins/data_views/public/data_views/data_views_api_client.ts @@ -19,9 +19,9 @@ export class DataViewsApiClient implements IDataViewsApiClient { this.http = http; } - private _request(url: string, query?: any) { + private _request(url: string, query?: any) { return this.http - .fetch(url, { + .fetch(url, { query, }) .catch((resp: any) => { @@ -60,7 +60,9 @@ export class DataViewsApiClient implements IDataViewsApiClient { } async hasUserIndexPattern(): Promise { - const response = await this._request(this._getUrl(['has_user_index_pattern'])); + const response = await this._request<{ result: boolean }>( + this._getUrl(['has_user_index_pattern']) + ); return response.result; } } diff --git a/src/plugins/es_ui_shared/public/request/send_request.ts b/src/plugins/es_ui_shared/public/request/send_request.ts index 11ab99cfb6978..bdc6386ad15c6 100644 --- a/src/plugins/es_ui_shared/public/request/send_request.ts +++ b/src/plugins/es_ui_shared/public/request/send_request.ts @@ -31,7 +31,7 @@ export const sendRequest = async ( ): Promise> => { try { const stringifiedBody = typeof body === 'string' ? body : JSON.stringify(body); - const response = await httpClient[method](path, { + const response = await httpClient[method]<{ data?: D } & D>(path, { body: stringifiedBody, query, asSystemRequest, diff --git a/src/plugins/home/public/application/components/sample_data_set_cards.js b/src/plugins/home/public/application/components/sample_data_set_cards.js index 7f5882f108fc8..3c5eeb4d84026 100644 --- a/src/plugins/home/public/application/components/sample_data_set_cards.js +++ b/src/plugins/home/public/application/components/sample_data_set_cards.js @@ -67,7 +67,6 @@ export class SampleDataSetCards extends React.Component { sampleDataSets: sampleDataSets.sort((a, b) => { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); }), - processingStatus: {}, }); }; @@ -82,6 +81,7 @@ export class SampleDataSetCards extends React.Component { try { await installSampleDataSet(id, targetSampleDataSet.defaultIndex); + await this.loadSampleDataSets(); // reload the list of sample data sets } catch (fetchError) { if (this._isMounted) { this.setState((prevState) => ({ diff --git a/src/plugins/home/public/index.ts b/src/plugins/home/public/index.ts index 7abaf5d19f008..009382eee0009 100644 --- a/src/plugins/home/public/index.ts +++ b/src/plugins/home/public/index.ts @@ -19,7 +19,9 @@ export type { export { FeatureCatalogueCategory } from './services'; export type { + AddDataTab, FeatureCatalogueEntry, + FeatureCatalogueRegistry, FeatureCatalogueSolution, Environment, TutorialVariables, diff --git a/src/plugins/home/server/index.ts b/src/plugins/home/server/index.ts index c75ce4e83921c..feffc2f2e003c 100644 --- a/src/plugins/home/server/index.ts +++ b/src/plugins/home/server/index.ts @@ -7,8 +7,21 @@ */ export type { HomeServerPluginSetup, HomeServerPluginStart } from './plugin'; -export type { TutorialProvider } from './services'; -export type { SampleDatasetProvider, SampleDataRegistrySetup } from './services'; +export { EmbeddableTypes, TutorialsCategory } from './services'; +export type { + AppLinkData, + ArtifactsSchema, + TutorialProvider, + TutorialSchema, + InstructionSetSchema, + InstructionsSchema, + TutorialContext, + SampleDatasetProvider, + SampleDataRegistrySetup, + SampleDatasetDashboardPanel, + SampleObject, + ScopedTutorialContextFactory, +} from './services'; import { PluginInitializerContext, PluginConfigDescriptor } from 'kibana/server'; import { HomeServerPlugin } from './plugin'; import { configSchema, ConfigSchema } from '../config'; @@ -23,10 +36,3 @@ export const config: PluginConfigDescriptor = { export const plugin = (initContext: PluginInitializerContext) => new HomeServerPlugin(initContext); export { INSTRUCTION_VARIANT } from '../common/instruction_variant'; -export { TutorialsCategory } from './services/tutorials'; -export type { - ArtifactsSchema, - TutorialSchema, - InstructionSetSchema, - InstructionsSchema, -} from './services/tutorials'; diff --git a/src/plugins/home/server/services/index.ts b/src/plugins/home/server/services/index.ts index 5674a3501f064..28086fc86d52c 100644 --- a/src/plugins/home/server/services/index.ts +++ b/src/plugins/home/server/services/index.ts @@ -9,10 +9,9 @@ // provided to other plugins as APIs // should model the plugin lifecycle -export { TutorialsRegistry } from './tutorials'; -export type { TutorialsRegistrySetup, TutorialsRegistryStart } from './tutorials'; +export { TutorialsRegistry, TutorialsCategory } from './tutorials'; -export { TutorialsCategory } from './tutorials'; +export type { TutorialsRegistrySetup, TutorialsRegistryStart } from './tutorials'; export type { InstructionSetSchema, @@ -22,12 +21,19 @@ export type { ArtifactsSchema, TutorialSchema, TutorialProvider, + TutorialContext, TutorialContextFactory, ScopedTutorialContextFactory, } from './tutorials'; -export { SampleDataRegistry } from './sample_data'; +export { EmbeddableTypes, SampleDataRegistry } from './sample_data'; -export type { SampleDataRegistrySetup, SampleDataRegistryStart } from './sample_data'; - -export type { SampleDatasetSchema, SampleDatasetProvider } from './sample_data'; +export type { + AppLinkData, + SampleDataRegistrySetup, + SampleDataRegistryStart, + SampleDatasetDashboardPanel, + SampleDatasetProvider, + SampleDatasetSchema, + SampleObject, +} from './sample_data'; diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts index cc328f3edbf71..08747f08fc923 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema, AppLinkSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; const ecommerceName = i18n.translate('home.sampleData.ecommerceSpecTitle', { defaultMessage: 'Sample eCommerce orders', @@ -18,7 +18,6 @@ const ecommerceName = i18n.translate('home.sampleData.ecommerceSpecTitle', { const ecommerceDescription = i18n.translate('home.sampleData.ecommerceSpecDescription', { defaultMessage: 'Sample data, visualizations, and dashboards for tracking eCommerce orders.', }); -const initialAppLinks = [] as AppLinkSchema[]; export const ecommerceSpecProvider = function (): SampleDatasetSchema { return { @@ -28,7 +27,6 @@ export const ecommerceSpecProvider = function (): SampleDatasetSchema { previewImagePath: '/plugins/home/assets/sample_data_resources/ecommerce/dashboard.png', darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/ecommerce/dashboard_dark.png', overviewDashboard: '722b74f0-b882-11e8-a6d9-e546fe2bba5f', - appLinks: initialAppLinks, defaultIndex: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', savedObjects: getSavedObjects(), dataIndices: [ diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts index 9559aa6b930a3..25923f247ca8b 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts @@ -140,9 +140,10 @@ export const getSavedObjects = (): SavedObject[] => [ { id: '9c6f83f0-bb4d-11e8-9c84-77068524bcab', type: 'visualization', - updated_at: '2018-10-01T15:13:03.270Z', + updated_at: '2021-10-28T15:07:24.077Z', version: '1', - migrationVersion: {}, + coreMigrationVersion: '8.0.0', + migrationVersion: { visualization: '8.0.0' }, attributes: { title: i18n.translate('home.sampleData.ecommerceSpec.salesCountMapTitle', { defaultMessage: '[eCommerce] Sales Count Map', @@ -154,10 +155,16 @@ export const getSavedObjects = (): SavedObject[] => [ version: 1, kibanaSavedObjectMeta: { searchSourceJSON: - '{"index":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","query":{"query":"","language":"kuery"},"filter":[]}', + '{"query":{"query":"","language":"kuery"},"filter":[],"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index"}', }, }, - references: [], + references: [ + { + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + }, + ], }, { attributes: { diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts index 29260b9967400..ac0987559eb79 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema, AppLinkSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; const flightsName = i18n.translate('home.sampleData.flightsSpecTitle', { defaultMessage: 'Sample flight data', @@ -18,7 +18,6 @@ const flightsName = i18n.translate('home.sampleData.flightsSpecTitle', { const flightsDescription = i18n.translate('home.sampleData.flightsSpecDescription', { defaultMessage: 'Sample data, visualizations, and dashboards for monitoring flight routes.', }); -const initialAppLinks = [] as AppLinkSchema[]; export const flightsSpecProvider = function (): SampleDatasetSchema { return { @@ -28,7 +27,6 @@ export const flightsSpecProvider = function (): SampleDatasetSchema { previewImagePath: '/plugins/home/assets/sample_data_resources/flights/dashboard.png', darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/flights/dashboard_dark.png', overviewDashboard: '7adfa750-4c81-11e8-b3d7-01146121b73d', - appLinks: initialAppLinks, defaultIndex: 'd3d7af60-4c81-11e8-b3d7-01146121b73d', savedObjects: getSavedObjects(), dataIndices: [ diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts index 43d42c2557431..77d5f868ad285 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema, AppLinkSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; const logsName = i18n.translate('home.sampleData.logsSpecTitle', { defaultMessage: 'Sample web logs', @@ -18,7 +18,6 @@ const logsName = i18n.translate('home.sampleData.logsSpecTitle', { const logsDescription = i18n.translate('home.sampleData.logsSpecDescription', { defaultMessage: 'Sample data, visualizations, and dashboards for monitoring web logs.', }); -const initialAppLinks = [] as AppLinkSchema[]; export const GLOBE_ICON_PATH = '/plugins/home/assets/sample_data_resources/logs/icon.svg'; export const logsSpecProvider = function (): SampleDatasetSchema { @@ -29,7 +28,6 @@ export const logsSpecProvider = function (): SampleDatasetSchema { previewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard.png', darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard_dark.png', overviewDashboard: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b', - appLinks: initialAppLinks, defaultIndex: '90943e30-9a47-11e8-b64d-95841ca0b247', savedObjects: getSavedObjects(), dataIndices: [ diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts index c60110176b67b..840fc6e2c175c 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts @@ -14,9 +14,10 @@ export const getSavedObjects = (): SavedObject[] => [ { id: '06cf9c40-9ee8-11e7-8711-e7a007dcef99', type: 'visualization', - updated_at: '2018-08-29T13:22:17.617Z', + updated_at: '2021-10-28T15:07:36.622Z', version: '1', - migrationVersion: {}, + coreMigrationVersion: '8.0.0', + migrationVersion: { visualization: '8.0.0' }, attributes: { title: i18n.translate('home.sampleData.logsSpec.visitorsMapTitle', { defaultMessage: '[Logs] Visitors Map', @@ -28,10 +29,16 @@ export const getSavedObjects = (): SavedObject[] => [ version: 1, kibanaSavedObjectMeta: { searchSourceJSON: - '{"index":"90943e30-9a47-11e8-b64d-95841ca0b247","filter":[],"query":{"query":"","language":"kuery"}}', + '{"filter":[],"query":{"query":"","language":"kuery"},"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index"}', }, }, - references: [], + references: [ + { + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + }, + ], }, { id: 'cb099a20-ea66-11eb-9425-113343a037e3', @@ -88,25 +95,32 @@ export const getSavedObjects = (): SavedObject[] => [ { id: '69a34b00-9ee8-11e7-8711-e7a007dcef99', type: 'visualization', - updated_at: '2018-08-29T13:24:46.136Z', + updated_at: '2021-10-28T14:38:21.435Z', version: '2', - migrationVersion: {}, + coreMigrationVersion: '8.0.0', + migrationVersion: { visualization: '8.0.0' }, attributes: { title: i18n.translate('home.sampleData.logsSpec.goalsTitle', { defaultMessage: '[Logs] Goals', }), visState: - '{"title":"[Logs] Goals","type":"gauge","params":{"type":"gauge","addTooltip":true,"addLegend":false,"gauge":{"verticalSplit":false,"extendRange":true,"percentageMode":false,"gaugeType":"Arc","gaugeStyle":"Full","backStyle":"Full","orientation":"vertical","colorSchema":"Green to Red","gaugeColorMode":"Labels","colorsRange":[{"from":0,"to":500},{"from":500,"to":1000},{"from":1000,"to":1500}],"invertColors":true,"labels":{"show":false,"color":"black"},"scale":{"show":true,"labels":false,"color":"#333"},"type":"meter","style":{"bgWidth":0.9,"width":0.9,"mask":false,"bgMask":false,"maskBars":50,"bgFill":"#eee","bgColor":false,"subText":"visitors","fontSize":60,"labelColor":true}},"isDisplayWarning":false},"aggs":[{"id":"1","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}}]}', + '{"title":"[Logs] Goals","type":"gauge","params":{"type":"gauge","addTooltip":true,"addLegend":false,"gauge":{"extendRange":true,"percentageMode":false,"gaugeType":"Arc","gaugeStyle":"Full","backStyle":"Full","orientation":"vertical","colorSchema":"Green to Red","gaugeColorMode":"Labels","colorsRange":[{"from":0,"to":500},{"from":500,"to":1000},{"from":1000,"to":1500}],"invertColors":true,"labels":{"show":false,"color":"black"},"scale":{"show":true,"labels":false,"color":"#333"},"type":"meter","style":{"bgWidth":0.9,"width":0.9,"mask":false,"bgMask":false,"maskBars":50,"bgFill":"#eee","bgColor":false,"subText":"visitors","fontSize":60,"labelColor":true},"alignment":"horizontal"},"isDisplayWarning":false},"aggs":[{"id":"1","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"clientip","customLabel":"Unique Visitors"}}]}', uiStateJSON: '{"vis":{"defaultColors":{"0 - 500":"rgb(165,0,38)","500 - 1000":"rgb(255,255,190)","1000 - 1500":"rgb(0,104,55)"},"colors":{"75 - 100":"#629E51","50 - 75":"#EAB839","0 - 50":"#E24D42","0 - 100":"#E24D42","200 - 300":"#7EB26D","500 - 1000":"#E5AC0E","0 - 500":"#E24D42","1000 - 1500":"#7EB26D"},"legendOpen":true}}', description: '', version: 1, kibanaSavedObjectMeta: { searchSourceJSON: - '{"index":"90943e30-9a47-11e8-b64d-95841ca0b247","filter":[],"query":{"query":"","language":"kuery"}}', + '{"filter":[],"query":{"query":"","language":"kuery"},"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index"}', }, }, - references: [], + references: [ + { + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + }, + ], }, { id: '7cbd2350-2223-11e8-b802-5bcf64c2cfb4', @@ -366,13 +380,13 @@ export const getSavedObjects = (): SavedObject[] => [ { id: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b', type: 'dashboard', - updated_at: '2021-07-21T21:43:43.870Z', + updated_at: '2021-10-28T15:07:36.622Z', version: '3', references: [ { id: '06cf9c40-9ee8-11e7-8711-e7a007dcef99', name: '4:panel_4', - type: 'map', + type: 'visualization', }, { id: '4eb6e500-e1c7-11e7-b6d5-4dc382ef7f5b', diff --git a/src/plugins/home/server/services/sample_data/index.ts b/src/plugins/home/server/services/sample_data/index.ts index 30384dad8951d..9af76ac3c765c 100644 --- a/src/plugins/home/server/services/sample_data/index.ts +++ b/src/plugins/home/server/services/sample_data/index.ts @@ -10,7 +10,12 @@ export { SampleDataRegistry } from './sample_data_registry'; export type { SampleDataRegistrySetup, SampleDataRegistryStart } from './sample_data_registry'; +export { EmbeddableTypes } from './lib/sample_dataset_registry_types'; + export type { - SampleDatasetSchema, + AppLinkData, + SampleDatasetDashboardPanel, SampleDatasetProvider, + SampleDatasetSchema, + SampleObject, } from './lib/sample_dataset_registry_types'; diff --git a/src/plugins/home/server/services/sample_data/lib/find_sample_objects.test.mock.ts b/src/plugins/home/server/services/sample_data/lib/find_sample_objects.test.mock.ts new file mode 100644 index 0000000000000..0d40ea23942e8 --- /dev/null +++ b/src/plugins/home/server/services/sample_data/lib/find_sample_objects.test.mock.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const mockBuildNode = jest.fn(); + +jest.mock('@kbn/es-query', () => { + return { + nodeTypes: { + function: { + buildNode: mockBuildNode, + }, + }, + }; +}); diff --git a/src/plugins/home/server/services/sample_data/lib/find_sample_objects.test.ts b/src/plugins/home/server/services/sample_data/lib/find_sample_objects.test.ts new file mode 100644 index 0000000000000..93a3e8c1d5f9c --- /dev/null +++ b/src/plugins/home/server/services/sample_data/lib/find_sample_objects.test.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mockBuildNode } from './find_sample_objects.test.mock'; + +import type { SavedObject, SavedObjectsFindResponse } from 'src/core/server'; +import { savedObjectsClientMock, loggingSystemMock } from 'src/core/server/mocks'; +import { findSampleObjects } from './find_sample_objects'; + +describe('findSampleObjects', () => { + function setup() { + const mockClient = savedObjectsClientMock.create(); + const mockLogger = loggingSystemMock.createLogger(); + return { + client: mockClient, + logger: mockLogger, + }; + } + + beforeEach(() => { + mockBuildNode.mockReset(); + }); + + it('searches for objects and returns expected results', async () => { + const { client, logger } = setup(); + const obj1 = { type: 'obj-type-1', id: 'obj-id-1' }; + const obj2 = { type: 'obj-type-2', id: 'obj-id-2' }; + const obj3 = { type: 'obj-type-3', id: 'obj-id-3' }; + const obj4 = { type: 'obj-type-3', id: 'obj-id-4' }; + const objects = [obj1, obj2, obj3, obj4]; + const params = { client, logger, objects }; + + client.bulkGet.mockResolvedValue({ + saved_objects: [ + obj1, // bulkGet success for obj1 + { ...obj2, error: { statusCode: 403 } }, // bulkGet failure - will not attempt to find by originId since the error is not 404 + { ...obj3, error: { statusCode: 404 } }, // bulkGet failure - will attempt to find by originId since the error is 404 + { ...obj4, error: { statusCode: 404 } }, // bulkGet failure - will attempt to find by originId since the error is 404 + ] as SavedObject[], + }); + client.find.mockResolvedValue({ + saved_objects: [{ type: obj4.type, id: 'obj-id-x', originId: obj4.id }], // find success for obj4 + total: 1, + } as SavedObjectsFindResponse); + const result = await findSampleObjects(params); + + expect(result).toEqual([ + { ...obj1, foundObjectId: obj1.id }, + { ...obj2, foundObjectId: undefined }, + { ...obj3, foundObjectId: undefined }, + { ...obj4, foundObjectId: 'obj-id-x' }, + ]); + expect(client.bulkGet).toHaveBeenCalledWith(objects); + expect(mockBuildNode).toHaveBeenCalledTimes(3); + expect(mockBuildNode).toHaveBeenNthCalledWith(1, 'is', `${obj3.type}.originId`, obj3.id); + expect(mockBuildNode).toHaveBeenNthCalledWith(2, 'is', `${obj4.type}.originId`, obj4.id); + expect(mockBuildNode).toHaveBeenNthCalledWith(3, 'or', expect.any(Array)); + expect(client.find).toHaveBeenCalledWith(expect.objectContaining({ type: ['obj-type-3'] })); // obj3 and obj4 have the same type; the type param is deduplicated + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it('skips find if there are no objects left to search for', async () => { + const { client, logger } = setup(); + const obj1 = { type: 'obj-type-1', id: 'obj-id-1' }; + const obj2 = { type: 'obj-type-2', id: 'obj-id-2' }; + const objects = [obj1, obj2]; + const params = { client, logger, objects }; + + client.bulkGet.mockResolvedValue({ + saved_objects: [ + obj1, // bulkGet success for obj1 + { ...obj2, error: { statusCode: 403 } }, // bulkGet failure - will not attempt to find by originId since the error is not 404 + ] as SavedObject[], + }); + const result = await findSampleObjects(params); + + expect(result).toEqual([ + { ...obj1, foundObjectId: obj1.id }, + { ...obj2, foundObjectId: undefined }, + ]); + expect(client.bulkGet).toHaveBeenCalledWith(objects); + expect(mockBuildNode).not.toHaveBeenCalled(); + expect(client.find).not.toHaveBeenCalled(); + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it('logs expected warnings', async () => { + const { client, logger } = setup(); + const obj1 = { type: 'obj-type-1', id: 'obj-id-1' }; + const objects = [obj1]; + const params = { client, logger, objects }; + + client.bulkGet.mockResolvedValue({ + saved_objects: [ + { ...obj1, error: { statusCode: 404 } }, // bulkGet failure - will attempt to find by originId since the error is 404 + ] as SavedObject[], + }); + client.find.mockResolvedValue({ + saved_objects: [ + { type: obj1.type, id: 'obj-id-x', originId: obj1.id }, // find success for obj4 + { type: obj1.type, id: 'obj-id-y', originId: obj1.id }, // find success for obj4 + ], + total: 10001, + } as SavedObjectsFindResponse); + const result = await findSampleObjects(params); + expect(result).toEqual([{ ...obj1, foundObjectId: 'obj-id-x' }]); // obj-id-y is ignored + expect(client.bulkGet).toHaveBeenCalledWith(objects); + expect(mockBuildNode).toHaveBeenCalledTimes(2); + expect(mockBuildNode).toHaveBeenNthCalledWith(1, 'is', `${obj1.type}.originId`, obj1.id); + expect(mockBuildNode).toHaveBeenNthCalledWith(2, 'or', expect.any(Array)); + expect(client.find).toHaveBeenCalledWith(expect.objectContaining({ type: ['obj-type-1'] })); + expect(logger.warn).toHaveBeenCalledTimes(2); + expect(logger.warn).toHaveBeenCalledWith( + 'findSampleObjects got 10001 results, only using the first 10000' + ); + expect(logger.warn).toHaveBeenCalledWith( + 'Found two sample objects with the same origin "obj-id-1" (previously found "obj-id-x", ignoring "obj-id-y")' + ); + }); +}); diff --git a/src/plugins/home/server/services/sample_data/lib/find_sample_objects.ts b/src/plugins/home/server/services/sample_data/lib/find_sample_objects.ts new file mode 100644 index 0000000000000..904470acc2c84 --- /dev/null +++ b/src/plugins/home/server/services/sample_data/lib/find_sample_objects.ts @@ -0,0 +1,104 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as esKuery from '@kbn/es-query'; +import type { Logger, SavedObjectsClientContract } from 'src/core/server'; + +const MAX_OBJECTS_TO_FIND = 10000; // we only expect up to a few dozen, search for 10k to be safe; anything over this is ignored + +export interface FindSampleObjectsParams { + client: SavedObjectsClientContract; + logger: Logger; + objects: SampleObject[]; +} + +export interface SampleObject { + type: string; + id: string; +} + +export interface FindSampleObjectsResponseObject { + type: string; + id: string; + /** Contains a string if this sample data object was found, or undefined if it was not. */ + foundObjectId: string | undefined; +} + +/** + * Given an array of objects in a sample dataset, this function attempts to find if those objects exist in the current space. + * It attempts to find objects with an origin of the sample data (e.g., matching `id` or `originId`). + */ +export async function findSampleObjects({ client, logger, objects }: FindSampleObjectsParams) { + const bulkGetResponse = await client.bulkGet(objects); + + let resultsMap = new Map(); + const objectsToFind: SampleObject[] = []; + objects.forEach((object, i) => { + const bulkGetResult = bulkGetResponse.saved_objects[i]; + if (!bulkGetResult.error) { + const { type, id } = object; + const key = getObjKey(type, id); + resultsMap.set(key, id); + } else if (bulkGetResult.error.statusCode === 404) { + objectsToFind.push(object); + } + }); + + if (objectsToFind.length > 0) { + const options = { + type: getUniqueTypes(objectsToFind), + filter: createKueryFilter(objectsToFind), + fields: ['title'], // we don't want to return all source fields, so we have to specify at least one source field + perPage: MAX_OBJECTS_TO_FIND, + }; + const findResponse = await client.find(options); + if (findResponse.total > MAX_OBJECTS_TO_FIND) { + // As of this writing, it is not possible to encounter this scenario when using Kibana import or copy-to-space, because at most one + // object can exist in a given space. However, as of today, when objects are shareable you _could_ get Kibana into a state where + // multiple objects of the same origin exist in the same space. + // #116677 describes solutions to fully mitigate this edge case in the future. + logger.warn( + `findSampleObjects got ${findResponse.total} results, only using the first ${MAX_OBJECTS_TO_FIND}` + ); + } + resultsMap = findResponse.saved_objects.reduce((acc, { type, id, originId }) => { + const key = getObjKey(type, originId!); + const existing = acc.get(key); + if (existing) { + // As of this writing, it is not possible to encounter this scenario when using Kibana import or copy-to-space, because at most one + // object can exist in a given space. However, as of today, when objects are shareable you _could_ get Kibana into a state where + // multiple objects of the same origin exist in the same space. + // #116677 describes solutions to fully mitigate this edge case in the future. + logger.warn( + `Found two sample objects with the same origin "${originId}" (previously found "${existing}", ignoring "${id}")` + ); + return acc; + } + return acc.set(key, id); + }, resultsMap); + } + + return objects.map(({ type, id }) => { + const key = getObjKey(type, id); + return { type, id, foundObjectId: resultsMap.get(key) }; + }); +} + +function getUniqueTypes(objects: SampleObject[]) { + return [...new Set(objects.map(({ type }) => type))]; +} + +function createKueryFilter(objects: SampleObject[]) { + const { buildNode } = esKuery.nodeTypes.function; + const kueryNodes = objects.map(({ type, id }) => buildNode('is', `${type}.originId`, id)); // the repository converts this node into "and (type is ..., originId is ...)" + return buildNode('or', kueryNodes); +} + +function getObjKey(type: string, id: string) { + return `${type}:${id}`; +} diff --git a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts index 09af7728f74d2..8d26d08460b5b 100644 --- a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts +++ b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts @@ -7,7 +7,7 @@ */ import type { SampleDatasetSchema } from './sample_dataset_schema'; -export type { SampleDatasetSchema, AppLinkSchema, DataIndexSchema } from './sample_dataset_schema'; +export type { SampleDatasetSchema, DataIndexSchema } from './sample_dataset_schema'; export enum DatasetStatusTypes { NOT_INSTALLED = 'not_installed', @@ -28,3 +28,34 @@ export enum EmbeddableTypes { VISUALIZE_EMBEDDABLE_TYPE = 'visualization', } export type SampleDatasetProvider = () => SampleDatasetSchema; + +/** This type is used to identify an object in a sample dataset. */ +export interface SampleObject { + /** The type of the sample object. */ + type: string; + /** The ID of the sample object. */ + id: string; +} + +/** + * This type is used by consumers to register a new app link for a sample dataset. + */ +export interface AppLinkData { + /** + * The sample object that is used for this app link's path; if the path does not use an object ID, set this to null. + */ + sampleObject: SampleObject | null; + /** + * Function that returns the path for this app link. Note that the `objectId` can be different than the given `sampleObject.id`, depending + * on how the sample data was installed. If the `sampleObject` is null, the `objectId` argument will be an empty string. + */ + getPath: (objectId: string) => string; + /** + * The label for this app link. + */ + label: string; + /** + * The icon for this app link. + */ + icon: string; +} diff --git a/src/plugins/home/server/services/sample_data/lib/sample_dataset_schema.ts b/src/plugins/home/server/services/sample_data/lib/sample_dataset_schema.ts index 87b042aebcc1f..66f69abca3f18 100644 --- a/src/plugins/home/server/services/sample_data/lib/sample_dataset_schema.ts +++ b/src/plugins/home/server/services/sample_data/lib/sample_dataset_schema.ts @@ -48,13 +48,6 @@ const dataIndexSchema = schema.object({ export type DataIndexSchema = TypeOf; -const appLinkSchema = schema.object({ - path: schema.string(), - label: schema.string(), - icon: schema.string(), -}); -export type AppLinkSchema = TypeOf; - export const sampleDataSchema = schema.object({ id: schema.string({ validate(value: string) { @@ -71,7 +64,6 @@ export const sampleDataSchema = schema.object({ // saved object id of main dashboard for sample data set overviewDashboard: schema.string(), - appLinks: schema.arrayOf(appLinkSchema, { defaultValue: [] }), // saved object id of default index-pattern for sample data set defaultIndex: schema.string(), diff --git a/src/plugins/home/server/services/sample_data/lib/utils.ts b/src/plugins/home/server/services/sample_data/lib/utils.ts new file mode 100644 index 0000000000000..153fe6923583d --- /dev/null +++ b/src/plugins/home/server/services/sample_data/lib/utils.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SampleObject } from './sample_dataset_registry_types'; + +export function getUniqueObjectTypes(objects: SampleObject[]) { + return [...new Set(objects.map(({ type }) => type))]; +} diff --git a/src/plugins/home/server/services/sample_data/routes/install.ts b/src/plugins/home/server/services/sample_data/routes/install.ts index d0457f0a6d301..17d35c6cb4b7e 100644 --- a/src/plugins/home/server/services/sample_data/routes/install.ts +++ b/src/plugins/home/server/services/sample_data/routes/install.ts @@ -6,13 +6,9 @@ * Side Public License, v 1. */ +import { Readable } from 'stream'; import { schema } from '@kbn/config-schema'; -import type { - IRouter, - Logger, - IScopedClusterClient, - SavedObjectsBulkCreateObject, -} from 'src/core/server'; +import { IRouter, Logger, IScopedClusterClient } from 'src/core/server'; import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; import { createIndexName } from '../lib/create_index_name'; import { @@ -22,6 +18,8 @@ import { } from '../lib/translate_timestamp'; import { loadData } from '../lib/load_data'; import { SampleDataUsageTracker } from '../usage/usage'; +import { getSavedObjectsClient } from './utils'; +import { getUniqueObjectTypes } from '../lib/utils'; const insertDataIntoIndex = ( dataIndexConfig: any, @@ -143,35 +141,31 @@ export function createInstallRoute( } } - let createResults; - try { - const { getClient, typeRegistry } = context.core.savedObjects; - - const includedHiddenTypes = sampleDataset.savedObjects - .map((object) => object.type) - .filter((supportedType) => typeRegistry.isHidden(supportedType)); + const { getImporter } = context.core.savedObjects; + const objectTypes = getUniqueObjectTypes(sampleDataset.savedObjects); + const savedObjectsClient = getSavedObjectsClient(context, objectTypes); + const importer = getImporter(savedObjectsClient); - const client = getClient({ includedHiddenTypes }); + const savedObjects = sampleDataset.savedObjects.map(({ version, ...obj }) => obj); + const readStream = Readable.from(savedObjects); - const savedObjects = sampleDataset.savedObjects as SavedObjectsBulkCreateObject[]; - createResults = await client.bulkCreate( - savedObjects.map(({ version, ...savedObject }) => savedObject), - { overwrite: true } - ); + try { + const { errors = [] } = await importer.import({ + readStream, + overwrite: true, + createNewCopies: false, + }); + if (errors.length > 0) { + const errMsg = `sample_data install errors while loading saved objects. Errors: ${JSON.stringify( + errors.map(({ type, id, error }) => ({ type, id, error })) // discard other fields + )}`; + logger.warn(errMsg); + return res.customError({ body: errMsg, statusCode: 500 }); + } } catch (err) { - const errMsg = `bulkCreate failed, error: ${err.message}`; + const errMsg = `import failed, error: ${err.message}`; throw new Error(errMsg); } - const errors = createResults.saved_objects.filter((savedObjectCreateResult) => { - return Boolean(savedObjectCreateResult.error); - }); - if (errors.length > 0) { - const errMsg = `sample_data install errors while loading saved objects. Errors: ${JSON.stringify( - errors - )}`; - logger.warn(errMsg); - return res.customError({ body: errMsg, statusCode: 403 }); - } usageTracker.addInstall(params.id); // FINALLY diff --git a/src/plugins/home/server/services/sample_data/routes/list.ts b/src/plugins/home/server/services/sample_data/routes/list.ts index e3e213196889c..a7ca32341f1f5 100644 --- a/src/plugins/home/server/services/sample_data/routes/list.ts +++ b/src/plugins/home/server/services/sample_data/routes/list.ts @@ -6,75 +6,122 @@ * Side Public License, v 1. */ -import { IRouter } from 'src/core/server'; -import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; +import type { IRouter, Logger, RequestHandlerContext } from 'src/core/server'; +import type { AppLinkData, SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; import { createIndexName } from '../lib/create_index_name'; +import type { FindSampleObjectsResponseObject } from '../lib/find_sample_objects'; +import { findSampleObjects } from '../lib/find_sample_objects'; +import { getUniqueObjectTypes } from '../lib/utils'; +import { getSavedObjectsClient } from './utils'; const NOT_INSTALLED = 'not_installed'; const INSTALLED = 'installed'; const UNKNOWN = 'unknown'; -export const createListRoute = (router: IRouter, sampleDatasets: SampleDatasetSchema[]) => { - router.get({ path: '/api/sample_data', validate: false }, async (context, req, res) => { - const registeredSampleDatasets = sampleDatasets.map((sampleDataset) => { - return { - id: sampleDataset.id, - name: sampleDataset.name, - description: sampleDataset.description, - previewImagePath: sampleDataset.previewImagePath, - darkPreviewImagePath: sampleDataset.darkPreviewImagePath, - overviewDashboard: sampleDataset.overviewDashboard, - appLinks: sampleDataset.appLinks, - defaultIndex: sampleDataset.defaultIndex, - dataIndices: sampleDataset.dataIndices.map(({ id }) => ({ id })), - status: sampleDataset.status, - statusMsg: sampleDataset.statusMsg, - }; - }); - const isInstalledPromises = registeredSampleDatasets.map(async (sampleDataset) => { - for (let i = 0; i < sampleDataset.dataIndices.length; i++) { - const dataIndexConfig = sampleDataset.dataIndices[i]; - const index = createIndexName(sampleDataset.id, dataIndexConfig.id); - try { - const { body: indexExists } = - await context.core.elasticsearch.client.asCurrentUser.indices.exists({ - index, - }); - if (!indexExists) { - sampleDataset.status = NOT_INSTALLED; - return; - } +export const createListRoute = ( + router: IRouter, + sampleDatasets: SampleDatasetSchema[], + appLinksMap: Map, + logger: Logger +) => { + router.get({ path: '/api/sample_data', validate: false }, async (context, _req, res) => { + const allExistingObjects = await findExistingSampleObjects(context, logger, sampleDatasets); - const { body: count } = await context.core.elasticsearch.client.asCurrentUser.count({ - index, - }); - if (count.count === 0) { - sampleDataset.status = NOT_INSTALLED; - return; - } - } catch (err) { - sampleDataset.status = UNKNOWN; - sampleDataset.statusMsg = err.message; - return; - } - } - try { - await context.core.savedObjects.client.get('dashboard', sampleDataset.overviewDashboard); - } catch (err) { - if (context.core.savedObjects.client.errors.isNotFoundError(err)) { - sampleDataset.status = NOT_INSTALLED; - return; - } + const registeredSampleDatasets = await Promise.all( + sampleDatasets.map(async (sampleDataset) => { + const existingObjects = allExistingObjects.get(sampleDataset.id)!; + const findObjectId = (type: string, id: string) => + existingObjects.find((object) => object.type === type && object.id === id) + ?.foundObjectId ?? id; - sampleDataset.status = UNKNOWN; - sampleDataset.statusMsg = err.message; - return; - } + const appLinks = (appLinksMap.get(sampleDataset.id) ?? []).map((data) => { + const { sampleObject, getPath, label, icon } = data; + if (sampleObject === null) { + return { path: getPath(''), label, icon }; + } + const objectId = findObjectId(sampleObject.type, sampleObject.id); + return { path: getPath(objectId), label, icon }; + }); + const sampleDataStatus = await getSampleDatasetStatus( + context, + allExistingObjects, + sampleDataset + ); - sampleDataset.status = INSTALLED; - }); + return { + id: sampleDataset.id, + name: sampleDataset.name, + description: sampleDataset.description, + previewImagePath: sampleDataset.previewImagePath, + darkPreviewImagePath: sampleDataset.darkPreviewImagePath, + overviewDashboard: findObjectId('dashboard', sampleDataset.overviewDashboard), + appLinks, + defaultIndex: findObjectId('index-pattern', sampleDataset.defaultIndex), + dataIndices: sampleDataset.dataIndices.map(({ id }) => ({ id })), + ...sampleDataStatus, + }; + }) + ); - await Promise.all(isInstalledPromises); return res.ok({ body: registeredSampleDatasets }); }); }; + +type ExistingSampleObjects = Map; +async function findExistingSampleObjects( + context: RequestHandlerContext, + logger: Logger, + sampleDatasets: SampleDatasetSchema[] +) { + const objects = sampleDatasets + .map(({ savedObjects }) => savedObjects.map(({ type, id }) => ({ type, id }))) + .flat(); + const objectTypes = getUniqueObjectTypes(objects); + const client = getSavedObjectsClient(context, objectTypes); + const findSampleObjectsResult = await findSampleObjects({ client, logger, objects }); + + let objectCounter = 0; + return sampleDatasets.reduce((acc, { id, savedObjects }) => { + const datasetResults = savedObjects.map(() => findSampleObjectsResult[objectCounter++]); + return acc.set(id, datasetResults); + }, new Map()); +} + +// TODO: introduce PARTIALLY_INSTALLED status (#116677) +async function getSampleDatasetStatus( + context: RequestHandlerContext, + existingSampleObjects: ExistingSampleObjects, + sampleDataset: SampleDatasetSchema +): Promise<{ status: string; statusMsg?: string }> { + const dashboard = existingSampleObjects + .get(sampleDataset.id)! + .find(({ type, id }) => type === 'dashboard' && id === sampleDataset.overviewDashboard); + if (!dashboard?.foundObjectId) { + return { status: NOT_INSTALLED }; + } + + for (let i = 0; i < sampleDataset.dataIndices.length; i++) { + const dataIndexConfig = sampleDataset.dataIndices[i]; + const index = createIndexName(sampleDataset.id, dataIndexConfig.id); + try { + const { body: indexExists } = + await context.core.elasticsearch.client.asCurrentUser.indices.exists({ + index, + }); + if (!indexExists) { + return { status: NOT_INSTALLED }; + } + + const { body: count } = await context.core.elasticsearch.client.asCurrentUser.count({ + index, + }); + if (count.count === 0) { + return { status: NOT_INSTALLED }; + } + } catch (err) { + return { status: UNKNOWN, statusMsg: err.message }; + } + } + + return { status: INSTALLED }; +} diff --git a/src/plugins/home/server/services/sample_data/routes/uninstall.ts b/src/plugins/home/server/services/sample_data/routes/uninstall.ts index 3108c06492dd8..b0e8e6f102f1e 100644 --- a/src/plugins/home/server/services/sample_data/routes/uninstall.ts +++ b/src/plugins/home/server/services/sample_data/routes/uninstall.ts @@ -6,16 +6,20 @@ * Side Public License, v 1. */ +import { isBoom } from '@hapi/boom'; import { schema } from '@kbn/config-schema'; -import _ from 'lodash'; -import { IRouter } from 'src/core/server'; +import type { IRouter, Logger } from 'src/core/server'; import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; import { createIndexName } from '../lib/create_index_name'; import { SampleDataUsageTracker } from '../usage/usage'; +import { findSampleObjects } from '../lib/find_sample_objects'; +import { getUniqueObjectTypes } from '../lib/utils'; +import { getSavedObjectsClient } from './utils'; export function createUninstallRoute( router: IRouter, sampleDatasets: SampleDatasetSchema[], + logger: Logger, usageTracker: SampleDataUsageTracker ): void { router.delete( @@ -25,16 +29,7 @@ export function createUninstallRoute( params: schema.object({ id: schema.string() }), }, }, - async ( - { - core: { - elasticsearch: { client: esClient }, - savedObjects: { getClient: getSavedObjectsClient, typeRegistry }, - }, - }, - request, - response - ) => { + async (context, request, response) => { const sampleDataset = sampleDatasets.find(({ id }) => id === request.params.id); if (!sampleDataset) { @@ -46,41 +41,46 @@ export function createUninstallRoute( const index = createIndexName(sampleDataset.id, dataIndexConfig.id); try { - await esClient.asCurrentUser.indices.delete({ - index, - }); + // TODO: don't delete the index if sample data exists in other spaces (#116677) + await context.core.elasticsearch.client.asCurrentUser.indices.delete({ index }); } catch (err) { - return response.customError({ - statusCode: err.status, - body: { - message: `Unable to delete sample data index "${index}", error: ${err.message}`, - }, - }); + // if the index doesn't exist, ignore the error and proceed + if (err.body.status !== 404) { + return response.customError({ + statusCode: err.body.status, + body: { + message: `Unable to delete sample data index "${index}", error: ${err.body.error.type}`, + }, + }); + } } } - const includedHiddenTypes = sampleDataset.savedObjects - .map((object) => object.type) - .filter((supportedType) => typeRegistry.isHidden(supportedType)); - - const savedObjectsClient = getSavedObjectsClient({ includedHiddenTypes }); + const objects = sampleDataset.savedObjects.map(({ type, id }) => ({ type, id })); + const objectTypes = getUniqueObjectTypes(objects); + const client = getSavedObjectsClient(context, objectTypes); + const findSampleObjectsResult = await findSampleObjects({ client, logger, objects }); - const deletePromises = sampleDataset.savedObjects.map(({ type, id }) => - savedObjectsClient.delete(type, id) + const objectsToDelete = findSampleObjectsResult.filter(({ foundObjectId }) => foundObjectId); + const deletePromises = objectsToDelete.map(({ type, foundObjectId }) => + client.delete(type, foundObjectId!).catch((err) => { + // if the object doesn't exist, ignore the error and proceed + if (isBoom(err) && err.output.statusCode === 404) { + return; + } + throw err; + }) ); try { await Promise.all(deletePromises); } catch (err) { - // ignore 404s since users could have deleted some of the saved objects via the UI - if (_.get(err, 'output.statusCode') !== 404) { - return response.customError({ - statusCode: err.status, - body: { - message: `Unable to delete sample dataset saved objects, error: ${err.message}`, - }, - }); - } + return response.customError({ + statusCode: err.body.status, + body: { + message: `Unable to delete sample dataset saved objects, error: ${err.body.error.type}`, + }, + }); } // track the usage operation in a non-blocking way diff --git a/src/plugins/home/server/services/sample_data/routes/utils.ts b/src/plugins/home/server/services/sample_data/routes/utils.ts new file mode 100644 index 0000000000000..6bab00895440a --- /dev/null +++ b/src/plugins/home/server/services/sample_data/routes/utils.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { RequestHandlerContext } from 'src/core/server'; + +export function getSavedObjectsClient(context: RequestHandlerContext, objectTypes: string[]) { + const { getClient, typeRegistry } = context.core.savedObjects; + const includedHiddenTypes = objectTypes.filter((supportedType) => + typeRegistry.isHidden(supportedType) + ); + return getClient({ includedHiddenTypes }); +} diff --git a/src/plugins/home/server/services/sample_data/sample_data_registry.ts b/src/plugins/home/server/services/sample_data/sample_data_registry.ts index ef453592d9790..f8dd12746832b 100644 --- a/src/plugins/home/server/services/sample_data/sample_data_registry.ts +++ b/src/plugins/home/server/services/sample_data/sample_data_registry.ts @@ -11,8 +11,8 @@ import { SavedObject } from 'src/core/public'; import { SampleDatasetProvider, SampleDatasetSchema, - AppLinkSchema, SampleDatasetDashboardPanel, + AppLinkData, } from './lib/sample_dataset_registry_types'; import { sampleDataSchema } from './lib/sample_dataset_schema'; @@ -27,6 +27,7 @@ import { registerSampleDatasetWithIntegration } from './lib/register_with_integr export class SampleDataRegistry { constructor(private readonly initContext: PluginInitializerContext) {} private readonly sampleDatasets: SampleDatasetSchema[] = []; + private readonly appLinksMap = new Map(); private registerSampleDataSet(specProvider: SampleDatasetProvider) { let value: SampleDatasetSchema; @@ -69,14 +70,10 @@ export class SampleDataRegistry { this.initContext.logger.get('sample_data', 'usage') ); const router = core.http.createRouter(); - createListRoute(router, this.sampleDatasets); - createInstallRoute( - router, - this.sampleDatasets, - this.initContext.logger.get('sampleData'), - usageTracker - ); - createUninstallRoute(router, this.sampleDatasets, usageTracker); + const logger = this.initContext.logger.get('sampleData'); + createListRoute(router, this.sampleDatasets, this.appLinksMap, logger); + createInstallRoute(router, this.sampleDatasets, logger, usageTracker); + createUninstallRoute(router, this.sampleDatasets, logger, usageTracker); this.registerSampleDataSet(flightsSpecProvider); this.registerSampleDataSet(logsSpecProvider); @@ -100,7 +97,7 @@ export class SampleDataRegistry { sampleDataset.savedObjects = sampleDataset.savedObjects.concat(savedObjects); }, - addAppLinksToSampleDataset: (id: string, appLinks: AppLinkSchema[]) => { + addAppLinksToSampleDataset: (id: string, appLinks: AppLinkData[]) => { const sampleDataset = this.sampleDatasets.find((dataset) => { return dataset.id === id; }); @@ -109,9 +106,8 @@ export class SampleDataRegistry { throw new Error(`Unable to find sample dataset with id: ${id}`); } - sampleDataset.appLinks = sampleDataset.appLinks - ? sampleDataset.appLinks.concat(appLinks) - : []; + const existingAppLinks = this.appLinksMap.get(id) ?? []; + this.appLinksMap.set(id, [...existingAppLinks, ...appLinks]); }, replacePanelInSampleDatasetDashboard: ({ diff --git a/src/plugins/home/server/services/tutorials/index.ts b/src/plugins/home/server/services/tutorials/index.ts index f745d0190efd5..36e780b238296 100644 --- a/src/plugins/home/server/services/tutorials/index.ts +++ b/src/plugins/home/server/services/tutorials/index.ts @@ -19,6 +19,7 @@ export type { ArtifactsSchema, TutorialSchema, TutorialProvider, + TutorialContext, TutorialContextFactory, ScopedTutorialContextFactory, } from './lib/tutorials_registry_types'; diff --git a/src/plugins/index_pattern_editor/public/components/index_pattern_editor_flyout_content.tsx b/src/plugins/index_pattern_editor/public/components/index_pattern_editor_flyout_content.tsx index bbe729d4684b7..5a6ad9aafdbdd 100644 --- a/src/plugins/index_pattern_editor/public/components/index_pattern_editor_flyout_content.tsx +++ b/src/plugins/index_pattern_editor/public/components/index_pattern_editor_flyout_content.tsx @@ -167,7 +167,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ useEffect(() => { const getRollups = async () => { try { - const response = await http.get('/api/rollup/indices'); + const response = await http.get('/api/rollup/indices'); if (response) { setRollupIndicesCapabilities(response); } diff --git a/src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts b/src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts index 8c710e8052348..5bff350b332a0 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts +++ b/src/plugins/index_pattern_management/public/components/field_editor/lib/validate_script.ts @@ -18,7 +18,10 @@ export const executeScript = async ({ http, }: ExecuteScriptParams): Promise => { return http - .post('/internal/index-pattern-management/preview_scripted_field', { + .post<{ + statusCode: ExecuteScriptResult['status']; + body: { hits: ExecuteScriptResult['hits'] }; + }>('/internal/index-pattern-management/preview_scripted_field', { body: JSON.stringify({ index: indexPatternTitle, name, diff --git a/src/plugins/index_pattern_management/public/scripting_languages/index.ts b/src/plugins/index_pattern_management/public/scripting_languages/index.ts index 46bb0a359ae89..f01802786ea57 100644 --- a/src/plugins/index_pattern_management/public/scripting_languages/index.ts +++ b/src/plugins/index_pattern_management/public/scripting_languages/index.ts @@ -21,12 +21,12 @@ export const getEnabledScriptingLanguages = ( http: HttpStart, toasts: NotificationsStart['toasts'] ) => - http.get('/api/kibana/scripts/languages').catch(() => { + http.get('/api/kibana/scripts/languages').catch(() => { toasts.addDanger( i18n.translate('indexPatternManagement.scriptingLanguages.errorFetchingToastDescription', { defaultMessage: 'Error getting available scripting languages from Elasticsearch', }) ); - return []; + return [] as estypes.ScriptLanguage[]; }); diff --git a/src/plugins/interactive_setup/public/progress_indicator.tsx b/src/plugins/interactive_setup/public/progress_indicator.tsx index 73f757246af53..21bdcd2f78688 100644 --- a/src/plugins/interactive_setup/public/progress_indicator.tsx +++ b/src/plugins/interactive_setup/public/progress_indicator.tsx @@ -51,7 +51,7 @@ export const ProgressIndicator: FunctionComponent = ({ o } catch (error) { const { response, body = {} } = error as IHttpFetchError; isAvailable = response ? response.status < 500 : undefined; - isPastPreboot = isKibanaPastPreboot(response, body); + isPastPreboot = isKibanaPastPreboot(response, body as StatusResponse); } return isAvailable === true && isPastPreboot ? 'complete' diff --git a/src/plugins/interactive_setup/public/submit_error_callout.tsx b/src/plugins/interactive_setup/public/submit_error_callout.tsx index 728bbeff559de..9622d08d48b86 100644 --- a/src/plugins/interactive_setup/public/submit_error_callout.tsx +++ b/src/plugins/interactive_setup/public/submit_error_callout.tsx @@ -11,7 +11,7 @@ import type { FunctionComponent } from 'react'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import type { IHttpFetchError } from 'kibana/public'; +import type { IHttpFetchError, ResponseErrorBody } from 'kibana/public'; import { ERROR_CONFIGURE_FAILURE, @@ -29,7 +29,7 @@ export interface SubmitErrorCalloutProps { } export const SubmitErrorCallout: FunctionComponent = (props) => { - const error = props.error as IHttpFetchError; + const error = props.error as IHttpFetchError; if ( error.body?.statusCode === 404 || diff --git a/src/plugins/interactive_setup/public/verification_code_form.tsx b/src/plugins/interactive_setup/public/verification_code_form.tsx index 0f2676a80364e..9ff86c63aca7f 100644 --- a/src/plugins/interactive_setup/public/verification_code_form.tsx +++ b/src/plugins/interactive_setup/public/verification_code_form.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import type { IHttpFetchError } from 'kibana/public'; +import type { IHttpFetchError, ResponseErrorBody } from 'kibana/public'; import { VERIFICATION_CODE_LENGTH } from '../common'; import { SingleCharsField } from './single_chars_field'; @@ -71,7 +71,7 @@ export const VerificationCodeForm: FunctionComponent }); } catch (error) { if ((error as IHttpFetchError).response?.status === 403) { - form.setError('code', (error as IHttpFetchError).body?.message); + form.setError('code', (error as IHttpFetchError).body?.message || ''); return; } else { throw error; diff --git a/src/plugins/share/public/index.ts b/src/plugins/share/public/index.ts index 73b685e2cab5a..75f541dd5ae3d 100644 --- a/src/plugins/share/public/index.ts +++ b/src/plugins/share/public/index.ts @@ -37,7 +37,6 @@ export { useLocatorUrl } from '../common/url_service/locators/use_locator_url'; import { SharePlugin } from './plugin'; -export { KibanaURL } from './kibana_url'; export { downloadMultipleAs, downloadFileAs } from './lib/download_as'; export type { DownloadableContent } from './lib/download_as'; diff --git a/src/plugins/share/public/lib/url_shortener.ts b/src/plugins/share/public/lib/url_shortener.ts index 6d0b7ae91e341..9a0ae9cfb0bad 100644 --- a/src/plugins/share/public/lib/url_shortener.ts +++ b/src/plugins/share/public/lib/url_shortener.ts @@ -29,7 +29,7 @@ export async function shortenUrl( params: { url: relativeUrl }, }); - const resp = await post('/api/short_url', { + const resp = await post<{ id: string }>('/api/short_url', { body, }); diff --git a/src/plugins/usage_collection/public/services/create_reporter.ts b/src/plugins/usage_collection/public/services/create_reporter.ts index e5006646fe368..fb187d1c0c486 100644 --- a/src/plugins/usage_collection/public/services/create_reporter.ts +++ b/src/plugins/usage_collection/public/services/create_reporter.ts @@ -22,7 +22,8 @@ export function createReporter(config: AnalyicsReporterConfig): Reporter { debug, storage: localStorage, async http(report) { - const response = await fetch.post('/api/ui_counters/_report', { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const response = await fetch.post('/api/ui_counters/_report', { body: JSON.stringify({ report }), asSystemRequest: true, }); diff --git a/src/plugins/vis_types/timelion/public/components/timelion_expression_input.tsx b/src/plugins/vis_types/timelion/public/components/timelion_expression_input.tsx index dd949f57bce28..88e6d255733ed 100644 --- a/src/plugins/vis_types/timelion/public/components/timelion_expression_input.tsx +++ b/src/plugins/vis_types/timelion/public/components/timelion_expression_input.tsx @@ -25,7 +25,7 @@ interface TimelionExpressionInputProps { } function TimelionExpressionInput({ value, setValue }: TimelionExpressionInputProps) { - const functionList = useRef([]); + const functionList = useRef([]); const kibana = useKibana(); const argValueSuggestions = useMemo(getArgValueSuggestions, []); @@ -84,7 +84,7 @@ function TimelionExpressionInput({ value, setValue }: TimelionExpressionInputPro useEffect(() => { if (kibana.services.http) { - kibana.services.http.get('../api/timelion/functions').then((data) => { + kibana.services.http.get('../api/timelion/functions').then((data) => { functionList.current = data; }); } diff --git a/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx b/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx index c74c0f2ee6c2d..633f15a9824ea 100644 --- a/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx +++ b/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx @@ -45,8 +45,10 @@ export const getTimelionVisRenderer: ( timeFieldName: '*', filters: [ { - range: { - '*': rangeFilterParams, + query: { + range: { + '*': rangeFilterParams, + }, }, }, ], diff --git a/src/plugins/vis_types/timelion/server/ui_settings.ts b/src/plugins/vis_types/timelion/server/ui_settings.ts index 1d8dc997a3f6a..40907b0271487 100644 --- a/src/plugins/vis_types/timelion/server/ui_settings.ts +++ b/src/plugins/vis_types/timelion/server/ui_settings.ts @@ -30,7 +30,8 @@ export function getUiSettings( }), deprecation: { message: i18n.translate('timelion.uiSettings.legacyChartsLibraryDeprication', { - defaultMessage: 'This setting is deprecated and will not be supported as of 8.0.', + defaultMessage: + 'This setting is deprecated and will not be supported in a future version.', }), docLinksKey: 'timelionSettings', }, diff --git a/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx b/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx index 886b569671a6b..0916892cfda46 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx @@ -81,10 +81,12 @@ function TimeseriesVisualization({ timeFieldName: '*', filters: [ { - range: { - '*': { - gte, - lte, + query: { + range: { + '*': { + gte, + lte, + }, }, }, }, diff --git a/test/api_integration/apis/home/sample_data.ts b/test/api_integration/apis/home/sample_data.ts index 2525cbe330044..55fee03186cbb 100644 --- a/test/api_integration/apis/home/sample_data.ts +++ b/test/api_integration/apis/home/sample_data.ts @@ -7,6 +7,7 @@ */ import expect from '@kbn/expect'; +import type { Response } from 'superagent'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { @@ -15,81 +16,142 @@ export default function ({ getService }: FtrProviderContext) { const es = getService('es'); const MILLISECOND_IN_WEEK = 1000 * 60 * 60 * 24 * 7; + const SPACES = ['default', 'other']; + const FLIGHTS_OVERVIEW_DASHBOARD_ID = '7adfa750-4c81-11e8-b3d7-01146121b73d'; // default ID of the flights overview dashboard + const FLIGHTS_CANVAS_APPLINK_PATH = + '/app/canvas#/workpad/workpad-a474e74b-aedc-47c3-894a-db77e62c41e0'; // includes default ID of the flights canvas applink path describe('sample data apis', () => { before(async () => { await esArchiver.emptyKibanaIndex(); }); - describe('list', () => { - it('should return list of sample data sets with installed status', async () => { - const resp = await supertest.get(`/api/sample_data`).set('kbn-xsrf', 'kibana').expect(200); - - expect(resp.body).to.be.an('array'); - expect(resp.body.length).to.be.above(0); - expect(resp.body[0].status).to.be('not_installed'); - }); + after(async () => { + await esArchiver.emptyKibanaIndex(); }); - describe('install', () => { - it('should return 404 if id does not match any sample data sets', async () => { - await supertest.post(`/api/sample_data/xxxx`).set('kbn-xsrf', 'kibana').expect(404); - }); + for (const space of SPACES) { + const apiPath = `/s/${space}/api/sample_data`; - it('should return 200 if success', async () => { - const resp = await supertest - .post(`/api/sample_data/flights`) - .set('kbn-xsrf', 'kibana') - .expect(200); + describe(`list in the ${space} space (before install)`, () => { + it('should return list of sample data sets with installed status', async () => { + const resp = await supertest.get(apiPath).set('kbn-xsrf', 'kibana').expect(200); - expect(resp.body).to.eql({ - elasticsearchIndicesCreated: { kibana_sample_data_flights: 13059 }, - kibanaSavedObjectsLoaded: 11, + const flightsData = findFlightsData(resp); + expect(flightsData.status).to.be('not_installed'); + // Check and make sure the sample dataset reflects the default object IDs, because no sample data objects exist. + // Instead of checking each object ID, we check the dashboard and canvas app link as representatives. + expect(flightsData.overviewDashboard).to.be(FLIGHTS_OVERVIEW_DASHBOARD_ID); + expect(flightsData.appLinks[0].path).to.be(FLIGHTS_CANVAS_APPLINK_PATH); }); }); - it('should load elasticsearch index containing sample data with dates relative to current time', async () => { - const resp = await es.search<{ timestamp: string }>({ - index: 'kibana_sample_data_flights', + describe(`install in the ${space} space`, () => { + it('should return 404 if id does not match any sample data sets', async () => { + await supertest.post(`${apiPath}/xxxx`).set('kbn-xsrf', 'kibana').expect(404); }); - const doc = resp.hits.hits[0]; - const docMilliseconds = Date.parse(doc._source!.timestamp); - const nowMilliseconds = Date.now(); - const delta = Math.abs(nowMilliseconds - docMilliseconds); - expect(delta).to.be.lessThan(MILLISECOND_IN_WEEK * 4); - }); + it('should return 200 if success', async () => { + const resp = await supertest + .post(`${apiPath}/flights`) + .set('kbn-xsrf', 'kibana') + .expect(200); - describe('parameters', () => { - it('should load elasticsearch index containing sample data with dates relative to now parameter', async () => { - const nowString = `2000-01-01T00:00:00`; - await supertest - .post(`/api/sample_data/flights?now=${nowString}`) - .set('kbn-xsrf', 'kibana'); + expect(resp.body).to.eql({ + elasticsearchIndicesCreated: { kibana_sample_data_flights: 13059 }, + kibanaSavedObjectsLoaded: 11, + }); + }); + it('should load elasticsearch index containing sample data with dates relative to current time', async () => { const resp = await es.search<{ timestamp: string }>({ index: 'kibana_sample_data_flights', }); const doc = resp.hits.hits[0]; const docMilliseconds = Date.parse(doc._source!.timestamp); - const nowMilliseconds = Date.parse(nowString); + const nowMilliseconds = Date.now(); const delta = Math.abs(nowMilliseconds - docMilliseconds); expect(delta).to.be.lessThan(MILLISECOND_IN_WEEK * 4); }); + + describe('parameters', () => { + it('should load elasticsearch index containing sample data with dates relative to now parameter', async () => { + const nowString = `2000-01-01T00:00:00`; + await supertest.post(`${apiPath}/flights?now=${nowString}`).set('kbn-xsrf', 'kibana'); + + const resp = await es.search<{ timestamp: string }>({ + index: 'kibana_sample_data_flights', + }); + + const doc = resp.hits.hits[0]; + const docMilliseconds = Date.parse(doc._source!.timestamp); + const nowMilliseconds = Date.parse(nowString); + const delta = Math.abs(nowMilliseconds - docMilliseconds); + expect(delta).to.be.lessThan(MILLISECOND_IN_WEEK * 4); + }); + }); }); - }); - describe('uninstall', () => { - it('should uninstall sample data', async () => { - await supertest.delete(`/api/sample_data/flights`).set('kbn-xsrf', 'kibana').expect(204); + describe(`list in the ${space} space (after install)`, () => { + it('should return list of sample data sets with installed status', async () => { + const resp = await supertest.get(apiPath).set('kbn-xsrf', 'kibana').expect(200); + + const flightsData = findFlightsData(resp); + expect(flightsData.status).to.be('installed'); + // Check and make sure the sample dataset reflects the existing object IDs in each space. + // Instead of checking each object ID, we check the dashboard and canvas app link as representatives. + if (space === 'default') { + expect(flightsData.overviewDashboard).to.be(FLIGHTS_OVERVIEW_DASHBOARD_ID); + expect(flightsData.appLinks[0].path).to.be(FLIGHTS_CANVAS_APPLINK_PATH); + } else { + // the sample data objects installed in the 'other' space had their IDs regenerated upon import + expect(flightsData.overviewDashboard).not.to.be(FLIGHTS_OVERVIEW_DASHBOARD_ID); + expect(flightsData.appLinks[0].path).not.to.be(FLIGHTS_CANVAS_APPLINK_PATH); + } + }); }); + } + + for (const space of SPACES) { + const apiPath = `/s/${space}/api/sample_data`; - it('should remove elasticsearch index containing sample data', async () => { - const resp = await es.indices.exists({ - index: 'kibana_sample_data_flights', + describe(`uninstall in the ${space} space`, () => { + it('should uninstall sample data', async () => { + // Note: the second time this happens, the index has already been removed, but the uninstall works anyway + await supertest.delete(`${apiPath}/flights`).set('kbn-xsrf', 'kibana').expect(204); + }); + + it('should remove elasticsearch index containing sample data', async () => { + const resp = await es.indices.exists({ + index: 'kibana_sample_data_flights', + }); + expect(resp).to.be(false); }); - expect(resp).to.be(false); }); - }); + + describe(`list in the ${space} space (after uninstall)`, () => { + it('should return list of sample data sets with installed status', async () => { + const resp = await supertest.get(apiPath).set('kbn-xsrf', 'kibana').expect(200); + + const flightsData = findFlightsData(resp); + expect(flightsData.status).to.be('not_installed'); + // Check and make sure the sample dataset reflects the default object IDs, because no sample data objects exist. + // Instead of checking each object ID, we check the dashboard and canvas app link as representatives. + expect(flightsData.overviewDashboard).to.be(FLIGHTS_OVERVIEW_DASHBOARD_ID); + expect(flightsData.appLinks[0].path).to.be(FLIGHTS_CANVAS_APPLINK_PATH); + }); + }); + } }); } + +function findFlightsData(response: Response) { + expect(response.body).to.be.an('array'); + expect(response.body.length).to.be.above(0); + // @ts-expect-error Binding element 'id' implicitly has an 'any' type. + const flightsData = response.body.find(({ id }) => id === 'flights'); + if (!flightsData) { + throw new Error('Could not find flights data'); + } + return flightsData; +} diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 385d250fe761d..f6e6caf102004 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -506,12 +506,19 @@ export class VisualBuilderPageObject extends FtrService { } public async toggleIndexPatternSelectionModePopover(shouldOpen: boolean) { - const isPopoverOpened = await this.testSubjects.exists( - 'switchIndexPatternSelectionModePopoverContent' - ); - if ((shouldOpen && !isPopoverOpened) || (!shouldOpen && isPopoverOpened)) { - await this.testSubjects.click('switchIndexPatternSelectionModePopoverButton'); - } + await this.retry.try(async () => { + const isPopoverOpened = await this.testSubjects.exists( + 'switchIndexPatternSelectionModePopoverContent' + ); + if ((shouldOpen && !isPopoverOpened) || (!shouldOpen && isPopoverOpened)) { + await this.testSubjects.click('switchIndexPatternSelectionModePopoverButton'); + } + if (shouldOpen) { + await this.testSubjects.existOrFail('switchIndexPatternSelectionModePopoverContent'); + } else { + await this.testSubjects.missingOrFail('switchIndexPatternSelectionModePopoverContent'); + } + }); } public async switchIndexPatternSelectionMode(useKibanaIndices: boolean) { diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts index 6706db82ce708..88201b0ec7e19 100644 --- a/test/functional/services/combo_box.ts +++ b/test/functional/services/combo_box.ts @@ -46,7 +46,9 @@ export class ComboBoxService extends FtrService { */ private async clickOption(isMouseClick: boolean, element: WebElementWrapper): Promise { // element.click causes scrollIntoView which causes combobox to close, using _webElement.click instead - return isMouseClick ? await element.clickMouseButton() : await element._webElement.click(); + await this.retry.try(async () => { + return isMouseClick ? await element.clickMouseButton() : await element._webElement.click(); + }); } /** diff --git a/test/interpreter_functional/test_suites/run_pipeline/esaggs_timeshift.ts b/test/interpreter_functional/test_suites/run_pipeline/esaggs_timeshift.ts index 244d07d2cfc82..adfd724f063b4 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/esaggs_timeshift.ts +++ b/test/interpreter_functional/test_suites/run_pipeline/esaggs_timeshift.ts @@ -12,6 +12,10 @@ import { ExpectExpression, expectExpressionProvider } from './helpers'; import { FtrProviderContext } from '../../../functional/ftr_provider_context'; function getCell(esaggsResult: any, row: number, column: number): unknown | undefined { + if (esaggsResult && !esaggsResult.columns) { + throw new Error(`Unexpected esaggs result: ${JSON.stringify(esaggsResult, undefined, ' ')}`); + } + const columnId = esaggsResult?.columns[column]?.id; if (!columnId) { return; @@ -37,8 +41,7 @@ export default function ({ }: FtrProviderContext & { updateBaselines: boolean }) { let expectExpression: ExpectExpression; - // FLAKY https://github.com/elastic/kibana/issues/107028 - describe.skip('esaggs timeshift tests', () => { + describe('esaggs timeshift tests', () => { before(() => { expectExpression = expectExpressionProvider({ getService, updateBaselines }); }); @@ -98,6 +101,7 @@ export default function ({ 'esaggs_shift_single_percentile', expression ).getResponse(); + // percentile is not stable expect(getCell(result, 0, 0)).to.be.within(10000, 20000); expect(getCell(result, 0, 1)).to.be.within(10000, 20000); diff --git a/test/plugin_functional/test_suites/core_plugins/execution_context.ts b/test/plugin_functional/test_suites/core_plugins/execution_context.ts index 7dc9922dca51d..6d1da821d3daa 100644 --- a/test/plugin_functional/test_suites/core_plugins/execution_context.ts +++ b/test/plugin_functional/test_suites/core_plugins/execution_context.ts @@ -33,9 +33,10 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide description: 'какое-то странное описание', }; - const result = await coreStart.http.get('/execution_context/pass', { - context, - }); + const result = await coreStart.http.get<{ ['x-opaque-id']: string }>( + '/execution_context/pass', + { context } + ); return result['x-opaque-id']; }) diff --git a/test/scripts/jenkins_fleet_cypress.sh b/test/scripts/jenkins_fleet_cypress.sh new file mode 100755 index 0000000000000..085c78cbf0a41 --- /dev/null +++ b/test/scripts/jenkins_fleet_cypress.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +source test/scripts/jenkins_test_setup_xpack.sh + +echo " -> Running fleet cypress tests" +cd "$XPACK_DIR" + +checks-reporter-with-killswitch "Fleet Cypress Tests" \ + node scripts/functional_tests \ + --debug --bail \ + --kibana-install-dir "$KIBANA_INSTALL_DIR" \ + --config test/fleet_cypress/cli_config.ts + +echo "" +echo "" diff --git a/vars/tasks.groovy b/vars/tasks.groovy index 050b62646fb3b..c6d926287750c 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -164,6 +164,14 @@ def functionalXpack(Map params = [:]) { task(kibanaPipeline.functionalTestProcess('xpack-UptimePlaywright', './test/scripts/jenkins_uptime_playwright.sh')) } } + + whenChanged([ + 'x-pack/plugins/fleet/', + ]) { + if (githubPr.isPr()) { + task(kibanaPipeline.functionalTestProcess('xpack-FleetCypress', './test/scripts/jenkins_fleet_cypress.sh')) + } + } } } diff --git a/x-pack/examples/alerting_example/public/components/view_alert.tsx b/x-pack/examples/alerting_example/public/components/view_alert.tsx index 40eeb9fd360dc..5f3581871e2bd 100644 --- a/x-pack/examples/alerting_example/public/components/view_alert.tsx +++ b/x-pack/examples/alerting_example/public/components/view_alert.tsx @@ -38,10 +38,12 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => { useEffect(() => { if (!alert) { - http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); + http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); } if (!alertState) { - http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`).then(setAlertState); + http + .get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`) + .then(setAlertState); } }, [alert, alertState, http, id]); diff --git a/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx b/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx index 8eef1882b9389..1bab422c2bcf0 100644 --- a/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx +++ b/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx @@ -44,10 +44,14 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => { useEffect(() => { if (!alert) { - http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); + http + .get | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`) + .then(setAlert); } if (!alertState) { - http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`).then(setAlertState); + http + .get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`) + .then(setAlertState); } }, [alert, alertState, http, id]); diff --git a/x-pack/plugins/actions/server/index.test.ts b/x-pack/plugins/actions/server/index.test.ts index 9021879fa38aa..fe8cf98a48f43 100644 --- a/x-pack/plugins/actions/server/index.test.ts +++ b/x-pack/plugins/actions/server/index.test.ts @@ -51,10 +51,10 @@ describe('index', () => { '"xpack.actions.customHostSettings[].ssl.rejectUnauthorized" is deprecated.Use "xpack.actions.customHostSettings[].ssl.verificationMode" instead, with the setting "verificationMode:full" eql to "rejectUnauthorized:true", and "verificationMode:none" eql to "rejectUnauthorized:false".' ); expect(messages[1]).toBe( - '"xpack.actions.rejectUnauthorized" is deprecated. Use "xpack.actions.verificationMode" instead, with the setting "verificationMode:full" eql to "rejectUnauthorized:true", and "verificationMode:none" eql to "rejectUnauthorized:false".' + '"xpack.actions.rejectUnauthorized" is deprecated. Use "xpack.actions.ssl.verificationMode" instead, with the setting "verificationMode:full" eql to "rejectUnauthorized:true", and "verificationMode:none" eql to "rejectUnauthorized:false".' ); expect(messages[2]).toBe( - '"xpack.actions.proxyRejectUnauthorizedCertificates" is deprecated. Use "xpack.actions.proxyVerificationMode" instead, with the setting "proxyVerificationMode:full" eql to "rejectUnauthorized:true",and "proxyVerificationMode:none" eql to "rejectUnauthorized:false".' + '"xpack.actions.proxyRejectUnauthorizedCertificates" is deprecated. Use "xpack.actions.ssl.proxyVerificationMode" instead, with the setting "proxyVerificationMode:full" eql to "rejectUnauthorized:true",and "proxyVerificationMode:none" eql to "rejectUnauthorized:false".' ); }); }); diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index e6c82969a0aa2..e1c60b9fd0491 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -103,13 +103,13 @@ export const config: PluginConfigDescriptor = { level: 'warning', configPath: `${fromPath}.rejectUnauthorized`, message: - `"xpack.actions.rejectUnauthorized" is deprecated. Use "xpack.actions.verificationMode" instead, ` + + `"xpack.actions.rejectUnauthorized" is deprecated. Use "xpack.actions.ssl.verificationMode" instead, ` + `with the setting "verificationMode:full" eql to "rejectUnauthorized:true", ` + `and "verificationMode:none" eql to "rejectUnauthorized:false".`, correctiveActions: { manualSteps: [ `Remove "xpack.actions.rejectUnauthorized" from your kibana configs.`, - `Use "xpack.actions.verificationMode" ` + + `Use "xpack.actions.ssl.verificationMode" ` + `with the setting "verificationMode:full" eql to "rejectUnauthorized:true", ` + `and "verificationMode:none" eql to "rejectUnauthorized:false".`, ], @@ -131,13 +131,13 @@ export const config: PluginConfigDescriptor = { level: 'warning', configPath: `${fromPath}.proxyRejectUnauthorizedCertificates`, message: - `"xpack.actions.proxyRejectUnauthorizedCertificates" is deprecated. Use "xpack.actions.proxyVerificationMode" instead, ` + + `"xpack.actions.proxyRejectUnauthorizedCertificates" is deprecated. Use "xpack.actions.ssl.proxyVerificationMode" instead, ` + `with the setting "proxyVerificationMode:full" eql to "rejectUnauthorized:true",` + `and "proxyVerificationMode:none" eql to "rejectUnauthorized:false".`, correctiveActions: { manualSteps: [ `Remove "xpack.actions.proxyRejectUnauthorizedCertificates" from your kibana configs.`, - `Use "xpack.actions.proxyVerificationMode" ` + + `Use "xpack.actions.ssl.proxyVerificationMode" ` + `with the setting "proxyVerificationMode:full" eql to "rejectUnauthorized:true",` + `and "proxyVerificationMode:none" eql to "rejectUnauthorized:false".`, ], diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 8531f4a2bb706..bbf00572935fa 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -268,7 +268,8 @@ export class ActionsPlugin implements Plugin { test('getTotalCount should replace first symbol . to __ for action types names', async () => { @@ -604,4 +604,102 @@ Object { } `); }); + + test('getExecutionsTotalCount', async () => { + const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser; + mockEsClient.search.mockReturnValueOnce( + // @ts-expect-error not full search response + elasticsearchClientMock.createSuccessTransportRequestPromise({ + aggregations: { + totalExecutions: { + byConnectorTypeId: { + value: { + connectorTypes: { + '.slack': 100, + '.server-log': 20, + }, + total: 120, + }, + }, + }, + failedExecutions: { + refs: { + byConnectorTypeId: { + value: { + connectorTypes: { + '.slack': 7, + }, + total: 7, + }, + }, + }, + }, + avgDuration: { value: 10 }, + avgDurationByType: { + doc_count: 216, + actionSavedObjects: { + doc_count: 108, + byTypeId: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: '.server-log', + doc_count: 99, + refs: { + doc_count: 99, + avgDuration: { + value: 919191.9191919192, + }, + }, + }, + { + key: '.email', + doc_count: 9, + refs: { + doc_count: 9, + avgDuration: { + value: 4.196666666666667e8, + }, + }, + }, + ], + }, + }, + }, + }, + }) + ); + + // for .slack connectors + mockEsClient.search.mockReturnValueOnce( + // @ts-expect-error not full search response + elasticsearchClientMock.createSuccessTransportRequestPromise({ + aggregations: { + avgDuration: { value: 10 }, + }, + }) + ); + const telemetry = await getExecutionsPerDayCount(mockEsClient, 'test'); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(telemetry).toStrictEqual({ + avgExecutionTime: 0, + avgExecutionTimeByType: { + '__server-log': 919191.9191919192, + __email: 419666666.6666667, + }, + + countByType: { + __slack: 100, + + '__server-log': 20, + }, + countFailed: 7, + countFailedByType: { + __slack: 7, + }, + countTotal: 120, + }); + }); }); diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index ab72352d460e3..d288611af5e21 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -379,4 +379,184 @@ function replaceFirstAndLastDotSymbols(strToReplace: string) { return hasLastSymbolDot ? `${appliedString.slice(0, -1)}__` : appliedString; } -// TODO: Implement executions count telemetry with eventLog, when it will write to index +export async function getExecutionsPerDayCount( + esClient: ElasticsearchClient, + eventLogIndex: string +): Promise<{ + countTotal: number; + countByType: Record; + countFailed: number; + countFailedByType: Record; + avgExecutionTime: number; + avgExecutionTimeByType: Record; +}> { + const scriptedMetric = { + scripted_metric: { + init_script: 'state.connectorTypes = [:]; state.total = 0;', + map_script: ` + if (doc['kibana.saved_objects.type'].value == 'action') { + String connectorType = doc['kibana.saved_objects.type_id'].value; + state.connectorTypes.put(connectorType, state.connectorTypes.containsKey(connectorType) ? state.connectorTypes.get(connectorType) + 1 : 1); + state.total++; + } + `, + // Combine script is executed per cluster, but we already have a key-value pair per cluster. + // Despite docs that say this is optional, this script can't be blank. + combine_script: 'return state', + // Reduce script is executed across all clusters, so we need to add up all the total from each cluster + // This also needs to account for having no data + reduce_script: ` + Map connectorTypes = [:]; + long total = 0; + for (state in states) { + if (state !== null) { + total += state.total; + for (String k : state.connectorTypes.keySet()) { + connectorTypes.put(k, connectorTypes.containsKey(k) ? connectorTypes.get(k) + state.connectorTypes.get(k) : state.connectorTypes.get(k)); + } + } + } + Map result = new HashMap(); + result.total = total; + result.connectorTypes = connectorTypes; + return result; + `, + }, + }; + + const { body: actionResults } = await esClient.search({ + index: eventLogIndex, + size: 0, + body: { + query: { + bool: { + filter: { + bool: { + must: [ + { + term: { 'event.action': 'execute' }, + }, + { + term: { 'event.provider': 'actions' }, + }, + { + range: { + '@timestamp': { + gte: 'now-1d', + }, + }, + }, + ], + }, + }, + }, + }, + aggs: { + totalExecutions: { + nested: { + path: 'kibana.saved_objects', + }, + aggs: { + byConnectorTypeId: scriptedMetric, + }, + }, + failedExecutions: { + filter: { + bool: { + filter: [ + { + term: { + 'event.outcome': 'failure', + }, + }, + ], + }, + }, + aggs: { + refs: { + nested: { + path: 'kibana.saved_objects', + }, + aggs: { + byConnectorTypeId: scriptedMetric, + }, + }, + }, + }, + avgDuration: { avg: { field: 'event.duration' } }, + avgDurationByType: { + nested: { + path: 'kibana.saved_objects', + }, + aggs: { + actionSavedObjects: { + filter: { term: { 'kibana.saved_objects.type': 'action' } }, + aggs: { + byTypeId: { + terms: { + field: 'kibana.saved_objects.type_id', + }, + aggs: { + refs: { + reverse_nested: {}, + aggs: { + avgDuration: { avg: { field: 'event.duration' } }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }); + + // @ts-expect-error aggegation type is not specified + const aggsExecutions = actionResults.aggregations.totalExecutions?.byConnectorTypeId.value; + // convert nanoseconds to milliseconds + const aggsAvgExecutionTime = Math.round( + // @ts-expect-error aggegation type is not specified + actionResults.aggregations.avgDuration.value / (1000 * 1000) + ); + const aggsFailedExecutions = + // @ts-expect-error aggegation type is not specified + actionResults.aggregations.failedExecutions?.refs?.byConnectorTypeId.value; + + const avgDurationByType = + // @ts-expect-error aggegation type is not specified + actionResults.aggregations.avgDurationByType?.actionSavedObjects?.byTypeId?.buckets; + + const avgExecutionTimeByType: Record = avgDurationByType.reduce( + // @ts-expect-error aggegation type is not specified + (res: Record, bucket) => { + res[replaceFirstAndLastDotSymbols(bucket.key)] = bucket?.refs.avgDuration.value; + return res; + }, + {} + ); + + return { + countTotal: aggsExecutions.total, + countByType: Object.entries(aggsExecutions.connectorTypes).reduce( + (res: Record, [key, value]) => { + // @ts-expect-error aggegation type is not specified + res[replaceFirstAndLastDotSymbols(key)] = value; + return res; + }, + {} + ), + countFailed: aggsFailedExecutions.total, + countFailedByType: Object.entries(aggsFailedExecutions.connectorTypes).reduce( + (res: Record, [key, value]) => { + // @ts-expect-error aggegation type is not specified + res[replaceFirstAndLastDotSymbols(key)] = value; + return res; + }, + {} + ), + avgExecutionTime: aggsAvgExecutionTime, + avgExecutionTimeByType, + }; +} diff --git a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts index 9ba9d7390a7b6..3e690d18063d6 100644 --- a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts +++ b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts @@ -37,8 +37,14 @@ export function createActionsUsageCollector( }, }, count_active_by_type: byTypeSchema, + count_actions_executions_per_day: { type: 'long' }, + count_actions_executions_by_type_per_day: byTypeSchema, count_active_email_connectors_by_service_type: byServiceProviderTypeSchema, count_actions_namespaces: { type: 'long' }, + count_actions_executions_failed_per_day: { type: 'long' }, + count_actions_executions_failed_by_type_per_day: byTypeSchema, + avg_execution_time_per_day: { type: 'long' }, + avg_execution_time_by_type_per_day: byTypeSchema, }, fetch: async () => { try { @@ -60,6 +66,12 @@ export function createActionsUsageCollector( count_active_by_type: {}, count_active_email_connectors_by_service_type: {}, count_actions_namespaces: 0, + count_actions_executions_per_day: 0, + count_actions_executions_by_type_per_day: {}, + count_actions_executions_failed_per_day: 0, + count_actions_executions_failed_by_type_per_day: {}, + avg_execution_time_per_day: 0, + avg_execution_time_by_type_per_day: {}, }; } }, diff --git a/x-pack/plugins/actions/server/usage/task.ts b/x-pack/plugins/actions/server/usage/task.ts index bacb9e5f72571..5ddcbab4261d1 100644 --- a/x-pack/plugins/actions/server/usage/task.ts +++ b/x-pack/plugins/actions/server/usage/task.ts @@ -7,13 +7,14 @@ import { Logger, CoreSetup } from 'kibana/server'; import moment from 'moment'; +import { IEventLogService } from '../../../event_log/server'; import { RunContext, TaskManagerSetupContract, TaskManagerStartContract, } from '../../../task_manager/server'; import { PreConfiguredAction } from '../types'; -import { getTotalCount, getInUseTotalCount } from './actions_telemetry'; +import { getTotalCount, getInUseTotalCount, getExecutionsPerDayCount } from './actions_telemetry'; export const TELEMETRY_TASK_TYPE = 'actions_telemetry'; @@ -24,9 +25,17 @@ export function initializeActionsTelemetry( taskManager: TaskManagerSetupContract, core: CoreSetup, kibanaIndex: string, - preconfiguredActions: PreConfiguredAction[] + preconfiguredActions: PreConfiguredAction[], + eventLog: IEventLogService ) { - registerActionsTelemetryTask(logger, taskManager, core, kibanaIndex, preconfiguredActions); + registerActionsTelemetryTask( + logger, + taskManager, + core, + kibanaIndex, + preconfiguredActions, + eventLog + ); } export function scheduleActionsTelemetry(logger: Logger, taskManager: TaskManagerStartContract) { @@ -38,13 +47,20 @@ function registerActionsTelemetryTask( taskManager: TaskManagerSetupContract, core: CoreSetup, kibanaIndex: string, - preconfiguredActions: PreConfiguredAction[] + preconfiguredActions: PreConfiguredAction[], + eventLog: IEventLogService ) { taskManager.registerTaskDefinitions({ [TELEMETRY_TASK_TYPE]: { title: 'Actions usage fetch task', timeout: '5m', - createTaskRunner: telemetryTaskRunner(logger, core, kibanaIndex, preconfiguredActions), + createTaskRunner: telemetryTaskRunner( + logger, + core, + kibanaIndex, + preconfiguredActions, + eventLog + ), }, }); } @@ -66,10 +82,12 @@ export function telemetryTaskRunner( logger: Logger, core: CoreSetup, kibanaIndex: string, - preconfiguredActions: PreConfiguredAction[] + preconfiguredActions: PreConfiguredAction[], + eventLog: IEventLogService ) { return ({ taskInstance }: RunContext) => { const { state } = taskInstance; + const eventLogIndex = eventLog.getIndexPattern(); const getEsClient = () => core.getStartServices().then( ([ @@ -84,8 +102,9 @@ export function telemetryTaskRunner( return Promise.all([ getTotalCount(esClient, kibanaIndex, preconfiguredActions), getInUseTotalCount(esClient, kibanaIndex, undefined, preconfiguredActions), + getExecutionsPerDayCount(esClient, eventLogIndex), ]) - .then(([totalAggegations, totalInUse]) => { + .then(([totalAggegations, totalInUse, totalExecutionsPerDay]) => { return { state: { runs: (state.runs || 0) + 1, @@ -96,6 +115,13 @@ export function telemetryTaskRunner( count_active_alert_history_connectors: totalInUse.countByAlertHistoryConnectorType, count_active_email_connectors_by_service_type: totalInUse.countEmailByService, count_actions_namespaces: totalInUse.countNamespaces, + count_actions_executions_per_day: totalExecutionsPerDay.countTotal, + count_actions_executions_by_type_per_day: totalExecutionsPerDay.countByType, + count_actions_executions_failed_per_day: totalExecutionsPerDay.countFailed, + count_actions_executions_failed_by_type_per_day: + totalExecutionsPerDay.countFailedByType, + avg_execution_time_per_day: totalExecutionsPerDay.avgExecutionTime, + avg_execution_time_by_type_per_day: totalExecutionsPerDay.avgExecutionTimeByType, }, runAt: getNextMidnight(), }; diff --git a/x-pack/plugins/actions/server/usage/types.ts b/x-pack/plugins/actions/server/usage/types.ts index 52677b35ac75b..2d041b1ba0d0e 100644 --- a/x-pack/plugins/actions/server/usage/types.ts +++ b/x-pack/plugins/actions/server/usage/types.ts @@ -16,9 +16,12 @@ export interface ActionsUsage { count_active_by_type: Record; count_active_email_connectors_by_service_type: Record; count_actions_namespaces: number; - // TODO: Implement executions count telemetry with eventLog, when it will write to index - // executions_by_type: Record; - // executions_total: number; + count_actions_executions_per_day: number; + count_actions_executions_by_type_per_day: Record; + count_actions_executions_failed_per_day: number; + count_actions_executions_failed_by_type_per_day: Record; + avg_execution_time_per_day: number; + avg_execution_time_by_type_per_day: Record; } export const byTypeSchema: MakeSchemaFrom['count_by_type'] = { diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 9834225e73723..f0703defbca3d 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -209,7 +209,13 @@ export class AlertingPlugin { usageCollection, core.getStartServices().then(([_, { taskManager }]) => taskManager) ); - initializeAlertingTelemetry(this.telemetryLogger, core, plugins.taskManager, kibanaIndex); + initializeAlertingTelemetry( + this.telemetryLogger, + core, + plugins.taskManager, + kibanaIndex, + this.eventLogService + ); } // Usage counter for telemetry diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts index 03a96d19b8e8a..af08c8c75c144 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts @@ -7,7 +7,11 @@ // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks'; -import { getTotalCountAggregations, getTotalCountInUse } from './alerts_telemetry'; +import { + getTotalCountAggregations, + getTotalCountInUse, + getExecutionsPerDayCount, +} from './alerts_telemetry'; describe('alerts telemetry', () => { test('getTotalCountInUse should replace first "." symbol to "__" in alert types names', async () => { @@ -114,4 +118,74 @@ Object { } `); }); + + test('getTotalExecutionsCount should return execution aggregations for total count, count by rule type and number of failed executions', async () => { + const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser; + mockEsClient.search.mockReturnValue( + // @ts-expect-error @elastic/elasticsearch Aggregate only allows unknown values + elasticsearchClientMock.createSuccessTransportRequestPromise({ + aggregations: { + byRuleTypeId: { + value: { + ruleTypes: { + '.index-threshold': 2, + 'logs.alert.document.count': 1, + 'document.test.': 1, + }, + ruleTypesDuration: { + '.index-threshold': 2087868, + 'logs.alert.document.count': 1675765, + 'document.test.': 17687687, + }, + }, + }, + failuresByReason: { + value: { + reasons: { + unknown: { + '.index-threshold': 2, + 'logs.alert.document.count': 1, + 'document.test.': 1, + }, + }, + }, + }, + avgDuration: { value: 10 }, + }, + hits: { + hits: [], + }, + }) + ); + + const telemetry = await getExecutionsPerDayCount(mockEsClient, 'test'); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + + expect(telemetry).toStrictEqual({ + avgExecutionTime: 0, + avgExecutionTimeByType: { + '__index-threshold': 1043934, + 'document.test__': 17687687, + 'logs.alert.document.count': 1675765, + }, + countByType: { + '__index-threshold': 2, + 'document.test__': 1, + 'logs.alert.document.count': 1, + }, + countFailuresByReason: { + unknown: 4, + }, + countFailuresByReasonByType: { + unknown: { + '.index-threshold': 2, + 'document.test.': 1, + 'logs.alert.document.count': 1, + }, + }, + countTotal: 4, + countTotalFailures: 4, + }); + }); }); diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts index 7ff9538c1aa26..180ee4300f18c 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts @@ -38,6 +38,65 @@ const alertTypeMetric = { }, }; +const ruleTypeExecutionsMetric = { + scripted_metric: { + init_script: 'state.ruleTypes = [:]; state.ruleTypesDuration = [:];', + map_script: ` + String ruleType = doc['rule.category'].value; + long duration = doc['event.duration'].value / (1000 * 1000); + state.ruleTypes.put(ruleType, state.ruleTypes.containsKey(ruleType) ? state.ruleTypes.get(ruleType) + 1 : 1); + state.ruleTypesDuration.put(ruleType, state.ruleTypesDuration.containsKey(ruleType) ? state.ruleTypesDuration.get(ruleType) + duration : duration); + `, + // Combine script is executed per cluster, but we already have a key-value pair per cluster. + // Despite docs that say this is optional, this script can't be blank. + combine_script: 'return state', + // Reduce script is executed across all clusters, so we need to add up all the total from each cluster + // This also needs to account for having no data + reduce_script: ` + Map result = [:]; + for (Map m : states.toArray()) { + if (m !== null) { + for (String k : m.keySet()) { + result.put(k, result.containsKey(k) ? result.get(k) + m.get(k) : m.get(k)); + } + } + } + return result; + `, + }, +}; + +const ruleTypeFailureExecutionsMetric = { + scripted_metric: { + init_script: 'state.reasons = [:]', + map_script: ` + if (doc['event.outcome'].value == 'failure') { + String reason = doc['event.reason'].value; + String ruleType = doc['rule.category'].value; + Map ruleTypes = state.reasons.containsKey(reason) ? state.reasons.get(reason) : [:]; + ruleTypes.put(ruleType, ruleTypes.containsKey(ruleType) ? ruleTypes.get(ruleType) + 1 : 1); + state.reasons.put(reason, ruleTypes); + } + `, + // Combine script is executed per cluster, but we already have a key-value pair per cluster. + // Despite docs that say this is optional, this script can't be blank. + combine_script: 'return state', + // Reduce script is executed across all clusters, so we need to add up all the total from each cluster + // This also needs to account for having no data + reduce_script: ` + Map result = [:]; + for (Map m : states.toArray()) { + if (m !== null) { + for (String k : m.keySet()) { + result.put(k, result.containsKey(k) ? result.get(k) + m.get(k) : m.get(k)); + } + } + } + return result; + `, + }, +}; + export async function getTotalCountAggregations( esClient: ElasticsearchClient, kibanaInex: string @@ -260,4 +319,130 @@ function replaceFirstAndLastDotSymbols(strToReplace: string) { return hasLastSymbolDot ? `${appliedString.slice(0, -1)}__` : appliedString; } -// TODO: Implement executions count telemetry with eventLog, when it will write to index +export async function getExecutionsPerDayCount( + esClient: ElasticsearchClient, + eventLogIndex: string +) { + const { body: searchResult } = await esClient.search({ + index: eventLogIndex, + size: 0, + body: { + query: { + bool: { + filter: { + bool: { + must: [ + { + term: { 'event.action': 'execute' }, + }, + { + term: { 'event.provider': 'alerting' }, + }, + { + range: { + '@timestamp': { + gte: 'now-1d', + }, + }, + }, + ], + }, + }, + }, + }, + aggs: { + byRuleTypeId: ruleTypeExecutionsMetric, + failuresByReason: ruleTypeFailureExecutionsMetric, + avgDuration: { avg: { field: 'event.duration' } }, + }, + }, + }); + + const executionsAggregations = searchResult.aggregations as { + byRuleTypeId: { + value: { ruleTypes: Record; ruleTypesDuration: Record }; + }; + }; + + const aggsAvgExecutionTime = Math.round( + // @ts-expect-error aggegation type is not specified + // convert nanoseconds to milliseconds + searchResult.aggregations.avgDuration.value / (1000 * 1000) + ); + + const executionFailuresAggregations = searchResult.aggregations as { + failuresByReason: { value: { reasons: Record> } }; + }; + + return { + countTotal: Object.keys(executionsAggregations.byRuleTypeId.value.ruleTypes).reduce( + (total: number, key: string) => + parseInt(executionsAggregations.byRuleTypeId.value.ruleTypes[key], 10) + total, + 0 + ), + countByType: Object.keys(executionsAggregations.byRuleTypeId.value.ruleTypes).reduce( + // ES DSL aggregations are returned as `any` by esClient.search + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj: any, key: string) => ({ + ...obj, + [replaceFirstAndLastDotSymbols(key)]: + executionsAggregations.byRuleTypeId.value.ruleTypes[key], + }), + {} + ), + countTotalFailures: Object.keys( + executionFailuresAggregations.failuresByReason.value.reasons + ).reduce((total: number, reason: string) => { + const byRuleTypesRefs = executionFailuresAggregations.failuresByReason.value.reasons[reason]; + const countByRuleTypes = Object.keys(byRuleTypesRefs).reduce( + (totalByType, ruleType) => parseInt(byRuleTypesRefs[ruleType] + totalByType, 10), + 0 + ); + return countByRuleTypes + total; + }, 0), + countFailuresByReason: Object.keys( + executionFailuresAggregations.failuresByReason.value.reasons + ).reduce( + // ES DSL aggregations are returned as `any` by esClient.search + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj: any, reason: string) => { + const byRuleTypesRefs = + executionFailuresAggregations.failuresByReason.value.reasons[reason]; + const countByRuleTypes = Object.keys(byRuleTypesRefs).reduce( + (totalByType, ruleType) => parseInt(byRuleTypesRefs[ruleType] + totalByType, 10), + 0 + ); + return { + ...obj, + [replaceFirstAndLastDotSymbols(reason)]: countByRuleTypes, + }; + }, + {} + ), + countFailuresByReasonByType: Object.keys( + executionFailuresAggregations.failuresByReason.value.reasons + ).reduce( + // ES DSL aggregations are returned as `any` by esClient.search + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj: any, key: string) => ({ + ...obj, + [replaceFirstAndLastDotSymbols(key)]: + executionFailuresAggregations.failuresByReason.value.reasons[key], + }), + {} + ), + avgExecutionTime: aggsAvgExecutionTime, + avgExecutionTimeByType: Object.keys(executionsAggregations.byRuleTypeId.value.ruleTypes).reduce( + // ES DSL aggregations are returned as `any` by esClient.search + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj: any, key: string) => ({ + ...obj, + [replaceFirstAndLastDotSymbols(key)]: Math.round( + executionsAggregations.byRuleTypeId.value.ruleTypesDuration[key] / + parseInt(executionsAggregations.byRuleTypeId.value.ruleTypes[key], 10) + ), + }), + {} + ), + }; +} diff --git a/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts b/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts index e9405c51dbf15..e5b25ea75fc1c 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts @@ -50,6 +50,26 @@ const byTypeSchema: MakeSchemaFrom['count_by_type'] = { xpack__ml__anomaly_detection_jobs_health: { type: 'long' }, // eslint-disable-line @typescript-eslint/naming-convention }; +const byReasonSchema: MakeSchemaFrom['count_rules_executions_failured_by_reason_per_day'] = + { + // TODO: Find out an automated way to populate the keys or reformat these into an array (and change the Remote Telemetry indexer accordingly) + DYNAMIC_KEY: { type: 'long' }, + read: { type: 'long' }, + decrypt: { type: 'long' }, + license: { type: 'long' }, + unknown: { type: 'long' }, + }; + +const byReasonSchemaByType: MakeSchemaFrom['count_rules_executions_failured_by_reason_by_type_per_day'] = + { + // TODO: Find out an automated way to populate the keys or reformat these into an array (and change the Remote Telemetry indexer accordingly) + DYNAMIC_KEY: byTypeSchema, + read: byTypeSchema, + decrypt: byTypeSchema, + license: byTypeSchema, + unknown: byTypeSchema, + }; + export function createAlertsUsageCollector( usageCollection: UsageCollectionSetup, taskManager: Promise @@ -92,6 +112,13 @@ export function createAlertsUsageCollector( count_active_by_type: {}, count_by_type: {}, count_rules_namespaces: 0, + count_rules_executions_per_day: 0, + count_rules_executions_by_type_per_day: {}, + count_rules_executions_failured_per_day: 0, + count_rules_executions_failured_by_reason_per_day: {}, + count_rules_executions_failured_by_reason_by_type_per_day: {}, + avg_execution_time_per_day: 0, + avg_execution_time_by_type_per_day: {}, }; } }, @@ -117,6 +144,13 @@ export function createAlertsUsageCollector( count_active_by_type: byTypeSchema, count_by_type: byTypeSchema, count_rules_namespaces: { type: 'long' }, + count_rules_executions_per_day: { type: 'long' }, + count_rules_executions_by_type_per_day: byTypeSchema, + count_rules_executions_failured_per_day: { type: 'long' }, + count_rules_executions_failured_by_reason_per_day: byReasonSchema, + count_rules_executions_failured_by_reason_by_type_per_day: byReasonSchemaByType, + avg_execution_time_per_day: { type: 'long' }, + avg_execution_time_by_type_per_day: byTypeSchema, }, }); } diff --git a/x-pack/plugins/alerting/server/usage/task.ts b/x-pack/plugins/alerting/server/usage/task.ts index 9d39b3765cb5d..2fbd56c105c31 100644 --- a/x-pack/plugins/alerting/server/usage/task.ts +++ b/x-pack/plugins/alerting/server/usage/task.ts @@ -7,13 +7,18 @@ import { Logger, CoreSetup } from 'kibana/server'; import moment from 'moment'; +import { IEventLogService } from '../../../event_log/server'; import { RunContext, TaskManagerSetupContract, TaskManagerStartContract, } from '../../../task_manager/server'; -import { getTotalCountAggregations, getTotalCountInUse } from './alerts_telemetry'; +import { + getTotalCountAggregations, + getTotalCountInUse, + getExecutionsPerDayCount, +} from './alerts_telemetry'; export const TELEMETRY_TASK_TYPE = 'alerting_telemetry'; @@ -23,9 +28,10 @@ export function initializeAlertingTelemetry( logger: Logger, core: CoreSetup, taskManager: TaskManagerSetupContract, - kibanaIndex: string + kibanaIndex: string, + eventLog: IEventLogService ) { - registerAlertingTelemetryTask(logger, core, taskManager, kibanaIndex); + registerAlertingTelemetryTask(logger, core, taskManager, kibanaIndex, eventLog); } export function scheduleAlertingTelemetry(logger: Logger, taskManager?: TaskManagerStartContract) { @@ -38,13 +44,14 @@ function registerAlertingTelemetryTask( logger: Logger, core: CoreSetup, taskManager: TaskManagerSetupContract, - kibanaIndex: string + kibanaIndex: string, + eventLog: IEventLogService ) { taskManager.registerTaskDefinitions({ [TELEMETRY_TASK_TYPE]: { title: 'Alerting usage fetch task', timeout: '5m', - createTaskRunner: telemetryTaskRunner(logger, core, kibanaIndex), + createTaskRunner: telemetryTaskRunner(logger, core, kibanaIndex, eventLog), }, }); } @@ -62,9 +69,15 @@ async function scheduleTasks(logger: Logger, taskManager: TaskManagerStartContra } } -export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex: string) { +export function telemetryTaskRunner( + logger: Logger, + core: CoreSetup, + kibanaIndex: string, + eventLog: IEventLogService +) { return ({ taskInstance }: RunContext) => { const { state } = taskInstance; + const eventLogIndex = eventLog.getIndexPattern(); const getEsClient = () => core.getStartServices().then( ([ @@ -80,8 +93,9 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex return Promise.all([ getTotalCountAggregations(esClient, kibanaIndex), getTotalCountInUse(esClient, kibanaIndex), + getExecutionsPerDayCount(esClient, eventLogIndex), ]) - .then(([totalCountAggregations, totalInUse]) => { + .then(([totalCountAggregations, totalInUse, totalExecutions]) => { return { state: { runs: (state.runs || 0) + 1, @@ -90,6 +104,15 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex count_active_total: totalInUse.countTotal, count_disabled_total: totalCountAggregations.count_total - totalInUse.countTotal, count_rules_namespaces: totalInUse.countNamespaces, + count_rules_executions_per_day: totalExecutions.countTotal, + count_rules_executions_by_type_per_day: totalExecutions.countByType, + count_rules_executions_failured_per_day: totalExecutions.countTotalFailures, + count_rules_executions_failured_by_reason_per_day: + totalExecutions.countFailuresByReason, + count_rules_executions_failured_by_reason_by_type_per_day: + totalExecutions.countFailuresByReasonByType, + avg_execution_time_per_day: totalExecutions.avgExecutionTime, + avg_execution_time_by_type_per_day: totalExecutions.avgExecutionTimeByType, }, runAt: getNextMidnight(), }; diff --git a/x-pack/plugins/alerting/server/usage/types.ts b/x-pack/plugins/alerting/server/usage/types.ts index 0e489893a1bbc..50d9b80c44b70 100644 --- a/x-pack/plugins/alerting/server/usage/types.ts +++ b/x-pack/plugins/alerting/server/usage/types.ts @@ -12,6 +12,13 @@ export interface AlertsUsage { count_by_type: Record; count_active_by_type: Record; count_rules_namespaces: number; + count_rules_executions_per_day: number; + count_rules_executions_by_type_per_day: Record; + count_rules_executions_failured_per_day: number; + count_rules_executions_failured_by_reason_per_day: Record; + count_rules_executions_failured_by_reason_by_type_per_day: Record>; + avg_execution_time_per_day: number; + avg_execution_time_by_type_per_day: Record; throttle_time: { min: number; avg: number; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress.json b/x-pack/plugins/apm/ftr_e2e/cypress.json index ee62f12976678..1791baaa5aae4 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress.json +++ b/x-pack/plugins/apm/ftr_e2e/cypress.json @@ -2,7 +2,7 @@ "fileServerFolder": "./cypress", "fixturesFolder": "./cypress/fixtures", "integrationFolder": "./cypress/integration", - "pluginsFile": "./cypress/plugins/index.js", + "pluginsFile": "./cypress/plugins/index.ts", "screenshotsFolder": "./cypress/screenshots", "supportFile": "./cypress/support/index.ts", "videosFolder": "./cypress/videos", @@ -13,4 +13,4 @@ "viewportWidth": 1440, "video": false, "screenshotOnRunFailure": false -} \ No newline at end of file +} diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_8.0.0/data.json.gz b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_8.0.0/data.json.gz deleted file mode 100644 index 1450997a0107e..0000000000000 Binary files a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_8.0.0/data.json.gz and /dev/null differ diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_8.0.0/mappings.json b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_mappings_only_8.0.0/mappings.json similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_8.0.0/mappings.json rename to x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/apm_mappings_only_8.0.0/mappings.json diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts index b03aa9a4fbd83..bd01c83b9cc6e 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts @@ -4,19 +4,30 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-synthtrace'; +import { + service, + browser, + timerange, + getChromeUserAgentDefaults, +} from '@elastic/apm-synthtrace'; export function opbeans({ from, to }: { from: number; to: number }) { const range = timerange(from, to); - const opbeansJava = service('opbeans-java', 'production', 'java').instance( - 'opbeans-java-prod-1' - ); + const opbeansJava = service('opbeans-java', 'production', 'java') + .instance('opbeans-java-prod-1') + .podId('opbeans-java-prod-1-pod'); const opbeansNode = service('opbeans-node', 'production', 'nodejs').instance( 'opbeans-node-prod-1' ); + const opbeansRum = browser( + 'opbeans-rum', + 'production', + getChromeUserAgentDefaults() + ); + return [ ...range .interval('1s') @@ -27,6 +38,15 @@ export function opbeans({ from, to }: { from: number; to: number }) { .timestamp(timestamp) .duration(1000) .success() + .errors(opbeansJava.error('[MockError] Foo').timestamp(timestamp)) + .children( + opbeansJava + .span('SELECT * FROM product', 'db', 'postgresql') + .timestamp(timestamp) + .duration(50) + .success() + .destination('postgresql') + ) .serialize(), ...opbeansNode .transaction('GET /api/product/:id') @@ -34,6 +54,17 @@ export function opbeans({ from, to }: { from: number; to: number }) { .duration(500) .success() .serialize(), + ...opbeansNode + .transaction('Worker job', 'Worker') + .timestamp(timestamp) + .duration(1000) + .success() + .serialize(), + ...opbeansRum + .transaction('/') + .timestamp(timestamp) + .duration(1000) + .serialize(), ]), ]; } diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts index 0ab2d5682a900..2c2e93d463c50 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts @@ -4,13 +4,31 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { synthtrace } from '../../../synthtrace'; +import { opbeans } from '../../fixtures/synthtrace/opbeans'; + +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const timeRange = { - rangeFrom: Cypress.env('START_DATE'), - rangeTo: Cypress.env('END_DATE'), + rangeFrom: start, + rangeTo: end, }; describe('Dependencies', () => { + before(async () => { + await synthtrace.index( + opbeans({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + beforeEach(() => { cy.loginAsReadOnlyUser(); }); @@ -40,21 +58,21 @@ describe('Dependencies', () => { cy.get('[data-test-subj="throughputChart"]'); cy.get('[data-test-subj="errorRateChart"]'); - cy.contains('opbeans-python').click({ force: true }); + cy.contains('opbeans-java').click({ force: true }); - cy.contains('h1', 'opbeans-python'); + cy.contains('h1', 'opbeans-java'); }); }); describe('service overview page', () => { it('shows dependency information and you can navigate to a page for a dependency', () => { cy.visit( - `/app/apm/services/opbeans-python/overview?${new URLSearchParams( + `/app/apm/services/opbeans-java/overview?${new URLSearchParams( timeRange )}` ); - cy.contains('postgresql').click({ force: true }); + cy.contains('a', 'postgresql').click({ force: true }); cy.contains('h1', 'postgresql'); }); @@ -63,7 +81,7 @@ describe('Dependencies', () => { describe('service dependencies tab', () => { it('shows dependency information and you can navigate to a page for a dependency', () => { cy.visit( - `/app/apm/services/opbeans-python/overview?${new URLSearchParams( + `/app/apm/services/opbeans-java/overview?${new URLSearchParams( timeRange )}` ); @@ -72,7 +90,7 @@ describe('Dependencies', () => { cy.contains('Time spent by dependency'); - cy.contains('postgresql').click({ force: true }); + cy.contains('a', 'postgresql').click({ force: true }); cy.contains('h1', 'postgresql'); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts index 8457282f5c256..1e09ec6dbf7c1 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts @@ -6,9 +6,11 @@ */ import url from 'url'; -import archives_metadata from '../../fixtures/es_archiver/archives_metadata'; +import { synthtrace } from '../../../synthtrace'; +import { opbeans } from '../../fixtures/synthtrace/opbeans'; -const { start, end } = archives_metadata['apm_8.0.0']; +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const serviceInventoryHref = url.format({ pathname: '/app/apm/services', @@ -27,6 +29,19 @@ const apisToIntercept = [ ]; describe('Home page', () => { + before(async () => { + await synthtrace.index( + opbeans({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + beforeEach(() => { cy.loginAsReadOnlyUser(); }); @@ -44,7 +59,6 @@ describe('Home page', () => { cy.visit( `${serviceInventoryHref}&kuery=not%20(processor.event%3A%22transaction%22)` ); - cy.contains('opbeans-python'); cy.contains('opbeans-java'); cy.contains('opbeans-node'); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/header_filters.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/header_filters.spec.ts index 6950a0bbadb9c..a7667002d4ea9 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/header_filters.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/header_filters.spec.ts @@ -5,9 +5,11 @@ * 2.0. */ import url from 'url'; -import archives_metadata from '../../../fixtures/es_archiver/archives_metadata'; +import { synthtrace } from '../../../../synthtrace'; +import { opbeans } from '../../../fixtures/synthtrace/opbeans'; -const { start, end } = archives_metadata['apm_8.0.0']; +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const serviceOverviewHref = url.format({ pathname: '/app/apm/services/opbeans-node/overview', @@ -62,6 +64,16 @@ const apisToIntercept = [ ]; describe('Service overview - header filters', () => { + before(async () => { + await synthtrace.index( + opbeans({ from: new Date(start).getTime(), to: new Date(end).getTime() }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + beforeEach(() => { cy.loginAsReadOnlyUser(); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/instances_table.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/instances_table.spec.ts index c7d9fa4e32106..dad92b8334981 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/instances_table.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/instances_table.spec.ts @@ -6,15 +6,19 @@ */ import url from 'url'; -import archives_metadata from '../../../fixtures/es_archiver/archives_metadata'; +import { synthtrace } from '../../../../synthtrace'; +import { opbeans } from '../../../fixtures/synthtrace/opbeans'; -const { start, end } = archives_metadata['apm_8.0.0']; +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const serviceOverviewHref = url.format({ pathname: '/app/apm/services/opbeans-java/overview', query: { rangeFrom: start, rangeTo: end }, }); +const serviceNodeName = 'opbeans-java-prod-1'; + const apisToIntercept = [ { endpoint: @@ -27,8 +31,7 @@ const apisToIntercept = [ name: 'instancesDetailsRequest', }, { - endpoint: - '/internal/apm/services/opbeans-java/service_overview_instances/details/31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad?*', + endpoint: `/internal/apm/services/opbeans-java/service_overview_instances/details/${serviceNodeName}?*`, name: 'instanceDetailsRequest', }, ]; @@ -49,8 +52,18 @@ describe('Instances table', () => { // }); describe('when data is loaded', () => { - const serviceNodeName = - '31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad'; + before(async () => { + await synthtrace.index( + opbeans({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); it('has data in the table', () => { cy.visit(serviceOverviewHref); @@ -91,7 +104,7 @@ describe('Instances table', () => { cy.wait('@instancesDetailsRequest'); cy.get( `[data-test-subj="instanceActionsButton_${serviceNodeName}"]` - ).realClick(); + ).click(); cy.contains('Pod logs'); cy.contains('Pod metrics'); cy.contains('Container logs'); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts index b0cf424b8067e..5601ade671908 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts @@ -6,9 +6,11 @@ */ import url from 'url'; -import archives_metadata from '../../../fixtures/es_archiver/archives_metadata'; +import { synthtrace } from '../../../../synthtrace'; +import { opbeans } from '../../../fixtures/synthtrace/opbeans'; -const { start, end } = archives_metadata['apm_8.0.0']; +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const serviceOverviewPath = '/app/apm/services/opbeans-node/overview'; const baseUrl = url.format({ @@ -17,6 +19,19 @@ const baseUrl = url.format({ }); describe('Service Overview', () => { + before(async () => { + await synthtrace.index( + opbeans({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + beforeEach(() => { cy.loginAsReadOnlyUser(); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/time_comparison.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/time_comparison.spec.ts index 65a82a8ab6bdf..e905c86a5854c 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/time_comparison.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/time_comparison.spec.ts @@ -6,9 +6,11 @@ */ import url from 'url'; import moment from 'moment'; -import archives_metadata from '../../../fixtures/es_archiver/archives_metadata'; +import { synthtrace } from '../../../../synthtrace'; +import { opbeans } from '../../../fixtures/synthtrace/opbeans'; -const { start, end } = archives_metadata['apm_8.0.0']; +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const serviceOverviewPath = '/app/apm/services/opbeans-java/overview'; const serviceOverviewHref = url.format({ @@ -49,6 +51,19 @@ const apisToIntercept = [ ]; describe('Service overview: Time Comparison', () => { + before(async () => { + await synthtrace.index( + opbeans({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + beforeEach(() => { cy.loginAsReadOnlyUser(); }); @@ -79,8 +94,12 @@ describe('Service overview: Time Comparison', () => { cy.contains('opbeans-java'); cy.get('[data-test-subj="comparisonSelect"]').should('be.enabled'); - const comparisonStartEnd = - 'comparisonStart=2021-08-02T06%3A50%3A00.000Z&comparisonEnd=2021-08-02T07%3A20%3A15.910Z'; + const comparisonStartEnd = `comparisonStart=${encodeURIComponent( + moment(start).subtract(1, 'day').toISOString() + )}&comparisonEnd=${encodeURIComponent( + moment(end).subtract(1, 'day').toISOString() + )}`; + // When the page loads it fetches all APIs with comparison time range cy.wait(apisToIntercept.map(({ name }) => `@${name}`)).then( (interceptions) => { diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts index 9180e6371fda7..3deb4b8619f60 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts @@ -6,9 +6,11 @@ */ import url from 'url'; -import archives_metadata from '../../../fixtures/es_archiver/archives_metadata'; +import { synthtrace } from '../../../../synthtrace'; +import { opbeans } from '../../../fixtures/synthtrace/opbeans'; -const { start, end } = archives_metadata['apm_8.0.0']; +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; const serviceOverviewHref = url.format({ pathname: '/app/apm/services/opbeans-node/transactions', @@ -16,6 +18,19 @@ const serviceOverviewHref = url.format({ }); describe('Transactions Overview', () => { + before(async () => { + await synthtrace.index( + opbeans({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + beforeEach(() => { cy.loginAsReadOnlyUser(); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts b/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts new file mode 100644 index 0000000000000..350d90ccb3fe4 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import Fs from 'fs'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; +import { SynthtraceEsClient } from '@elastic/apm-synthtrace'; +import { createLogger, LogLevel } from '@elastic/apm-synthtrace'; +import { CA_CERT_PATH } from '@kbn/dev-utils'; + +// *********************************************************** +// This example plugins/index.ts can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +/** + * @type {Cypress.PluginConfig} + */ +const plugin: Cypress.PluginConfig = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config + + const node = config.env.ES_NODE; + const requestTimeout = config.env.ES_REQUEST_TIMEOUT; + const isCloud = config.env.TEST_CLOUD; + + const client = new Client({ + node, + requestTimeout, + Connection: HttpConnection, + ...(isCloud ? { tls: { ca: Fs.readFileSync(CA_CERT_PATH, 'utf-8') } } : {}), + }); + + const synthtraceEsClient = new SynthtraceEsClient( + client, + createLogger(LogLevel.info) + ); + + on('task', { + 'synthtrace:index': async (events) => { + await synthtraceEsClient.index(events); + return null; + }, + 'synthtrace:clean': async () => { + await synthtraceEsClient.clean(); + return null; + }, + }); +}; + +module.exports = plugin; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress_start.ts b/x-pack/plugins/apm/ftr_e2e/cypress_start.ts index 0cfc58653801a..2d0be8c007089 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress_start.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress_start.ts @@ -10,7 +10,6 @@ import Url from 'url'; import cypress from 'cypress'; import { FtrProviderContext } from './ftr_provider_context'; -import archives_metadata from './cypress/fixtures/es_archiver/archives_metadata'; import { createApmUsersAndRoles } from '../scripts/create-apm-users-and-roles/create_apm_users_and_roles'; import { esArchiverLoad, esArchiverUnload } from './cypress/tasks/es_archiver'; @@ -35,8 +34,7 @@ async function cypressStart( ) { const config = getService('config'); - const archiveName = 'apm_8.0.0'; - const { start, end } = archives_metadata[archiveName]; + const archiveName = 'apm_mappings_only_8.0.0'; const kibanaUrl = Url.format({ protocol: config.get('servers.kibana.protocol'), @@ -56,21 +54,33 @@ async function cypressStart( }, }); - console.log('Loading esArchiver...'); - await esArchiverLoad('apm_8.0.0'); + const esNode = Url.format({ + protocol: config.get('servers.elasticsearch.protocol'), + port: config.get('servers.elasticsearch.port'), + hostname: config.get('servers.elasticsearch.hostname'), + auth: `${config.get('servers.elasticsearch.username')}:${config.get( + 'servers.elasticsearch.password' + )}`, + }); + + const esRequestTimeout = config.get('timeouts.esRequestTimeout'); + + console.log(`Loading ES archive "${archiveName}"`); + await esArchiverLoad(archiveName); const res = await cypressExecution({ ...(spec !== undefined ? { spec } : {}), config: { baseUrl: kibanaUrl }, env: { - START_DATE: start, - END_DATE: end, KIBANA_URL: kibanaUrl, + ES_NODE: esNode, + ES_REQUEST_TIMEOUT: esRequestTimeout, + TEST_CLOUD: process.env.TEST_CLOUD, }, }); - console.log('Removing esArchiver...'); - await esArchiverUnload('apm_8.0.0'); + console.log('Unloading ES archives...'); + await esArchiverUnload(archiveName); return res; } diff --git a/x-pack/plugins/apm/ftr_e2e/synthtrace.ts b/x-pack/plugins/apm/ftr_e2e/synthtrace.ts new file mode 100644 index 0000000000000..3c818b65200b6 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/synthtrace.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const synthtrace = { + index: (events: any[]) => + new Promise((resolve) => { + cy.task('synthtrace:index', events).then(resolve); + }), + clean: () => + new Promise((resolve) => { + cy.task('synthtrace:clean').then(resolve); + }), +}; diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx index 5e9095def6e55..9e113b37a1394 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx @@ -7,7 +7,6 @@ import { EuiFlexGroup, - EuiFlexGrid, EuiFlexItem, EuiPanel, EuiSpacer, @@ -73,28 +72,30 @@ export function ErrorGroupOverview() { return ( - - - - - + + + + + + + + + - - - - - - - + + + + diff --git a/x-pack/plugins/apm/public/components/app/service_map/index.tsx b/x-pack/plugins/apm/public/components/app/service_map/index.tsx index 75d5837f738c5..0ec1e6630003a 100644 --- a/x-pack/plugins/apm/public/components/app/service_map/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_map/index.tsx @@ -168,8 +168,8 @@ export function ServiceMap({ status === FETCH_STATUS.FAILURE && error && 'body' in error && - error.body.statusCode === 500 && - error.body.message === SERVICE_MAP_TIMEOUT_ERROR + error.body?.statusCode === 500 && + error.body?.message === SERVICE_MAP_TIMEOUT_ERROR ) { return ( diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx index aae6dddbec718..7e9b4325591d9 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx @@ -130,13 +130,11 @@ describe('ServiceOverview', () => { 'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate': { currentPeriod: { - transactionErrorRate: [], - noHits: true, + timeseries: [], average: null, }, previousPeriod: { - transactionErrorRate: [], - noHits: true, + timeseries: [], average: null, }, }, diff --git a/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx index cf57f618940b4..cda0058bdacd3 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx @@ -40,13 +40,11 @@ type ErrorRate = const INITIAL_STATE: ErrorRate = { currentPeriod: { - noHits: true, - transactionErrorRate: [], + timeseries: [], average: null, }, previousPeriod: { - noHits: true, - transactionErrorRate: [], + timeseries: [], average: null, }, }; @@ -116,7 +114,7 @@ export function FailedTransactionRateChart({ const timeseries = [ { - data: data.currentPeriod.transactionErrorRate, + data: data.currentPeriod.timeseries, type: 'linemark', color: theme.eui.euiColorVis7, title: i18n.translate('xpack.apm.errorRate.chart.errorRate', { @@ -126,7 +124,7 @@ export function FailedTransactionRateChart({ ...(comparisonEnabled ? [ { - data: data.previousPeriod.transactionErrorRate, + data: data.previousPeriod.timeseries, type: 'area', color: theme.eui.euiColorMediumShade, title: i18n.translate( diff --git a/x-pack/plugins/apm/public/hooks/use_fetcher.tsx b/x-pack/plugins/apm/public/hooks/use_fetcher.tsx index 72fb8ac0bb3cf..b77f6f9cf0fbb 100644 --- a/x-pack/plugins/apm/public/hooks/use_fetcher.tsx +++ b/x-pack/plugins/apm/public/hooks/use_fetcher.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import React, { useEffect, useMemo, useState } from 'react'; -import { IHttpFetchError } from 'src/core/public'; +import { IHttpFetchError, ResponseErrorBody } from 'src/core/public'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { useTimeRangeId } from '../context/time_range_id/use_time_range_id'; import { @@ -26,10 +26,12 @@ export enum FETCH_STATUS { export interface FetcherResult { data?: Data; status: FETCH_STATUS; - error?: IHttpFetchError; + error?: IHttpFetchError; } -function getDetailsFromErrorResponse(error: IHttpFetchError) { +function getDetailsFromErrorResponse( + error: IHttpFetchError +) { const message = error.body?.message ?? error.response?.statusText; return ( <> @@ -118,7 +120,7 @@ export function useFetcher( } as FetcherResult>); } } catch (e) { - const err = e as Error | IHttpFetchError; + const err = e as Error | IHttpFetchError; if (!signal.aborted) { const errorDetails = diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts index 48c2d555fd43b..741100aca16e9 100644 --- a/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts @@ -17,7 +17,6 @@ export interface TraceSample { } const INITIAL_DATA = { - noHits: true, traceSamples: [] as TraceSample[], }; @@ -71,16 +70,7 @@ export function useTransactionTraceSamplesFetcher({ }, }); - if (response.noHits) { - return response; - } - - const { traceSamples } = response; - - return { - noHits: false, - traceSamples, - }; + return response; } }, // the samples should not be refetched if the transactionId or traceId changes diff --git a/x-pack/plugins/apm/public/services/rest/callApi.ts b/x-pack/plugins/apm/public/services/rest/callApi.ts index 9b6d0c383e9a7..196878a08821e 100644 --- a/x-pack/plugins/apm/public/services/rest/callApi.ts +++ b/x-pack/plugins/apm/public/services/rest/callApi.ts @@ -66,7 +66,7 @@ export async function callApi( | 'delete' | 'patch'; - const res = await http[lowercaseMethod](pathname, options); + const res = await http[lowercaseMethod](pathname, options); if (isCachable(fetchOptions)) { cache.set(cacheKey, res); diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts index a2d22a2c8f6ad..dce8a3f397eaa 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -84,8 +84,5 @@ export async function getBuckets({ y: bucket.doc_count, }) ); - - return { - buckets: resp.hits.total.value > 0 ? buckets : [], - }; + return { buckets }; } diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts index 41dc33dfa193f..386372fbf655e 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts @@ -16,7 +16,5 @@ export function cancelEsRequestOnAbort>( controller.abort(); }); - promise.finally(() => subscription.unsubscribe()); - - return promise; + return promise.finally(() => subscription.unsubscribe()); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts index 06138931c004e..fb66cb9649085 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts @@ -123,7 +123,6 @@ export async function fetchAndTransformGcMetrics({ if (!aggregations) { return { ...chartBase, - noHits: true, series: [], }; } @@ -170,7 +169,6 @@ export async function fetchAndTransformGcMetrics({ return { ...chartBase, - noHits: response.hits.total.value === 0, series, }; } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts index addc17e5b09d8..828ee28260471 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts @@ -107,7 +107,7 @@ export async function getMemoryChartData({ operationName: 'get_cgroup_memory_metrics_charts', }); - if (cgroupResponse.noHits) { + if (cgroupResponse.series.length === 0) { return await fetchAndTransformMetrics({ environment, kuery, diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts index d626842a5f5dc..107e2d5774816 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts @@ -60,7 +60,6 @@ test('transformDataToMetricsChart should transform an ES result into a chart obj expect(chart).toMatchInlineSnapshot(` Object { "key": "test_chart_key", - "noHits": false, "series": Array [ Object { "color": "red", diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 999830dabefc4..7eaa90845d652 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -19,14 +19,13 @@ export function transformDataToMetricsChart( result: ESSearchResponse, chartBase: ChartBase ) { - const { aggregations, hits } = result; + const { aggregations } = result; const timeseriesData = aggregations?.timeseriesData; return { title: chartBase.title, key: chartBase.key, yUnit: chartBase.yUnit, - noHits: hits.total.value === 0, series: Object.keys(chartBase.series).map((seriesKey, i) => { const overallValue = aggregations?.[seriesKey]?.value; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/latency_correlations/latency_correlations_search_service.ts b/x-pack/plugins/apm/server/lib/search_strategies/latency_correlations/latency_correlations_search_service.ts index f170818d018d4..5fed2f4eb4dc4 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/latency_correlations/latency_correlations_search_service.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/latency_correlations/latency_correlations_search_service.ts @@ -151,7 +151,11 @@ export const latencyCorrelationsSearchServiceProvider: LatencyCorrelationsSearch params, percentileAggregationPercents ); - const percentiles = Object.values(percentilesRecords); + + // We need to round the percentiles values + // because the queries we're using based on it + // later on wouldn't allow numbers with decimals. + const percentiles = Object.values(percentilesRecords).map(Math.round); addLogMessage(`Loaded percentiles.`); diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts index afb88189a5fd2..e064d97bb7aee 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts @@ -49,8 +49,7 @@ describe('getServiceMapServiceNodeInfo', () => { it('returns data', async () => { jest.spyOn(getErrorRateModule, 'getErrorRate').mockResolvedValueOnce({ average: 0.5, - transactionErrorRate: [], - noHits: false, + timeseries: [{ x: 1634808240000, y: 0 }], }); const setup = { diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts index 43147684ef3f7..2f089adf70c1c 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts @@ -104,7 +104,7 @@ async function getErrorStats({ end, }: Options) { return withApmSpan('get_error_rate_for_service_map_node', async () => { - const { noHits, average } = await getErrorRate({ + const { average } = await getErrorRate({ environment, setup, serviceName, @@ -113,8 +113,7 @@ async function getErrorStats({ end, kuery: '', }); - - return { avgErrorRate: noHits ? null : average }; + return { avgErrorRate: average }; }); } diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts index ac1c2653bf148..308a1b9a2db26 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts @@ -55,12 +55,12 @@ export function getStoredAnnotations({ try { const response: ESSearchResponse = - await (unwrapEsResponse( + (await unwrapEsResponse( client.search({ index: annotationsClient.index, body, }) - ) as any); + )) as any; return response.hits.hits.map((hit) => { return { diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts index e85bd61ac440a..b7318e81a84a3 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts @@ -49,8 +49,7 @@ export async function getErrorRate({ start: number; end: number; }): Promise<{ - noHits: boolean; - transactionErrorRate: Coordinate[]; + timeseries: Coordinate[]; average: number | null; }> { const { apmEventClient } = setup; @@ -111,20 +110,16 @@ export async function getErrorRate({ 'get_transaction_group_error_rate', params ); - - const noHits = resp.hits.total.value === 0; - if (!resp.aggregations) { - return { noHits, transactionErrorRate: [], average: null }; + return { timeseries: [], average: null }; } - const transactionErrorRate = getFailedTransactionRateTimeSeries( + const timeseries = getFailedTransactionRateTimeSeries( resp.aggregations.timeseries.buckets ); - const average = calculateFailedTransactionRate(resp.aggregations.outcomes); - return { noHits, transactionErrorRate, average }; + return { timeseries, average }; } export async function getErrorRatePeriods({ @@ -171,22 +166,22 @@ export async function getErrorRatePeriods({ start: comparisonStart, end: comparisonEnd, }) - : { noHits: true, transactionErrorRate: [], average: null }; + : { timeseries: [], average: null }; const [currentPeriod, previousPeriod] = await Promise.all([ currentPeriodPromise, previousPeriodPromise, ]); - const firstCurrentPeriod = currentPeriod.transactionErrorRate; + const currentPeriodTimeseries = currentPeriod.timeseries; return { currentPeriod, previousPeriod: { ...previousPeriod, - transactionErrorRate: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firstCurrentPeriod, - previousPeriodTimeseries: previousPeriod.transactionErrorRate, + timeseries: offsetPreviousPeriodCoordinates({ + currentPeriodTimeseries, + previousPeriodTimeseries: previousPeriod.timeseries, }), }, }; diff --git a/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts b/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts index b085c0fc4a839..9b96cf19c516d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts @@ -93,19 +93,14 @@ export async function getTraceSamples({ }, }); - return response.hits.hits; + return response.hits.hits.map((hit) => ({ + transactionId: hit._source.transaction.id, + traceId: hit._source.trace.id, + })); } - const samplesForDistributionHits = await getTraceSamplesHits(); - - const traceSamples = samplesForDistributionHits.map((hit) => ({ - transactionId: hit._source.transaction.id, - traceId: hit._source.trace.id, - })); - return { - noHits: samplesForDistributionHits.length === 0, - traceSamples, + traceSamples: await getTraceSamplesHits(), }; }); } diff --git a/x-pack/plugins/canvas/public/application.tsx b/x-pack/plugins/canvas/public/application.tsx index 04d3958b68e36..937c9f56f948c 100644 --- a/x-pack/plugins/canvas/public/application.tsx +++ b/x-pack/plugins/canvas/public/application.tsx @@ -37,6 +37,7 @@ import { services, LegacyServicesProvider, CanvasPluginServices, + pluginServices as canvasServices, } from './services'; import { initFunctions } from './functions'; // @ts-expect-error untyped local @@ -151,7 +152,13 @@ export const initializeCanvas = async ( }, ], content: (domNode) => { - ReactDOM.render(, domNode); + ReactDOM.render( + , + domNode + ); return () => ReactDOM.unmountComponentAtNode(domNode); }, }); diff --git a/x-pack/plugins/canvas/public/components/function_reference_generator/function_reference_generator.tsx b/x-pack/plugins/canvas/public/components/function_reference_generator/function_reference_generator.tsx index b4d22d8e6e6db..49b5aaaf1b209 100644 --- a/x-pack/plugins/canvas/public/components/function_reference_generator/function_reference_generator.tsx +++ b/x-pack/plugins/canvas/public/components/function_reference_generator/function_reference_generator.tsx @@ -9,15 +9,16 @@ import React, { FC } from 'react'; import { ExpressionFunction } from 'src/plugins/expressions'; import { EuiButtonEmpty } from '@elastic/eui'; import copy from 'copy-to-clipboard'; -import { useNotifyService } from '../../services'; +import { CanvasPluginServices } from '../../services'; + import { generateFunctionReference } from './generate_function_reference'; interface Props { functionRegistry: Record; + notifyService: CanvasPluginServices['notify']; } -export const FunctionReferenceGenerator: FC = ({ functionRegistry }) => { - const notifyService = useNotifyService(); +export const FunctionReferenceGenerator: FC = ({ functionRegistry, notifyService }) => { const functionDefinitions = Object.values(functionRegistry); const copyDocs = () => { diff --git a/x-pack/plugins/canvas/public/components/help_menu/help_menu.tsx b/x-pack/plugins/canvas/public/components/help_menu/help_menu.tsx index af1850beb5290..9331de3fcad4b 100644 --- a/x-pack/plugins/canvas/public/components/help_menu/help_menu.tsx +++ b/x-pack/plugins/canvas/public/components/help_menu/help_menu.tsx @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunction } from 'src/plugins/expressions'; import { KeyboardShortcutsDoc } from '../keyboard_shortcuts_doc'; +import { CanvasPluginServices } from '../../services/'; let FunctionReferenceGenerator: null | React.LazyExoticComponent = null; @@ -31,9 +32,10 @@ const strings = { interface Props { functionRegistry: Record; + notifyService: CanvasPluginServices['notify']; } -export const HelpMenu: FC = ({ functionRegistry }) => { +export const HelpMenu: FC = ({ functionRegistry, notifyService }) => { const [isFlyoutVisible, setFlyoutVisible] = useState(false); const showFlyout = () => { @@ -53,7 +55,10 @@ export const HelpMenu: FC = ({ functionRegistry }) => { {FunctionReferenceGenerator ? ( - + ) : null} diff --git a/x-pack/plugins/canvas/public/routes/workpad/hooks/use_fullscreen_presentation_helper.ts b/x-pack/plugins/canvas/public/routes/workpad/hooks/use_fullscreen_presentation_helper.ts index 9021c6d6c2753..ca66fa227e4eb 100644 --- a/x-pack/plugins/canvas/public/routes/workpad/hooks/use_fullscreen_presentation_helper.ts +++ b/x-pack/plugins/canvas/public/routes/workpad/hooks/use_fullscreen_presentation_helper.ts @@ -5,6 +5,7 @@ * 2.0. */ import { useContext, useEffect } from 'react'; +import useEffectOnce from 'react-use/lib/useEffectOnce'; import { usePlatformService } from '../../../services'; import { WorkpadRoutingContext } from '..'; @@ -27,4 +28,10 @@ export const useFullscreenPresentationHelper = () => { setFullscreen(true); } }, [isFullscreen, setFullscreen]); + + // Remove fullscreen when component unmounts + useEffectOnce(() => () => { + setFullscreen(true); + document.querySelector('body')?.classList.remove(fullscreenClass); + }); }; diff --git a/x-pack/plugins/canvas/public/services/kibana/custom_element.ts b/x-pack/plugins/canvas/public/services/kibana/custom_element.ts index ec3b68d2d0bba..093373d55a3c5 100644 --- a/x-pack/plugins/canvas/public/services/kibana/custom_element.ts +++ b/x-pack/plugins/canvas/public/services/kibana/custom_element.ts @@ -25,8 +25,8 @@ export const customElementServiceFactory: CanvasCustomElementServiceFactory = ({ create: (customElement) => http.post(apiPath, { body: JSON.stringify(customElement) }), get: (customElementId) => http - .get(`${apiPath}/${customElementId}`) - .then(({ data: element }: { data: CustomElement }) => element), + .get<{ data: CustomElement }>(`${apiPath}/${customElementId}`) + .then(({ data: element }) => element), update: (id, element) => http.put(`${apiPath}/${id}`, { body: JSON.stringify(element) }), remove: (id) => http.delete(`${apiPath}/${id}`), find: async (name) => { diff --git a/x-pack/plugins/canvas/public/services/kibana/workpad.ts b/x-pack/plugins/canvas/public/services/kibana/workpad.ts index 35b82735845d0..9f69d5096237c 100644 --- a/x-pack/plugins/canvas/public/services/kibana/workpad.ts +++ b/x-pack/plugins/canvas/public/services/kibana/workpad.ts @@ -63,7 +63,7 @@ export const workpadServiceFactory: CanvasWorkpadServiceFactory = ({ coreStart, return { get: async (id: string) => { - const workpad = await coreStart.http.get(`${getApiPath()}/${id}`); + const workpad = await coreStart.http.get(`${getApiPath()}/${id}`); return { css: DEFAULT_WORKPAD_CSS, variables: [], ...workpad }; }, diff --git a/x-pack/plugins/canvas/public/setup_expressions.ts b/x-pack/plugins/canvas/public/setup_expressions.ts index e182d8efa097f..54f1c6dbc0d96 100644 --- a/x-pack/plugins/canvas/public/setup_expressions.ts +++ b/x-pack/plugins/canvas/public/setup_expressions.ts @@ -26,7 +26,7 @@ export const setupExpressions = async ({ const loadServerFunctionWrappers = async () => { if (!cached) { cached = (async () => { - const serverFunctionList = await coreSetup.http.get(API_ROUTE_FUNCTIONS); + const serverFunctionList = await coreSetup.http.get(API_ROUTE_FUNCTIONS); const batchedFunction = bfetch.batchedFunction({ url: API_ROUTE_FUNCTIONS }); const { serialize } = serializeProvider(expressions.getTypes()); diff --git a/x-pack/plugins/canvas/public/store.ts b/x-pack/plugins/canvas/public/store.ts index e8821bafbb052..7fe4eb21ee46f 100644 --- a/x-pack/plugins/canvas/public/store.ts +++ b/x-pack/plugins/canvas/public/store.ts @@ -32,7 +32,7 @@ export async function createFreshStore(core: CoreSetup) { const basePath = core.http.basePath.get(); // Retrieve server functions - const serverFunctionsResponse = await core.http.get(API_ROUTE_FUNCTIONS); + const serverFunctionsResponse = await core.http.get>(API_ROUTE_FUNCTIONS); const serverFunctions = Object.values(serverFunctionsResponse); initialState.app = { diff --git a/x-pack/plugins/canvas/server/sample_data/load_sample_data.ts b/x-pack/plugins/canvas/server/sample_data/load_sample_data.ts index 96d1789a7cae4..d891a5405a424 100644 --- a/x-pack/plugins/canvas/server/sample_data/load_sample_data.ts +++ b/x-pack/plugins/canvas/server/sample_data/load_sample_data.ts @@ -28,11 +28,16 @@ export function loadSampleData( return savedObject; }); } + const getPath = (objectId: string) => `/app/canvas#/workpad/${objectId}`; addSavedObjectsToSampleDataset('ecommerce', updateCanvasWorkpadTimestamps(ecommerceSavedObjects)); addAppLinksToSampleDataset('ecommerce', [ { - path: '/app/canvas#/workpad/workpad-e08b9bdb-ec14-4339-94c4-063bddfd610e', + sampleObject: { + type: 'canvas-workpad', + id: 'workpad-e08b9bdb-ec14-4339-94c4-063bddfd610e', + }, + getPath, icon: 'canvasApp', label, }, @@ -41,7 +46,11 @@ export function loadSampleData( addSavedObjectsToSampleDataset('flights', updateCanvasWorkpadTimestamps(flightsSavedObjects)); addAppLinksToSampleDataset('flights', [ { - path: '/app/canvas#/workpad/workpad-a474e74b-aedc-47c3-894a-db77e62c41e0', + sampleObject: { + type: 'canvas-workpad', + id: 'workpad-a474e74b-aedc-47c3-894a-db77e62c41e0', + }, + getPath, icon: 'canvasApp', label, }, @@ -50,7 +59,11 @@ export function loadSampleData( addSavedObjectsToSampleDataset('logs', updateCanvasWorkpadTimestamps(webLogsSavedObjects)); addAppLinksToSampleDataset('logs', [ { - path: '/app/canvas#/workpad/workpad-ad72a4e9-b422-480c-be6d-a64a0b79541d', + sampleObject: { + type: 'canvas-workpad', + id: 'workpad-ad72a4e9-b422-480c-be6d-a64a0b79541d', + }, + getPath, icon: 'canvasApp', label, }, diff --git a/x-pack/plugins/cases/public/containers/configure/api.ts b/x-pack/plugins/cases/public/containers/configure/api.ts index f7d0cf1ad9aef..1fd358e4dae9d 100644 --- a/x-pack/plugins/cases/public/containers/configure/api.ts +++ b/x-pack/plugins/cases/public/containers/configure/api.ts @@ -30,10 +30,10 @@ import { import { CaseConfigure } from './types'; export const fetchConnectors = async ({ signal }: ApiProps): Promise => { - const response = await KibanaServices.get().http.fetch(`${CASE_CONFIGURE_CONNECTORS_URL}/_find`, { - method: 'GET', - signal, - }); + const response = await KibanaServices.get().http.fetch( + `${CASE_CONFIGURE_CONNECTORS_URL}/_find`, + { method: 'GET', signal } + ); return response; }; @@ -97,10 +97,10 @@ export const patchCaseConfigure = async ( }; export const fetchActionTypes = async ({ signal }: ApiProps): Promise => { - const response = await KibanaServices.get().http.fetch(getAllConnectorTypesUrl(), { - method: 'GET', - signal, - }); + const response = await KibanaServices.get().http.fetch( + getAllConnectorTypesUrl(), + { method: 'GET', signal } + ); return convertArrayToCamelCase(response) as ActionTypeConnector[]; }; diff --git a/x-pack/plugins/cloud/public/plugin.test.ts b/x-pack/plugins/cloud/public/plugin.test.ts index c1c94375d7063..43659d137a6e0 100644 --- a/x-pack/plugins/cloud/public/plugin.test.ts +++ b/x-pack/plugins/cloud/public/plugin.test.ts @@ -348,7 +348,7 @@ describe('Cloud Plugin', () => { expect(coreStart.chrome.setCustomNavLink.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { - "euiIconType": "arrowLeft", + "euiIconType": "logoCloud", "href": "https://cloud.elastic.co/abc123", "title": "Manage this deployment", }, @@ -370,7 +370,7 @@ describe('Cloud Plugin', () => { expect(coreStart.chrome.setCustomNavLink.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { - "euiIconType": "arrowLeft", + "euiIconType": "logoCloud", "href": "https://cloud.elastic.co/abc123", "title": "Manage this deployment", }, diff --git a/x-pack/plugins/cloud/public/plugin.ts b/x-pack/plugins/cloud/public/plugin.ts index 64b03acdc3ffd..e71b145c438ed 100644 --- a/x-pack/plugins/cloud/public/plugin.ts +++ b/x-pack/plugins/cloud/public/plugin.ts @@ -131,7 +131,7 @@ export class CloudPlugin implements Plugin { title: i18n.translate('xpack.cloud.deploymentLinkLabel', { defaultMessage: 'Manage this deployment', }), - euiIconType: 'arrowLeft', + euiIconType: 'logoCloud', href: getFullCloudUrl(baseUrl, deploymentUrl), }); } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts index 3f6436424a63b..68916164f3189 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.ts @@ -160,7 +160,7 @@ export const AnalyticsLogic = kea(url, { query }); actions.onAnalyticsDataLoad(response); } catch (e) { flashAPIErrors(e); @@ -180,7 +180,7 @@ export const AnalyticsLogic = kea(url, { query: queryParams }); actions.onQueryDataLoad(response); } catch (e) { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx index 0b65c59a18419..e7c98332ee651 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx @@ -86,7 +86,7 @@ export const ACTIONS_COLUMN = { try { const query = (item as Query).key || (item as RecentQuery).query_string || '""'; - const response = await http.get( + const response = await http.get<{ id: string }>( `/internal/app_search/engines/${engineName}/curations/find_or_create`, { query: { query } } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs_logic.ts index 86c8ec8c5fbd1..800e038cc1923 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/api_logs_logic.ts @@ -104,14 +104,17 @@ export const ApiLogsLogic = kea>({ const { engineName } = EngineLogic.values; try { - const response = await http.get(`/internal/app_search/engines/${engineName}/api_logs`, { - query: { - 'page[current]': values.meta.page.current, - 'filters[date][from]': getDateString(-1), - 'filters[date][to]': getDateString(), - sort_direction: 'desc', - }, - }); + const response = await http.get( + `/internal/app_search/engines/${engineName}/api_logs`, + { + query: { + 'page[current]': values.meta.page.current, + 'filters[date][from]': getDateString(-1), + 'filters[date][to]': getDateString(), + sort_direction: 'desc', + }, + } + ); // Manual fetches (e.g. page load, user pagination) should update the view immediately, // while polls are stored in-state until the user manually triggers the 'Refresh' action diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/add_domain/add_domain_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/add_domain/add_domain_logic.ts index ab85f8a585d1a..494d123cae125 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/add_domain/add_domain_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/add_domain/add_domain_logic.ts @@ -23,6 +23,7 @@ import { CrawlerDomain, CrawlerDomainValidationResult, CrawlerDomainValidationResultChange, + CrawlerDomainValidationResultFromServer, CrawlerDomainValidationStepName, } from '../../types'; import { crawlDomainValidationToResult, crawlerDataServerToClient } from '../../utils'; @@ -207,7 +208,7 @@ export const AddDomainLogic = kea(route, { body: JSON.stringify({ url: values.addDomainFormInputValue.trim(), checks }), }); const result = crawlDomainValidationToResult(data); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.ts index 5b9960ddf54e0..d1530c79a6821 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.ts @@ -12,7 +12,14 @@ import { flashAPIErrors } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; import { EngineLogic } from '../engine'; -import { CrawlerData, CrawlerDomain, CrawlEvent, CrawlRequest, CrawlerStatus } from './types'; +import { + CrawlerData, + CrawlerDomain, + CrawlEvent, + CrawlRequest, + CrawlerStatus, + CrawlerDataFromServer, +} from './types'; import { crawlerDataServerToClient } from './utils'; const POLLING_DURATION = 1000; @@ -104,7 +111,9 @@ export const CrawlerLogic = kea>({ const { engineName } = EngineLogic.values; try { - const response = await http.get(`/internal/app_search/engines/${engineName}/crawler`); + const response = await http.get( + `/internal/app_search/engines/${engineName}/crawler` + ); const crawlerData = crawlerDataServerToClient(response); actions.onReceiveCrawlerData(crawlerData); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview_logic.ts index c6a26e50a6758..605d45effaa24 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview_logic.ts @@ -13,7 +13,7 @@ import { HttpLogic } from '../../../shared/http'; import { EngineLogic } from '../engine'; import { CrawlerLogic } from './crawler_logic'; -import { CrawlerDomain } from './types'; +import { CrawlerDataFromServer, CrawlerDomain } from './types'; import { crawlerDataServerToClient, getDeleteDomainSuccessMessage } from './utils'; interface CrawlerOverviewActions { @@ -31,7 +31,7 @@ export const CrawlerOverviewLogic = kea( `/internal/app_search/engines/${engineName}/crawler/domains/${domain.id}`, { query: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_single_domain_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_single_domain_logic.ts index 9452ae1d578ed..64687e24ccb29 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_single_domain_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_single_domain_logic.ts @@ -16,7 +16,7 @@ import { EngineLogic, generateEnginePath } from '../engine'; import { CrawlerLogic } from './crawler_logic'; -import { CrawlerDomain, EntryPoint, Sitemap, CrawlRule } from './types'; +import { CrawlerDomain, EntryPoint, Sitemap, CrawlRule, CrawlerDomainFromServer } from './types'; import { crawlerDomainServerToClient, getDeleteDomainSuccessMessage } from './utils'; export interface CrawlerSingleDomainValues { @@ -92,7 +92,7 @@ export const CrawlerSingleDomainLogic = kea< const { engineName } = EngineLogic.values; try { - const response = await http.get( + const response = await http.get( `/internal/app_search/engines/${engineName}/crawler/domains/${domainId}` ); @@ -113,7 +113,7 @@ export const CrawlerSingleDomainLogic = kea< }; try { - const response = await http.put( + const response = await http.put( `/internal/app_search/engines/${engineName}/crawler/domains/${domain.id}`, { body: JSON.stringify(payload), diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts index 52e1b1825b180..30380b8b41e3b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts @@ -239,7 +239,10 @@ export const CredentialsLogic = kea({ 'page[current]': meta.page.current, 'page[size]': meta.page.size, }; - const response = await http.get('/internal/app_search/credentials', { query }); + const response = await http.get<{ meta: Meta; results: ApiToken[] }>( + '/internal/app_search/credentials', + { query } + ); actions.setCredentialsData(response.meta, response.results); } catch (e) { flashAPIErrors(e); @@ -248,7 +251,9 @@ export const CredentialsLogic = kea({ fetchDetails: async () => { try { const { http } = HttpLogic.values; - const response = await http.get('/internal/app_search/credentials/details'); + const response = await http.get( + '/internal/app_search/credentials/details' + ); actions.setCredentialsDetails(response); } catch (e) { @@ -287,11 +292,13 @@ export const CredentialsLogic = kea({ const body = JSON.stringify(data); if (id) { - const response = await http.put(`/internal/app_search/credentials/${name}`, { body }); + const response = await http.put(`/internal/app_search/credentials/${name}`, { + body, + }); actions.onApiTokenUpdateSuccess(response); flashSuccessToast(UPDATE_MESSAGE(name)); } else { - const response = await http.post('/internal/app_search/credentials', { body }); + const response = await http.post('/internal/app_search/credentials', { body }); actions.onApiTokenCreateSuccess(response); flashSuccessToast(CREATE_MESSAGE(name)); } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx index 4248eb62e33f1..3e12aa7b629f0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx @@ -122,7 +122,7 @@ describe('SuggestionsLogic', () => { await nextTick(); expect(http.post).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify({ page: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx index 074d2114ee8cb..16c32c9bb0545 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx @@ -74,8 +74,8 @@ export const SuggestionsLogic = kea( + `/internal/app_search/engines/${engineName}/adaptive_relevance/suggestions`, { body: JSON.stringify({ page: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts index b1f16944c985b..2b51cbb884ff9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts @@ -295,7 +295,7 @@ describe('CurationLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify([ { @@ -412,6 +412,7 @@ describe('CurationLogic', () => { expect(http.put).toHaveBeenCalledWith( '/internal/app_search/engines/some-engine/curations/cur-123456789', { + query: { skip_record_analytics: 'true' }, body: '{"queries":["a","b","c"],"query":"b","promoted":["d","e","f"],"hidden":["g"]}', // Uses state currently in CurationLogic } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts index 6393ccf974225..08bf8cfd179eb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts @@ -194,15 +194,18 @@ export const CurationLogic = kea( `/internal/app_search/engines/${engineName}/curations/${props.curationId}`, { query: { skip_record_analytics: 'true' } } ); @@ -248,9 +251,10 @@ export const CurationLogic = kea( `/internal/app_search/engines/${engineName}/curations/${props.curationId}`, { + query: { skip_record_analytics: 'true' }, body: JSON.stringify({ queries: values.queries, query: values.activeQuery, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts index 487072584583f..422c2e8575162 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts @@ -85,12 +85,15 @@ export const CurationsLogic = kea( + `/internal/app_search/engines/${engineName}/curations`, + { + query: { + 'page[current]': meta.page.current, + 'page[size]': meta.page.size, + }, + } + ); actions.onCurationsLoad(response); } catch (e) { flashAPIErrors(e); @@ -118,9 +121,10 @@ export const CurationsLogic = kea( + `/internal/app_search/engines/${engineName}/curations`, + { body: JSON.stringify({ queries }) } + ); navigateToUrl(generateEnginePath(ENGINE_CURATION_PATH, { curationId: response.id })); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts index e6a847f6e9ec6..171c774d8add2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts @@ -241,7 +241,7 @@ describe('CurationSuggestionLogic', () => { await nextTick(); expect(http.get).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions/foo-query', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions/foo-query', { query: { type: 'curation', @@ -297,7 +297,7 @@ describe('CurationSuggestionLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify([ { @@ -380,7 +380,7 @@ describe('CurationSuggestionLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify([ { @@ -463,7 +463,7 @@ describe('CurationSuggestionLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify([ { @@ -508,7 +508,7 @@ describe('CurationSuggestionLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify([ { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts index 8e6c3a9c6a6ae..0e774d811f3be 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts @@ -79,8 +79,9 @@ export const CurationSuggestionLogic = kea< const { engineName } = EngineLogic.values; try { - const suggestionResponse = await http.get( - `/internal/app_search/engines/${engineName}/search_relevance_suggestions/${props.query}`, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const suggestionResponse = await http.get( + `/internal/app_search/engines/${engineName}/adaptive_relevance/suggestions/${props.query}`, { query: { type: 'curation', @@ -250,7 +251,7 @@ const updateSuggestion = async ( status: string ) => { const response = await http.put<{ results: Array }>( - `/internal/app_search/engines/${engineName}/search_relevance_suggestions`, + `/internal/app_search/engines/${engineName}/adaptive_relevance/suggestions`, { body: JSON.stringify([ { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.test.ts index 83a200943256b..8c2545fad651a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.test.ts @@ -114,7 +114,7 @@ describe('IgnoredQueriesLogic', () => { await nextTick(); expect(http.post).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify({ page: { @@ -170,7 +170,7 @@ describe('IgnoredQueriesLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', + '/internal/app_search/engines/some-engine/adaptive_relevance/suggestions', { body: JSON.stringify([ { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.ts index e36b5bc156b46..798117ec353d4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_history/components/ignored_queries_panel/ignored_queries_logic.ts @@ -89,7 +89,7 @@ export const IgnoredQueriesLogic = kea; - }>(`/internal/app_search/engines/${engineName}/search_relevance_suggestions`, { + }>(`/internal/app_search/engines/${engineName}/adaptive_relevance/suggestions`, { body: JSON.stringify([ { query: ignoredQuery, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.test.ts index b8aae9c39174d..0d09f2d28f396 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.test.ts @@ -97,7 +97,7 @@ describe('CurationsSettingsLogic', () => { await nextTick(); expect(http.get).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions/settings' + '/internal/app_search/engines/some-engine/adaptive_relevance/settings' ); expect(CurationsSettingsLogic.actions.onCurationsSettingsLoad).toHaveBeenCalledWith({ enabled: true, @@ -204,7 +204,7 @@ describe('CurationsSettingsLogic', () => { await nextTick(); expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions/settings', + '/internal/app_search/engines/some-engine/adaptive_relevance/settings', { body: JSON.stringify({ curation: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.ts index 3984cbd024da4..692d893a8e22f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations_settings/curations_settings_logic.ts @@ -71,8 +71,8 @@ export const CurationsSettingsLogic = kea< const { engineName } = EngineLogic.values; try { - const response = await http.get( - `/internal/app_search/engines/${engineName}/search_relevance_suggestions/settings` + const response = await http.get<{ curation: CurationsSettings }>( + `/internal/app_search/engines/${engineName}/adaptive_relevance/settings` ); actions.onCurationsSettingsLoad(response.curation); } catch (e) { @@ -95,8 +95,8 @@ export const CurationsSettingsLogic = kea< const { http } = HttpLogic.values; const { engineName } = EngineLogic.values; try { - const response = await http.put( - `/internal/app_search/engines/${engineName}/search_relevance_suggestions/settings`, + const response = await http.put<{ curation: CurationsSettings }>( + `/internal/app_search/engines/${engineName}/adaptive_relevance/settings`, { body: JSON.stringify({ curation: currationsSetting }), } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts index e92bc068824b0..5ea2f0fe7cf73 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.ts @@ -181,7 +181,10 @@ export const DocumentCreationLogic = kea< const promises = chunk(documents, CHUNK_SIZE).map((documentsChunk) => { const body = JSON.stringify({ documents: documentsChunk }); - return http.post(`/internal/app_search/engines/${engineName}/documents`, { body }); + return http.post( + `/internal/app_search/engines/${engineName}/documents`, + { body } + ); }); try { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts index 25c16a7df2c50..9c41c55f5033c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.ts @@ -59,7 +59,7 @@ export const DocumentDetailLogic = kea({ try { const { http } = HttpLogic.values; - const response = await http.get( + const response = await http.get<{ fields: FieldDetails[] }>( `/internal/app_search/engines/${engineName}/documents/${documentId}` ); actions.setFields(response.fields); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts index aa5e15a3265b1..0cfe8d0c2f933 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts @@ -132,7 +132,9 @@ export const EngineLogic = kea>({ const { http } = HttpLogic.values; try { - const response = await http.get(`/internal/app_search/engines/${engineName}`); + const response = await http.get( + `/internal/app_search/engines/${engineName}` + ); actions.setEngineData(response); } catch (error) { if (error?.response?.status >= 400 && error?.response?.status < 500) { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.ts index 73cfef8530521..878681a728e2b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.ts @@ -84,7 +84,9 @@ export const EngineOverviewLogic = kea( + `/internal/app_search/engines/${engineName}/overview` + ); actions.onOverviewMetricsLoad(response); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.ts index 507b83cc8b5cf..c6fb1a401c591 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.ts @@ -119,7 +119,7 @@ export const EnginesLogic = kea>({ const { enginesMeta } = values; try { - const response = await http.get('/internal/app_search/engines', { + const response = await http.get('/internal/app_search/engines', { query: { type: 'indexed', 'page[current]': enginesMeta.page.current, @@ -136,7 +136,7 @@ export const EnginesLogic = kea>({ const { metaEnginesMeta } = values; try { - const response = await http.get('/internal/app_search/engines', { + const response = await http.get('/internal/app_search/engines', { query: { type: 'meta', 'page[current]': metaEnginesMeta.page.current, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts index c94de74b5ab22..fd2ed0693257d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts @@ -246,7 +246,7 @@ export const RelevanceTuningLogic = kea< const url = `/internal/app_search/engines/${engineName}/search_settings/details`; try { - const response = await http.get(url); + const response = await http.get(url); actions.onInitializeRelevanceTuning({ ...response, searchSettings: { @@ -278,7 +278,7 @@ export const RelevanceTuningLogic = kea< const filteredBoosts = removeEmptyValueBoosts(boosts); try { - const response = await http.post(url, { + const response = await http.post<{ results: Result[] }>(url, { query: { query, }, @@ -313,7 +313,7 @@ export const RelevanceTuningLogic = kea< const url = `/internal/app_search/engines/${engineName}/search_settings`; try { - const response = await http.put(url, { + const response = await http.put(url, { body: JSON.stringify(removeBoostStateProps(values.searchSettings)), }); flashSuccessToast(UPDATE_SUCCESS_MESSAGE, { text: SUCCESS_CHANGES_MESSAGE }); @@ -337,7 +337,7 @@ export const RelevanceTuningLogic = kea< const url = `/internal/app_search/engines/${engineName}/search_settings/reset`; try { - const response = await http.post(url); + const response = await http.post(url); flashSuccessToast(DELETE_SUCCESS_MESSAGE, { text: SUCCESS_CHANGES_MESSAGE }); actions.onSearchSettingsSuccess(response); } catch (e) { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts index 5ff153c3beb64..99b3e6157e227 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings_logic.ts @@ -12,13 +12,14 @@ import { i18n } from '@kbn/i18n'; import { flashAPIErrors, flashSuccessToast } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; -import { Schema, SchemaConflicts } from '../../../shared/schema/types'; +import { Schema, SchemaConflicts, SchemaType } from '../../../shared/schema/types'; import { EngineLogic } from '../engine'; import { DEFAULT_SNIPPET_SIZE } from './constants'; import { FieldResultSetting, FieldResultSettingObject, + ServerFieldResultSetting, ServerFieldResultSettingObject, } from './types'; @@ -299,7 +300,11 @@ export const ResultSettingsLogic = kea; + schemaConflicts?: SchemaConflicts; + searchSettings: { result_fields: Record }; + }>(url); actions.initializeResultFields(serverFieldResultSettings, schema, schemaConflicts); } catch (e) { @@ -322,7 +327,9 @@ export const ResultSettingsLogic = kea; + }>(url, { body: JSON.stringify({ result_fields: values.reducedServerResultFields, }), diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/sample_response/sample_response_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/sample_response/sample_response_logic.ts index d4c5a842daac9..34f1478ad24fe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/sample_response/sample_response_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/sample_response/sample_response_logic.ts @@ -14,6 +14,7 @@ import { flashAPIErrors } from '../../../../shared/flash_messages'; import { HttpLogic } from '../../../../shared/http'; import { EngineLogic } from '../../engine'; +import { FieldValue } from '../../result/types'; import { SampleSearchResponse, ServerFieldResultSettingObject } from '../types'; const NO_RESULTS_MESSAGE = i18n.translate( @@ -71,7 +72,7 @@ export const SampleResponseLogic = kea> }>(url, { query: { query }, body: JSON.stringify({ page: { @@ -84,6 +85,7 @@ export const SampleResponseLogic = kea(route); actions.setRoleMappings(response); } catch (e) { flashAPIErrors(e); @@ -367,7 +367,7 @@ export const RoleMappingsLogic = kea(route); actions.setRoleMappingsData(response); } catch (e) { flashAPIErrors(e); @@ -466,7 +466,10 @@ export const RoleMappingsLogic = kea( + '/internal/app_search/single_user_role_mapping', + { body } + ); actions.setSingleUserRoleMapping(response); actions.setUserCreated(); actions.initializeRoleMappings(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/reindex_job/reindex_job_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/reindex_job/reindex_job_logic.ts index fb50c9390a8d9..e8ac47dbecbf2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/reindex_job/reindex_job_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/reindex_job/reindex_job_logic.ts @@ -53,7 +53,7 @@ export const ReindexJobLogic = kea( `/internal/app_search/engines/${engineName}/reindex_job/${id}` ); actions.onLoadSuccess(response); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_base_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_base_logic.ts index b9107666a881b..b299f827676d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_base_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_base_logic.ts @@ -56,7 +56,9 @@ export const SchemaBaseLogic = kea( + `/internal/app_search/engines/${engineName}/schema` + ); actions.onSchemaLoad(response); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_logic.ts index b26fd92064582..536a63700c5cd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/schema/schema_logic.ts @@ -146,9 +146,10 @@ export const SchemaLogic = kea>({ clearFlashMessages(); try { - const response = await http.post(`/internal/app_search/engines/${engineName}/schema`, { - body: JSON.stringify(schema), - }); + const response = await http.post( + `/internal/app_search/engines/${engineName}/schema`, + { body: JSON.stringify(schema) } + ); actions.onSchemaLoad(response); flashSuccessToast(successMessage || UPDATE_SCHEMA_SUCCESS); } catch (e) { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts index 424baedf210f5..1b14b89f81a4b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts @@ -61,9 +61,10 @@ export const SearchLogic = kea>({ const { engineName } = EngineLogic.values; try { - const response = await http.post(`/internal/app_search/engines/${engineName}/search`, { - query: { query }, - }); + const response = await http.post<{ results: Result[] }>( + `/internal/app_search/engines/${engineName}/search`, + { query: { query } } + ); actions.onSearch(response); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui_logic.ts index 7a3e429d842f8..1466cfa1ff9b7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui_logic.ts @@ -106,7 +106,11 @@ export const SearchUILogic = kea> const url = `/internal/app_search/engines/${engineName}/search_ui/field_config`; try { - const initialFieldValues = await http.get(url); + const initialFieldValues = await http.get< + InitialFieldValues & { + defaultValues: Pick; + } + >(url); const { defaultValues: { urlField, titleField }, validFields, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/synonyms_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/synonyms_logic.ts index 123a2e50fdf2f..906877e79fedf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/synonyms_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/synonyms/synonyms_logic.ts @@ -115,12 +115,15 @@ export const SynonymsLogic = kea> const { engineName } = EngineLogic.values; try { - const response = await http.get(`/internal/app_search/engines/${engineName}/synonyms`, { - query: { - 'page[current]': meta.page.current, - 'page[size]': meta.page.size, - }, - }); + const response = await http.get( + `/internal/app_search/engines/${engineName}/synonyms`, + { + query: { + 'page[current]': meta.page.current, + 'page[size]': meta.page.size, + }, + } + ); actions.onSynonymsLoad(response); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/generic_endpoint_inline_editable_table/generic_endpoint_inline_editable_table_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/tables/generic_endpoint_inline_editable_table/generic_endpoint_inline_editable_table_logic.ts index 9cb1061993dc3..71c993dca9cb9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/generic_endpoint_inline_editable_table/generic_endpoint_inline_editable_table_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/generic_endpoint_inline_editable_table/generic_endpoint_inline_editable_table_logic.ts @@ -83,7 +83,9 @@ export const GenericEndpointInlineEditableTableLogic = kea< const { addRoute, onAdd, dataProperty } = props; try { - const response = await http.post(addRoute, { body: JSON.stringify(item) }); + const response = await http.post>(addRoute, { + body: JSON.stringify(item), + }); const itemsFromResponse = response[dataProperty]; onAdd(item, itemsFromResponse); @@ -99,7 +101,7 @@ export const GenericEndpointInlineEditableTableLogic = kea< const { deleteRoute, onDelete, dataProperty } = props; try { - const response = await http.delete(deleteRoute(item)); + const response = await http.delete>(deleteRoute(item)); const itemsFromResponse = response[dataProperty]; onDelete(item, itemsFromResponse); @@ -116,7 +118,7 @@ export const GenericEndpointInlineEditableTableLogic = kea< const dataToSubmit = stripIdAndCreatedAtFromItem(item); try { - const response = await http.put(updateRoute(item), { + const response = await http.put>(updateRoute(item), { body: JSON.stringify(dataToSubmit), }); const itemsFromResponse = response[dataProperty]; @@ -141,7 +143,7 @@ export const GenericEndpointInlineEditableTableLogic = kea< try { actions.setLoading(); - const response = await http.put(reorderRoute, { + const response = await http.put>(reorderRoute, { body: JSON.stringify({ [dataProperty]: reorderedItemIds }), }); const itemsFromResponse = response[dataProperty]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts index 6f09cbb15c7db..06055e9562676 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts @@ -392,7 +392,7 @@ export const AddSourceLogic = kea(route); actions.setSourceConfigData(response); } catch (e) { flashAPIErrors(e); @@ -415,7 +415,7 @@ export const AddSourceLogic = kea(route, { query }); actions.setSourceConnectData(response); successCallback(response.oauthUrl); } catch (e) { @@ -435,7 +435,7 @@ export const AddSourceLogic = kea(route, { query }); actions.setSourceConnectData(response); } catch (e) { flashAPIErrors(e); @@ -449,7 +449,7 @@ export const AddSourceLogic = kea(route); actions.setPreContentSourceConfigData(response); } catch (e) { flashAPIErrors(e); @@ -482,7 +482,7 @@ export const AddSourceLogic = kea(route, { body: JSON.stringify(params), }); if (successCallback) successCallback(); @@ -527,7 +527,13 @@ export const AddSourceLogic = kea(route, { query }); const { serviceName, indexPermissions, serviceType, preContentSourceId, hasConfigureStep } = response; @@ -574,7 +580,7 @@ export const AddSourceLogic = kea params[key] === undefined && delete params[key]); try { - const response = await HttpLogic.values.http.post(route, { + const response = await HttpLogic.values.http.post(route, { body: JSON.stringify({ ...params }), }); actions.setCustomSourceData(response); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts index 2d7667e08d8f8..d62bd6252f130 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts @@ -381,8 +381,10 @@ export const DisplaySettingsLogic = kea< : `/internal/workplace_search/account/sources/${sourceId}/display_settings/config`; try { - const response = await HttpLogic.values.http.get(route); + const response = await HttpLogic.values.http.get(route); actions.onInitializeDisplaySettings({ + // isOrganization is not typed + // @ts-expect-error TS2345 isOrganization, sourceId, serverRoute: route, @@ -396,9 +398,10 @@ export const DisplaySettingsLogic = kea< const { searchResultConfig, serverRoute } = values; try { - const response = await HttpLogic.values.http.post(serverRoute, { - body: JSON.stringify({ ...searchResultConfig }), - }); + const response = await HttpLogic.values.http.post( + serverRoute, + { body: JSON.stringify({ ...searchResultConfig }) } + ); actions.setServerResponseData(response); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts index d664197afaa26..218bb368e848f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/schema/schema_logic.ts @@ -272,7 +272,9 @@ export const SchemaLogic = kea>({ : `/internal/workplace_search/account/sources/${sourceId}/schemas`; try { - const response = await http.get(route); + const response = await http.get(route); + // TODO: fix + // @ts-expect-error TS2783 actions.onInitializeSchema({ sourceId, ...response }); } catch (e) { flashAPIErrors(e); @@ -287,7 +289,7 @@ export const SchemaLogic = kea>({ try { await actions.initializeSchema(); - const response = await http.get(route); + const response = await http.get(route); actions.onInitializeSchemaFieldErrors({ fieldCoercionErrors: response.fieldCoercionErrors, }); @@ -339,7 +341,7 @@ export const SchemaLogic = kea>({ actions.resetMostRecentIndexJob(emptyReindexJob); try { - const response = await http.post(route, { + const response = await http.post(route, { body: JSON.stringify({ ...updatedSchema }), }); actions.onSchemaSetSuccess(response); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts index 87a55f0e7dd3a..2f4fdca44d441 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts @@ -20,10 +20,12 @@ import { BLOCKED_TIME_WINDOWS_PATH, getContentSourcePath, } from '../../../../routes'; + import { BlockedWindow, DayOfWeek, IndexingSchedule, + ContentSourceFullData, SyncJobType, TimeUnit, } from '../../../../types'; @@ -313,7 +315,7 @@ export const SynchronizationLogic = kea< const route = `/internal/workplace_search/org/sources/${sourceId}/settings`; try { - const response = await HttpLogic.values.http.patch(route, { + const response = await HttpLogic.values.http.patch(route, { body: JSON.stringify(body), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts index 0b67e3f2da79b..e97d48889d809 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts @@ -159,7 +159,9 @@ export const SourceLogic = kea>({ : `/internal/workplace_search/account/sources/${sourceId}`; try { - const response = await HttpLogic.values.http.get(route); + const response = await HttpLogic.values.http.get< + ContentSourceFullData & { errors?: string } + >(route); actions.setContentSource(response); if (response.isFederatedSource) { actions.initializeFederatedSummary(sourceId); @@ -186,7 +188,7 @@ export const SourceLogic = kea>({ initializeFederatedSummary: async ({ sourceId }) => { const route = `/internal/workplace_search/account/sources/${sourceId}/federated_summary`; try { - const response = await HttpLogic.values.http.get(route); + const response = await HttpLogic.values.http.get<{ summary: DocumentSummaryItem[] }>(route); actions.onUpdateSummary(response.summary); } catch (e) { flashAPIErrors(e); @@ -206,7 +208,7 @@ export const SourceLogic = kea>({ } = values; try { - const response = await HttpLogic.values.http.post(route, { + const response = await HttpLogic.values.http.post(route, { body: JSON.stringify({ query, page }), }); actions.setSearchResults(response); @@ -221,7 +223,7 @@ export const SourceLogic = kea>({ : `/internal/workplace_search/account/sources/${sourceId}/settings`; try { - const response = await HttpLogic.values.http.patch(route, { + const response = await HttpLogic.values.http.patch<{ name: string }>(route, { body: JSON.stringify({ content_source: source }), }); if (source.name) { @@ -239,7 +241,7 @@ export const SourceLogic = kea>({ : `/internal/workplace_search/account/sources/${sourceId}`; try { - const response = await HttpLogic.values.http.delete(route); + const response = await HttpLogic.values.http.delete<{ name: string }>(route); KibanaLogic.values.navigateToUrl(getSourcesPath(SOURCES_PATH, isOrganization)); flashSuccessToast( i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts index b2c53b0a4b549..90b1f83281e94 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts @@ -163,7 +163,7 @@ export const SourcesLogic = kea>( : '/internal/workplace_search/account/sources'; try { - const response = await HttpLogic.values.http.get(route); + const response = await HttpLogic.values.http.get(route); breakpoint(); // Prevents errors if logic unmounts while fetching actions.pollForSourceStatusChanges(); actions.onInitializeSources(response); @@ -256,7 +256,7 @@ export const fetchSourceStatuses = async ( let response; try { - response = await HttpLogic.values.http.get(route); + response = await HttpLogic.values.http.get(route); breakpoint(); SourcesLogic.actions.setServerSourceStatuses(response); } catch (e) { @@ -267,7 +267,8 @@ export const fetchSourceStatuses = async ( } } - return response; + // TODO: remove casting. return type should be ContentSourceStatus[] | undefined + return response as ContentSourceStatus[]; }; const updateSourcesOnToggle = ( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts index 3ba7d68d0b3e9..6e465854ff44f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts @@ -174,7 +174,7 @@ export const GroupLogic = kea>({ listeners: ({ actions, values }) => ({ initializeGroup: async ({ groupId }) => { try { - const response = await HttpLogic.values.http.get( + const response = await HttpLogic.values.http.get( `/internal/workplace_search/groups/${groupId}` ); actions.onInitializeGroup(response); @@ -220,7 +220,7 @@ export const GroupLogic = kea>({ } = values; try { - const response = await HttpLogic.values.http.put( + const response = await HttpLogic.values.http.put( `/internal/workplace_search/groups/${id}`, { body: JSON.stringify({ group: { name: groupNameInputValue } }), @@ -247,7 +247,7 @@ export const GroupLogic = kea>({ } = values; try { - const response = await HttpLogic.values.http.post( + const response = await HttpLogic.values.http.post( `/internal/workplace_search/groups/${id}/share`, { body: JSON.stringify({ content_source_ids: selectedGroupSources }), @@ -279,7 +279,7 @@ export const GroupLogic = kea>({ ); try { - const response = await HttpLogic.values.http.put( + const response = await HttpLogic.values.http.put( `/internal/workplace_search/groups/${id}/boosts`, { body: JSON.stringify({ content_source_boosts: boosts }), diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts index 19c16f6147dcc..c14538346ad31 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts @@ -255,7 +255,9 @@ export const GroupsLogic = kea>({ listeners: ({ actions, values }) => ({ initializeGroups: async () => { try { - const response = await HttpLogic.values.http.get('/internal/workplace_search/groups'); + const response = await HttpLogic.values.http.get( + '/internal/workplace_search/groups' + ); actions.onInitializeGroups(response); } catch (e) { flashAPIErrors(e); @@ -288,7 +290,7 @@ export const GroupsLogic = kea>({ }; try { - const response = await HttpLogic.values.http.post( + const response = await HttpLogic.values.http.post( '/internal/workplace_search/groups/search', { body: JSON.stringify({ @@ -307,7 +309,7 @@ export const GroupsLogic = kea>({ fetchGroupUsers: async ({ groupId }) => { actions.setAllGroupLoading(true); try { - const response = await HttpLogic.values.http.get( + const response = await HttpLogic.values.http.get( `/internal/workplace_search/groups/${groupId}/group_users` ); actions.setGroupUsers(response); @@ -317,10 +319,13 @@ export const GroupsLogic = kea>({ }, saveNewGroup: async () => { try { - const response = await HttpLogic.values.http.post('/internal/workplace_search/groups', { - body: JSON.stringify({ group_name: values.newGroupName }), - headers, - }); + const response = await HttpLogic.values.http.post( + '/internal/workplace_search/groups', + { + body: JSON.stringify({ group_name: values.newGroupName }), + headers, + } + ); actions.getSearchResults(true); const SUCCESS_MESSAGE = i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/oauth_authorize/oauth_authorize_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/oauth_authorize/oauth_authorize_logic.ts index e21cde02481a0..95a8dd4b3fbad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/oauth_authorize/oauth_authorize_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/oauth_authorize/oauth_authorize_logic.ts @@ -96,7 +96,7 @@ export const OAuthAuthorizeLogic = kea(oauthAuthorizeRoute, { query }); if (response.status === 'redirect') { window.location.replace(response.redirect_uri); @@ -113,7 +113,7 @@ export const OAuthAuthorizeLogic = kea(oauthAuthorizeRoute, { body: JSON.stringify({ client_id: cachedPreAuth.clientId, response_type: cachedPreAuth.responseType, @@ -135,7 +135,7 @@ export const OAuthAuthorizeLogic = kea(oauthAuthorizeRoute, { body: JSON.stringify({ client_id: cachedPreAuth.clientId, response_type: cachedPreAuth.responseType, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts index 1d79e66e778fb..494f46a8efb3e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.ts @@ -97,7 +97,9 @@ export const OverviewLogic = kea> listeners: ({ actions }) => ({ initializeOverview: async () => { try { - const response = await HttpLogic.values.http.get('/internal/workplace_search/overview'); + const response = await HttpLogic.values.http.get( + '/internal/workplace_search/overview' + ); actions.setServerData(response); } catch (e) { flashAPIErrors(e); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts index 29103aa0c39af..092b70e1f4ae8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts @@ -356,7 +356,9 @@ export const RoleMappingsLogic = kea(route); actions.setRoleMappings(response); } catch (e) { flashAPIErrors(e); @@ -367,7 +369,7 @@ export const RoleMappingsLogic = kea(route); actions.setRoleMappingsData(response); } catch (e) { flashAPIErrors(e); @@ -466,11 +468,9 @@ export const RoleMappingsLogic = kea( '/internal/workplace_search/org/single_user_role_mapping', - { - body, - } + { body } ); actions.setSingleUserRoleMapping(response); actions.setUserCreated(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/search_authorize/search_authorize_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/search_authorize/search_authorize_logic.ts index 852d0370e00b3..9b80882ff4150 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/search_authorize/search_authorize_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/search_authorize/search_authorize_logic.ts @@ -71,7 +71,7 @@ export const SearchAuthorizeLogic = kea< }; try { - const response = await http.get(oauthAuthorizeRoute, { query }); + const response = await http.get(oauthAuthorizeRoute, { query }); if (response.status === 'redirect') { window.location.replace(response.redirect_uri); @@ -91,7 +91,7 @@ export const SearchAuthorizeLogic = kea< const { cachedPreAuth } = values; try { - const response = await http.post(oauthAuthorizeRoute, { + const response = await http.post<{ redirect_uri: string }>(oauthAuthorizeRoute, { body: JSON.stringify({ client_id: cachedPreAuth.clientId, response_type: cachedPreAuth.responseType, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts index e06504edbf0ac..6484677b6df6b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/security/security_logic.ts @@ -138,7 +138,7 @@ export const SecurityLogic = kea> const { http } = HttpLogic.values; try { - const response = await http.get(route); + const response = await http.get(route); actions.setServerProps(response); } catch (e) { flashAPIErrors(e); @@ -151,7 +151,7 @@ export const SecurityLogic = kea> const { http } = HttpLogic.values; try { - const response = await http.patch(route, { body }); + const response = await http.patch(route, { body }); actions.setSourceRestrictionsUpdated(response); flashSuccessToast(SOURCE_RESTRICTIONS_SUCCESS_MESSAGE); AppLogic.actions.setSourceRestriction(isEnabled); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts index 4faaca58ab8a0..64dfa3f8e13bb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_logic.ts @@ -200,7 +200,7 @@ export const SettingsLogic = kea> const route = '/internal/workplace_search/org/settings'; try { - const response = await http.get(route); + const response = await http.get(route); actions.setServerProps(response); } catch (e) { flashAPIErrors(e); @@ -211,7 +211,7 @@ export const SettingsLogic = kea> const route = '/internal/workplace_search/org/settings/connectors'; try { - const response = await http.get(route); + const response = await http.get(route); actions.onInitializeConnectors(response); } catch (e) { flashAPIErrors(e); @@ -225,7 +225,9 @@ export const SettingsLogic = kea> const body = JSON.stringify({ name }); try { - const response = await http.put(route, { body }); + const response = await http.put<{ + organizationName: string; + }>(route, { body }); actions.setUpdatedName(response); flashSuccessToast(ORG_UPDATED_MESSAGE); AppLogic.actions.setOrgName(name); @@ -240,7 +242,7 @@ export const SettingsLogic = kea> const body = JSON.stringify({ logo }); try { - const response = await http.put(imageRoute, { body }); + const response = await http.put<{ logo: string | null }>(imageRoute, { body }); actions.setLogo(response.logo); flashSuccessToast(ORG_UPDATED_MESSAGE); } catch (e) { @@ -255,7 +257,7 @@ export const SettingsLogic = kea> const body = JSON.stringify({ icon }); try { - const response = await http.put(imageRoute, { body }); + const response = await http.put<{ icon: string | null }>(imageRoute, { body }); actions.setIcon(response.icon); flashSuccessToast(ORG_UPDATED_MESSAGE); } catch (e) { @@ -275,7 +277,9 @@ export const SettingsLogic = kea> clearFlashMessages(); try { - const response = await http.put(route, { body }); + const response = await http.put<{ + oauthApplication: IOauthApplication; + }>(route, { body }); actions.setUpdatedOauthApplication(response); flashSuccessToast(OAUTH_APP_UPDATED_MESSAGE); } catch (e) { diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/adaptive_relevance.test.ts similarity index 67% rename from x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts rename to x-pack/plugins/enterprise_search/server/routes/app_search/adaptive_relevance.test.ts index daab7c35596bf..cec2262c95a2e 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/adaptive_relevance.test.ts @@ -7,17 +7,17 @@ import { MockRouter, mockRequestHandler, mockDependencies } from '../../__mocks__'; -import { registerSearchRelevanceSuggestionsRoutes } from './search_relevance_suggestions'; +import { registerSearchRelevanceSuggestionsRoutes } from './adaptive_relevance'; describe('search relevance insights routes', () => { beforeEach(() => { jest.clearAllMocks(); }); - describe('POST /internal/app_search/engines/{name}/search_relevance_suggestions', () => { + describe('POST /internal/app_search/engines/{name}/adaptive_relevance/suggestions', () => { const mockRouter = new MockRouter({ method: 'post', - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/suggestions', }); beforeEach(() => { @@ -33,15 +33,15 @@ describe('search relevance insights routes', () => { }); expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/suggestions', }); }); }); - describe('PUT /internal/app_search/engines/{name}/search_relevance_suggestions', () => { + describe('PUT /internal/app_search/engines/{name}/adaptive_relevance/suggestions', () => { const mockRouter = new MockRouter({ method: 'put', - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/suggestions', }); beforeEach(() => { @@ -62,15 +62,15 @@ describe('search relevance insights routes', () => { }); expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/suggestions', }); }); }); - describe('GET /internal/app_search/engines/{name}/search_relevance_suggestions/settings', () => { + describe('GET /internal/app_search/engines/{name}/adaptive_relevance/settings', () => { const mockRouter = new MockRouter({ method: 'get', - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/settings', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/settings', }); beforeEach(() => { @@ -86,15 +86,15 @@ describe('search relevance insights routes', () => { }); expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/settings', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/settings', }); }); }); - describe('PUT /internal/app_search/engines/{name}/search_relevance_suggestions/settings', () => { + describe('PUT /internal/app_search/engines/{name}/adaptive_relevance/settings', () => { const mockRouter = new MockRouter({ method: 'put', - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/settings', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/settings', }); beforeEach(() => { @@ -111,15 +111,15 @@ describe('search relevance insights routes', () => { }); expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/settings', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/settings', }); }); }); - describe('GET /internal/app_search/engines/{engineName}/search_relevance_suggestions/{query}', () => { + describe('GET /internal/app_search/engines/{engineName}/adaptive_relevance/suggestions/{query}', () => { const mockRouter = new MockRouter({ method: 'get', - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/{query}', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/suggestions/{query}', }); beforeEach(() => { @@ -136,7 +136,7 @@ describe('search relevance insights routes', () => { }); expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/as/engines/:engineName/search_relevance_suggestions/:query', + path: '/as/engines/:engineName/adaptive_relevance/suggestions/:query', }); }); }); diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/adaptive_relevance.ts similarity index 70% rename from x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts rename to x-pack/plugins/enterprise_search/server/routes/app_search/adaptive_relevance.ts index 95b50a9c4971e..02260d19186da 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/adaptive_relevance.ts @@ -17,7 +17,7 @@ export function registerSearchRelevanceSuggestionsRoutes({ }: RouteDependencies) { router.post( { - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/suggestions', validate: { params: schema.object({ engineName: schema.string(), @@ -35,13 +35,13 @@ export function registerSearchRelevanceSuggestionsRoutes({ }, }, enterpriseSearchRequestHandler.createRequest({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/suggestions', }) ); router.put( skipBodyValidation({ - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/suggestions', validate: { params: schema.object({ engineName: schema.string(), @@ -49,13 +49,13 @@ export function registerSearchRelevanceSuggestionsRoutes({ }, }), enterpriseSearchRequestHandler.createRequest({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/suggestions', }) ); router.get( { - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/settings', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/settings', validate: { params: schema.object({ engineName: schema.string(), @@ -63,13 +63,13 @@ export function registerSearchRelevanceSuggestionsRoutes({ }, }, enterpriseSearchRequestHandler.createRequest({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/settings', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/settings', }) ); router.put( skipBodyValidation({ - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/settings', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/settings', validate: { params: schema.object({ engineName: schema.string(), @@ -77,13 +77,13 @@ export function registerSearchRelevanceSuggestionsRoutes({ }, }), enterpriseSearchRequestHandler.createRequest({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/settings', + path: '/api/as/v0/engines/:engineName/adaptive_relevance/settings', }) ); router.get( { - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/{query}', + path: '/internal/app_search/engines/{engineName}/adaptive_relevance/suggestions/{query}', validate: { params: schema.object({ engineName: schema.string(), @@ -95,7 +95,7 @@ export function registerSearchRelevanceSuggestionsRoutes({ }, }, enterpriseSearchRequestHandler.createRequest({ - path: '/as/engines/:engineName/search_relevance_suggestions/:query', + path: '/as/engines/:engineName/adaptive_relevance/suggestions/:query', }) ); } diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/curations.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/curations.ts index b6ef8c8acafa5..a7282e5dc6cc4 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/curations.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/curations.ts @@ -85,6 +85,9 @@ export function registerCurationsRoutes({ { path: '/internal/app_search/engines/{engineName}/curations/{curationId}', validate: { + query: schema.object({ + skip_record_analytics: schema.string(), + }), params: schema.object({ engineName: schema.string(), curationId: schema.string(), diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts index 737b21e6f5a92..602d8c48d520e 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/index.ts @@ -7,6 +7,7 @@ import { RouteDependencies } from '../../plugin'; +import { registerSearchRelevanceSuggestionsRoutes } from './adaptive_relevance'; import { registerAnalyticsRoutes } from './analytics'; import { registerApiLogsRoutes } from './api_logs'; import { registerCrawlerRoutes } from './crawler'; @@ -22,7 +23,6 @@ import { registerResultSettingsRoutes } from './result_settings'; import { registerRoleMappingsRoutes } from './role_mappings'; import { registerSchemaRoutes } from './schema'; import { registerSearchRoutes } from './search'; -import { registerSearchRelevanceSuggestionsRoutes } from './search_relevance_suggestions'; import { registerSearchSettingsRoutes } from './search_settings'; import { registerSearchUIRoutes } from './search_ui'; import { registerSettingsRoutes } from './settings'; diff --git a/x-pack/plugins/event_log/server/event_log_service.mock.ts b/x-pack/plugins/event_log/server/event_log_service.mock.ts index a3ad81eb0e5a6..f43f3e025a7cf 100644 --- a/x-pack/plugins/event_log/server/event_log_service.mock.ts +++ b/x-pack/plugins/event_log/server/event_log_service.mock.ts @@ -17,6 +17,7 @@ const createEventLogServiceMock = () => { getProviderActions: jest.fn(), registerSavedObjectProvider: jest.fn(), getLogger: jest.fn().mockReturnValue(eventLoggerMock.create()), + getIndexPattern: jest.fn(), }; return mock; }; diff --git a/x-pack/plugins/event_log/server/event_log_service.ts b/x-pack/plugins/event_log/server/event_log_service.ts index 993631ed3ca8a..2cf22b0f20755 100644 --- a/x-pack/plugins/event_log/server/event_log_service.ts +++ b/x-pack/plugins/event_log/server/event_log_service.ts @@ -92,6 +92,10 @@ export class EventLogService implements IEventLogService { return this.savedObjectProviderRegistry.registerProvider(type, provider); } + getIndexPattern() { + return this.esContext.esNames.indexPattern; + } + getLogger(initialProperties: IEvent): IEventLogger { return new EventLogger({ esContext: this.esContext, diff --git a/x-pack/plugins/event_log/server/types.ts b/x-pack/plugins/event_log/server/types.ts index c50bed7e01dd5..6ffde7fd6dbe0 100644 --- a/x-pack/plugins/event_log/server/types.ts +++ b/x-pack/plugins/event_log/server/types.ts @@ -33,6 +33,7 @@ export interface IEventLogService { getProviderActions(): Map>; registerSavedObjectProvider(type: string, provider: SavedObjectProvider): void; getLogger(properties: IEvent): IEventLogger; + getIndexPattern(): string; } export interface IEventLogClientService { diff --git a/x-pack/plugins/fleet/.gitignore b/x-pack/plugins/fleet/.gitignore new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/x-pack/plugins/fleet/cypress/README.md b/x-pack/plugins/fleet/cypress/README.md new file mode 100644 index 0000000000000..085ed7533e036 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/README.md @@ -0,0 +1,148 @@ +# Cypress Tests + +The `fleet/cypress` directory contains functional UI tests that execute using [Cypress](https://www.cypress.io/). + +## Running the tests + +There are currently three ways to run the tests, comprised of two execution modes and two target environments, which will be detailed below. + +### Execution modes + +#### Interactive mode + +When you run Cypress in interactive mode, an interactive runner is displayed that allows you to see commands as they execute while also viewing the application under test. For more information, please see [cypress documentation](https://docs.cypress.io/guides/core-concepts/test-runner.html#Overview). + +#### Headless mode + +A headless browser is a browser simulation program that does not have a user interface. These programs operate like any other browser, but do not display any UI. This is why meanwhile you are executing the tests on this mode you are not going to see the application under test. Just the output of the test is displayed on the terminal once the execution is finished. + +### Target environments + +#### FTR (CI) + +This is the configuration used by CI. It uses the FTR to spawn both a Kibana instance (http://localhost:5620) and an Elasticsearch instance (http://localhost:9220) with a preloaded minimum set of data (see preceding "Test data" section), and then executes cypress against this stack. You can find this configuration in `x-pack/test/fleet_cypress` + +### Test Execution: Examples + +#### FTR + Headless (Chrome) + +Since this is how tests are run on CI, this will likely be the configuration you want to reproduce failures locally, etc. + +```shell +# bootstrap kibana from the project root +yarn kbn bootstrap + +# build the plugins/assets that cypress will execute against +node scripts/build_kibana_platform_plugins + +# launch the cypress test runner +cd x-pack/plugins/fleet +yarn cypress:run-as-ci +``` +#### FTR + Interactive + +This is the preferred mode for developing new tests. + +```shell +# bootstrap kibana from the project root +yarn kbn bootstrap + +# build the plugins/assets that cypress will execute against +node scripts/build_kibana_platform_plugins + +# launch the cypress test runner +cd x-pack/plugins/fleet +yarn cypress:open-as-ci +``` + +Alternatively, kibana test server can be started separately, to pick up changes in UI (e.g. change in data-test-subj selector) + +``` +# launch kibana test server +node scripts/functional_tests_server --config x-pack/test/fleet_cypress/config.ts + +# launch cypress runner +node scripts/functional_test_runner --config x-pack/test/fleet_cypress/visual_config.ts +``` + +Note that you can select the browser you want to use on the top right side of the interactive runner. + +## Folder Structure + +### integration/ + +Cypress convention. Contains the specs that are going to be executed. + +### fixtures/ + +Cypress convention. Fixtures are used as external pieces of static data when we stub responses. + +### plugins/ + +Cypress convention. As a convenience, by default Cypress will automatically include the plugins file cypress/plugins/index.js before every single spec file it runs. + +### screens/ + +Contains the elements we want to interact with in our tests. + +Each file inside the screens folder represents a screen in our application. + +### tasks/ + +_Tasks_ are functions that may be reused across tests. + +Each file inside the tasks folder represents a screen of our application. + +## Test data + +The data the tests need: + +- Is generated on the fly using our application APIs (preferred way) +- Is ingested on the ELS instance using the `es_archive` utility + +### How to generate a new archive + +**Note:** As mentioned above, archives are only meant to contain external data, e.g. beats data. Due to the tendency for archived domain objects (rules, signals) to quickly become out of date, it is strongly suggested that you generate this data within the test, through interaction with either the UI or the API. + +We use es_archiver to manage the data that our Cypress tests need. + +1. Set up a clean instance of kibana and elasticsearch (if this is not possible, try to clean/minimize the data that you are going to archive). +2. With the kibana and elasticsearch instance up and running, create the data that you need for your test. +3. When you are sure that you have all the data you need run the following command from: `x-pack/plugins/fleet` + +```sh +node ../../../scripts/es_archiver save --dir ../../test/fleet_cypress/es_archives --config ../../../test/functional/config.js --es-url http://:@: +``` + +Example: + +```sh +node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/fleet_cypress/es_archives --config ../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 +``` + +Note that the command will create the folder if it does not exist. + +## Development Best Practices + +### Clean up the state + +Remember to clean up the state of the test after its execution, typically with the `cleanKibana` function. Be mindful of failure scenarios, as well: if your test fails, will it leave the environment in a recoverable state? + +### Minimize the use of es_archive + +When possible, create all the data that you need for executing the tests using the application APIS or the UI. + +### Speed up test execution time + +Loading the web page takes a big amount of time, in order to minimize that impact, the following points should be +taken into consideration until another solution is implemented: + +- Group the tests that are similar in different contexts. +- For every context login only once, clean the state between tests if needed without re-loading the page. +- All tests in a spec file must be order-independent. + +Remember that minimizing the number of times the web page is loaded, we minimize as well the execution time. + +## Linting + +Optional linting rules for Cypress and linting setup can be found [here](https://github.com/cypress-io/eslint-plugin-cypress#usage) diff --git a/x-pack/plugins/fleet/cypress/cypress.json b/x-pack/plugins/fleet/cypress/cypress.json new file mode 100644 index 0000000000000..158001b045561 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/cypress.json @@ -0,0 +1,19 @@ +{ + "baseUrl": "http://localhost:5620", + "defaultCommandTimeout": 60000, + "requestTimeout": 60000, + "responseTimetout": 60000, + "execTimeout": 120000, + "pageLoadTimeout": 120000, + "nodeVersion": "system", + "retries": { + "runMode": 2 + }, + "screenshotsFolder": "../../../target/kibana-fleet/cypress/screenshots", + "trashAssetsBeforeRuns": false, + "video": false, + "videosFolder": "../../../target/kibana-fleet/cypress/videos", + "viewportHeight": 900, + "viewportWidth": 1440, + "screenshotOnRunFailure": true +} diff --git a/x-pack/plugins/fleet/cypress/fixtures/integrations/agent_policies.json b/x-pack/plugins/fleet/cypress/fixtures/integrations/agent_policies.json new file mode 100644 index 0000000000000..ba1360e11a21d --- /dev/null +++ b/x-pack/plugins/fleet/cypress/fixtures/integrations/agent_policies.json @@ -0,0 +1,978 @@ +{ + "items": [ + { + "id": "30e16140-2106-11ec-a289-25321523992d", + "namespace": "default", + "monitoring_enabled": [ + "logs", + "metrics" + ], + "name": "Default policy", + "description": "Default agent policy created by Kibana", + "is_default": true, + "is_preconfigured": true, + "status": "active", + "is_managed": false, + "revision": 4, + "updated_at": "2021-09-29T09:52:13.879Z", + "updated_by": "elastic", + "package_policies": [ + { + "id": "15785537-fdf2-4e38-bd49-ae0537bbe162", + "version": "WzU5NSwxXQ==", + "name": "system-1", + "namespace": "default", + "package": { + "name": "system", + "title": "System", + "version": "1.4.0" + }, + "enabled": true, + "policy_id": "30e16140-2106-11ec-a289-25321523992d", + "output_id": "1ffdf460-2106-11ec-a289-25321523992d", + "inputs": [ + { + "type": "logfile", + "policy_template": "system", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.auth" + }, + "vars": { + "paths": { + "value": [ + "/var/log/auth.log*", + "/var/log/secure*" + ], + "type": "text" + } + }, + "id": "logfile-system.auth-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "paths": [ + "/var/log/auth.log*", + "/var/log/secure*" + ], + "exclude_files": [ + ".gz$" + ], + "multiline": { + "pattern": "^\\s", + "match": "after" + }, + "processors": [ + { + "add_locale": null + } + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.syslog" + }, + "vars": { + "paths": { + "value": [ + "/var/log/messages*", + "/var/log/syslog*" + ], + "type": "text" + } + }, + "id": "logfile-system.syslog-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "paths": [ + "/var/log/messages*", + "/var/log/syslog*" + ], + "exclude_files": [ + ".gz$" + ], + "multiline": { + "pattern": "^\\s", + "match": "after" + }, + "processors": [ + { + "add_locale": null + } + ] + } + } + ] + }, + { + "type": "winlog", + "policy_template": "system", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.application" + }, + "vars": { + "event_id": { + "type": "text" + }, + "processors": { + "type": "yaml" + }, + "tags": { + "value": [], + "type": "text" + } + }, + "id": "winlog-system.application-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "name": "Application", + "condition": "${host.platform} == 'windows'", + "ignore_older": "72h", + "tags": null + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.security" + }, + "vars": { + "event_id": { + "type": "text" + }, + "processors": { + "type": "yaml" + }, + "tags": { + "value": [], + "type": "text" + } + }, + "id": "winlog-system.security-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "name": "Security", + "condition": "${host.platform} == 'windows'", + "tags": null + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.system" + }, + "vars": { + "event_id": { + "type": "text" + }, + "processors": { + "type": "yaml" + }, + "tags": { + "value": [], + "type": "text" + } + }, + "id": "winlog-system.system-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "name": "System", + "condition": "${host.platform} == 'windows'", + "tags": null + } + } + ], + "vars": { + "preserve_original_event": { + "value": false, + "type": "bool" + } + } + }, + { + "type": "system/metrics", + "policy_template": "system", + "enabled": true, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "metrics", + "dataset": "system.core" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "core.metrics": { + "value": [ + "percentages" + ], + "type": "text" + } + }, + "id": "system/metrics-system.core-15785537-fdf2-4e38-bd49-ae0537bbe162" + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.cpu" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "cpu.metrics": { + "value": [ + "percentages", + "normalized_percentages" + ], + "type": "text" + } + }, + "id": "system/metrics-system.cpu-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "cpu" + ], + "cpu.metrics": [ + "percentages", + "normalized_percentages" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.diskio" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "diskio.include_devices": { + "value": [], + "type": "text" + } + }, + "id": "system/metrics-system.diskio-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "diskio" + ], + "diskio.include_devices": null, + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.filesystem" + }, + "vars": { + "period": { + "value": "1m", + "type": "text" + }, + "processors": { + "value": "- drop_event.when.regexp:\n system.filesystem.mount_point: ^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)\n", + "type": "yaml" + } + }, + "id": "system/metrics-system.filesystem-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "filesystem" + ], + "period": "1m", + "processors": [ + { + "drop_event.when.regexp": { + "system.filesystem.mount_point": "^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)" + } + } + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.fsstat" + }, + "vars": { + "period": { + "value": "1m", + "type": "text" + }, + "processors": { + "value": "- drop_event.when.regexp:\n system.fsstat.mount_point: ^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)\n", + "type": "yaml" + } + }, + "id": "system/metrics-system.fsstat-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "fsstat" + ], + "period": "1m", + "processors": [ + { + "drop_event.when.regexp": { + "system.fsstat.mount_point": "^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)" + } + } + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.load" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.load-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "load" + ], + "condition": "${host.platform} != 'windows'", + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.memory" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.memory-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "memory" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.network" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "network.interfaces": { + "value": [], + "type": "text" + } + }, + "id": "system/metrics-system.network-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "network" + ], + "period": "10s", + "network.interfaces": null + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.process" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "process.include_top_n.by_cpu": { + "value": 5, + "type": "integer" + }, + "process.include_top_n.by_memory": { + "value": 5, + "type": "integer" + }, + "process.cmdline.cache.enabled": { + "value": true, + "type": "bool" + }, + "process.cgroups.enabled": { + "value": false, + "type": "bool" + }, + "process.env.whitelist": { + "value": [], + "type": "text" + }, + "process.include_cpu_ticks": { + "value": false, + "type": "bool" + }, + "processes": { + "value": [ + ".*" + ], + "type": "text" + } + }, + "id": "system/metrics-system.process-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "process" + ], + "period": "10s", + "process.include_top_n.by_cpu": 5, + "process.include_top_n.by_memory": 5, + "process.cmdline.cache.enabled": true, + "process.cgroups.enabled": false, + "process.include_cpu_ticks": false, + "processes": [ + ".*" + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.process.summary" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.process.summary-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "process_summary" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.socket_summary" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.socket_summary-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "socket_summary" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.uptime" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.uptime-15785537-fdf2-4e38-bd49-ae0537bbe162", + "compiled_stream": { + "metricsets": [ + "uptime" + ], + "period": "10s" + } + } + ], + "vars": { + "system.hostfs": { + "type": "text" + } + } + }, + { + "type": "httpjson", + "policy_template": "system", + "enabled": false, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "system.application" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"XmlWinEventLog:Application\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded" + ], + "type": "text" + } + }, + "id": "httpjson-system.application-15785537-fdf2-4e38-bd49-ae0537bbe162" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "system.security" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"XmlWinEventLog:Security\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded" + ], + "type": "text" + } + }, + "id": "httpjson-system.security-15785537-fdf2-4e38-bd49-ae0537bbe162" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "system.system" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"XmlWinEventLog:System\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded" + ], + "type": "text" + } + }, + "id": "httpjson-system.system-15785537-fdf2-4e38-bd49-ae0537bbe162" + } + ], + "vars": { + "url": { + "value": "https://server.example.com:8089", + "type": "text" + }, + "username": { + "type": "text" + }, + "password": { + "type": "password" + }, + "token": { + "type": "password" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "ssl": { + "value": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n", + "type": "yaml" + } + } + } + ], + "revision": 1, + "created_at": "2021-09-29T09:18:23.207Z", + "created_by": "system", + "updated_at": "2021-09-29T09:18:23.207Z", + "updated_by": "system" + }, + { + "id": "63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "version": "WzczOSwxXQ==", + "name": "apache-1", + "description": "", + "namespace": "default", + "policy_id": "30e16140-2106-11ec-a289-25321523992d", + "enabled": true, + "output_id": "", + "inputs": [ + { + "type": "logfile", + "policy_template": "apache", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "apache.access" + }, + "vars": { + "paths": { + "value": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ], + "type": "text" + }, + "tags": { + "value": [ + "apache-access" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "logfile-apache.access-63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "compiled_stream": { + "paths": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ], + "tags": [ + "apache-access" + ], + "exclude_files": [ + ".gz$" + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "apache.error" + }, + "vars": { + "paths": { + "value": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ], + "type": "text" + }, + "tags": { + "value": [ + "apache-error" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "logfile-apache.error-63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "compiled_stream": { + "paths": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ], + "exclude_files": [ + ".gz$" + ], + "tags": [ + "apache-error" + ], + "processors": [ + { + "add_locale": null + } + ] + } + } + ] + }, + { + "type": "httpjson", + "policy_template": "apache", + "enabled": false, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "apache.access" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"access*\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded", + "apache-access" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "httpjson-apache.access-63172a6b-4f00-4376-b5e6-fe9b3f00fc79" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "apache.error" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=apache:error OR sourcetype=apache_error", + "type": "text" + }, + "tags": { + "value": [ + "forwarded", + "apache-error" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "httpjson-apache.error-63172a6b-4f00-4376-b5e6-fe9b3f00fc79" + } + ], + "vars": { + "url": { + "value": "https://server.example.com:8089", + "type": "text" + }, + "username": { + "type": "text" + }, + "password": { + "type": "password" + }, + "token": { + "type": "password" + }, + "ssl": { + "value": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n", + "type": "yaml" + } + } + }, + { + "type": "apache/metrics", + "policy_template": "apache", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "apache.status" + }, + "vars": { + "period": { + "value": "30s", + "type": "text" + }, + "server_status_path": { + "value": "/server-status", + "type": "text" + } + }, + "id": "apache/metrics-apache.status-63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "compiled_stream": { + "metricsets": [ + "status" + ], + "hosts": [ + "http://127.0.0.1" + ], + "period": "30s", + "server_status_path": "/server-status" + } + } + ], + "vars": { + "hosts": { + "value": [ + "http://127.0.0.1" + ], + "type": "text" + } + } + } + ], + "package": { + "name": "apache", + "title": "Apache", + "version": "1.1.0" + }, + "revision": 1, + "created_at": "2021-09-29T09:52:12.865Z", + "created_by": "elastic", + "updated_at": "2021-09-29T09:52:12.865Z", + "updated_by": "elastic" + } + ], + "agents": 1 + }, + { + "id": "30e16141-2106-11ec-a289-25321523992d", + "namespace": "default", + "monitoring_enabled": [ + "logs", + "metrics" + ], + "name": "Default Fleet Server policy", + "description": "Default Fleet Server agent policy created by Kibana", + "is_default": false, + "is_default_fleet_server": true, + "is_preconfigured": true, + "status": "active", + "is_managed": false, + "revision": 1, + "updated_at": "2021-09-29T09:18:25.581Z", + "updated_by": "system", + "package_policies": [ + { + "id": "3f79c8a2-ed32-45d9-a7e7-b58852f4cb7d", + "version": "WzU5NywxXQ==", + "name": "fleet_server-1", + "namespace": "default", + "package": { + "name": "fleet_server", + "title": "Fleet Server", + "version": "1.0.1" + }, + "enabled": true, + "policy_id": "30e16141-2106-11ec-a289-25321523992d", + "output_id": "1ffdf460-2106-11ec-a289-25321523992d", + "inputs": [ + { + "type": "fleet-server", + "policy_template": "fleet_server", + "enabled": true, + "streams": [], + "vars": { + "host": { + "value": [ + "0.0.0.0" + ], + "type": "text" + }, + "port": { + "value": [ + 8220 + ], + "type": "integer" + }, + "max_connections": { + "type": "integer" + }, + "custom": { + "value": "", + "type": "yaml" + } + }, + "compiled_input": { + "server": { + "port": 8220, + "host": "0.0.0.0" + } + } + } + ], + "revision": 1, + "created_at": "2021-09-29T09:18:25.204Z", + "created_by": "system", + "updated_at": "2021-09-29T09:18:25.204Z", + "updated_by": "system" + } + ], + "agents": 0 + } + ], + "total": 2, + "page": 1, + "perPage": 20 +} \ No newline at end of file diff --git a/x-pack/plugins/fleet/cypress/fixtures/integrations/agent_policy.json b/x-pack/plugins/fleet/cypress/fixtures/integrations/agent_policy.json new file mode 100644 index 0000000000000..aa6520f513acd --- /dev/null +++ b/x-pack/plugins/fleet/cypress/fixtures/integrations/agent_policy.json @@ -0,0 +1,644 @@ +{ + "item": { + "id": "30e16140-2106-11ec-a289-25321523992d", + "namespace": "default", + "monitoring_enabled": [ + "logs", + "metrics" + ], + "name": "Default policy", + "description": "Default agent policy created by Kibana", + "is_default": true, + "is_preconfigured": true, + "status": "active", + "is_managed": false, + "revision": 1, + "updated_at": "2021-09-30T10:02:50.389Z", + "updated_by": "system", + "package_policies": [ + { + "id": "4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "version": "WzEyNjQsMV0=", + "name": "system-1", + "namespace": "default", + "package": { + "name": "system", + "title": "System", + "version": "1.4.0" + }, + "enabled": true, + "policy_id": "8f108d20-21d5-11ec-9dad-073c0cd6096b", + "output_id": "4f979e90-21d5-11ec-9dad-073c0cd6096b", + "inputs": [ + { + "type": "logfile", + "policy_template": "system", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.auth" + }, + "vars": { + "paths": { + "value": [ + "/var/log/auth.log*", + "/var/log/secure*" + ], + "type": "text" + } + }, + "id": "logfile-system.auth-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "paths": [ + "/var/log/auth.log*", + "/var/log/secure*" + ], + "exclude_files": [ + ".gz$" + ], + "multiline": { + "pattern": "^\\s", + "match": "after" + }, + "processors": [ + { + "add_locale": null + } + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.syslog" + }, + "vars": { + "paths": { + "value": [ + "/var/log/messages*", + "/var/log/syslog*" + ], + "type": "text" + } + }, + "id": "logfile-system.syslog-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "paths": [ + "/var/log/messages*", + "/var/log/syslog*" + ], + "exclude_files": [ + ".gz$" + ], + "multiline": { + "pattern": "^\\s", + "match": "after" + }, + "processors": [ + { + "add_locale": null + } + ] + } + } + ] + }, + { + "type": "winlog", + "policy_template": "system", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.application" + }, + "vars": { + "event_id": { + "type": "text" + }, + "processors": { + "type": "yaml" + }, + "tags": { + "value": [], + "type": "text" + } + }, + "id": "winlog-system.application-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "name": "Application", + "condition": "${host.platform} == 'windows'", + "ignore_older": "72h", + "tags": null + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.security" + }, + "vars": { + "event_id": { + "type": "text" + }, + "processors": { + "type": "yaml" + }, + "tags": { + "value": [], + "type": "text" + } + }, + "id": "winlog-system.security-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "name": "Security", + "condition": "${host.platform} == 'windows'", + "tags": null + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "system.system" + }, + "vars": { + "event_id": { + "type": "text" + }, + "processors": { + "type": "yaml" + }, + "tags": { + "value": [], + "type": "text" + } + }, + "id": "winlog-system.system-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "name": "System", + "condition": "${host.platform} == 'windows'", + "tags": null + } + } + ], + "vars": { + "preserve_original_event": { + "value": false, + "type": "bool" + } + } + }, + { + "type": "system/metrics", + "policy_template": "system", + "enabled": true, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "metrics", + "dataset": "system.core" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "core.metrics": { + "value": [ + "percentages" + ], + "type": "text" + } + }, + "id": "system/metrics-system.core-4243f6b9-6ce2-48ec-859a-b5df4baa7c11" + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.cpu" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "cpu.metrics": { + "value": [ + "percentages", + "normalized_percentages" + ], + "type": "text" + } + }, + "id": "system/metrics-system.cpu-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "cpu" + ], + "cpu.metrics": [ + "percentages", + "normalized_percentages" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.diskio" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "diskio.include_devices": { + "value": [], + "type": "text" + } + }, + "id": "system/metrics-system.diskio-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "diskio" + ], + "diskio.include_devices": null, + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.filesystem" + }, + "vars": { + "period": { + "value": "1m", + "type": "text" + }, + "processors": { + "value": "- drop_event.when.regexp:\n system.filesystem.mount_point: ^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)\n", + "type": "yaml" + } + }, + "id": "system/metrics-system.filesystem-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "filesystem" + ], + "period": "1m", + "processors": [ + { + "drop_event.when.regexp": { + "system.filesystem.mount_point": "^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)" + } + } + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.fsstat" + }, + "vars": { + "period": { + "value": "1m", + "type": "text" + }, + "processors": { + "value": "- drop_event.when.regexp:\n system.fsstat.mount_point: ^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)\n", + "type": "yaml" + } + }, + "id": "system/metrics-system.fsstat-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "fsstat" + ], + "period": "1m", + "processors": [ + { + "drop_event.when.regexp": { + "system.fsstat.mount_point": "^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)" + } + } + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.load" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.load-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "load" + ], + "condition": "${host.platform} != 'windows'", + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.memory" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.memory-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "memory" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.network" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "network.interfaces": { + "value": [], + "type": "text" + } + }, + "id": "system/metrics-system.network-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "network" + ], + "period": "10s", + "network.interfaces": null + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.process" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + }, + "process.include_top_n.by_cpu": { + "value": 5, + "type": "integer" + }, + "process.include_top_n.by_memory": { + "value": 5, + "type": "integer" + }, + "process.cmdline.cache.enabled": { + "value": true, + "type": "bool" + }, + "process.cgroups.enabled": { + "value": false, + "type": "bool" + }, + "process.env.whitelist": { + "value": [], + "type": "text" + }, + "process.include_cpu_ticks": { + "value": false, + "type": "bool" + }, + "processes": { + "value": [ + ".*" + ], + "type": "text" + } + }, + "id": "system/metrics-system.process-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "process" + ], + "period": "10s", + "process.include_top_n.by_cpu": 5, + "process.include_top_n.by_memory": 5, + "process.cmdline.cache.enabled": true, + "process.cgroups.enabled": false, + "process.include_cpu_ticks": false, + "processes": [ + ".*" + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.process.summary" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.process.summary-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "process_summary" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.socket_summary" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.socket_summary-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "socket_summary" + ], + "period": "10s" + } + }, + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "system.uptime" + }, + "vars": { + "period": { + "value": "10s", + "type": "text" + } + }, + "id": "system/metrics-system.uptime-4243f6b9-6ce2-48ec-859a-b5df4baa7c11", + "compiled_stream": { + "metricsets": [ + "uptime" + ], + "period": "10s" + } + } + ], + "vars": { + "system.hostfs": { + "type": "text" + } + } + }, + { + "type": "httpjson", + "policy_template": "system", + "enabled": false, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "system.application" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"XmlWinEventLog:Application\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded" + ], + "type": "text" + } + }, + "id": "httpjson-system.application-4243f6b9-6ce2-48ec-859a-b5df4baa7c11" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "system.security" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"XmlWinEventLog:Security\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded" + ], + "type": "text" + } + }, + "id": "httpjson-system.security-4243f6b9-6ce2-48ec-859a-b5df4baa7c11" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "system.system" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"XmlWinEventLog:System\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded" + ], + "type": "text" + } + }, + "id": "httpjson-system.system-4243f6b9-6ce2-48ec-859a-b5df4baa7c11" + } + ], + "vars": { + "url": { + "value": "https://server.example.com:8089", + "type": "text" + }, + "username": { + "type": "text" + }, + "password": { + "type": "password" + }, + "token": { + "type": "password" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "ssl": { + "value": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n", + "type": "yaml" + } + } + } + ], + "revision": 1, + "created_at": "2021-09-30T10:02:48.904Z", + "created_by": "system", + "updated_at": "2021-09-30T10:02:48.904Z", + "updated_by": "system" + } + ] + } +} \ No newline at end of file diff --git a/x-pack/plugins/fleet/cypress/fixtures/integrations/apache.json b/x-pack/plugins/fleet/cypress/fixtures/integrations/apache.json new file mode 100644 index 0000000000000..3b78048fdd83f --- /dev/null +++ b/x-pack/plugins/fleet/cypress/fixtures/integrations/apache.json @@ -0,0 +1,1059 @@ +{ + "response": { + "name": "apache", + "title": "Apache", + "version": "1.1.0", + "release": "ga", + "description": "This Elastic integration collects logs and metrics from Apache servers", + "type": "integration", + "download": "/epr/apache/apache-1.1.0.zip", + "path": "/package/apache/1.1.0", + "icons": [ + { + "src": "/img/logo_apache.svg", + "path": "/package/apache/1.1.0/img/logo_apache.svg", + "title": "Apache Logo", + "size": "32x32", + "type": "image/svg+xml" + } + ], + "format_version": "1.0.0", + "readme": "/package/apache/1.1.0/docs/README.md", + "license": "basic", + "categories": [ + "web" + ], + "conditions": { + "kibana.version": "^7.14.0" + }, + "screenshots": [ + { + "src": "/img/apache-metrics-overview.png", + "path": "/package/apache/1.1.0/img/apache-metrics-overview.png", + "title": "Apache metrics overview", + "size": "3360x3064", + "type": "image/png" + }, + { + "src": "/img/apache-logs-overview.png", + "path": "/package/apache/1.1.0/img/apache-logs-overview.png", + "title": "Apache logs overview", + "size": "3342x1384", + "type": "image/png" + } + ], + "assets": { + "kibana": { + "dashboard": [ + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "dashboard", + "file": "apache-Logs-Apache-Dashboard.json", + "path": "apache-1.1.0/kibana/dashboard/apache-Logs-Apache-Dashboard.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "dashboard", + "file": "apache-Metrics-Apache-HTTPD-server-status.json", + "path": "apache-1.1.0/kibana/dashboard/apache-Metrics-Apache-HTTPD-server-status.json" + } + ], + "ml_module": [ + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "ml_module", + "file": "apache-Logs-ml.json", + "path": "apache-1.1.0/kibana/ml_module/apache-Logs-ml.json" + } + ], + "search": [ + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "search", + "file": "apache-HTTPD.json", + "path": "apache-1.1.0/kibana/search/apache-HTTPD.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "search", + "file": "apache-access-logs.json", + "path": "apache-1.1.0/kibana/search/apache-access-logs.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "search", + "file": "apache-errors-log.json", + "path": "apache-1.1.0/kibana/search/apache-errors-log.json" + } + ], + "visualization": [ + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-22057f20-3a12-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-22057f20-3a12-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-320cd980-3a36-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-320cd980-3a36-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-47820ce0-3a1d-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-47820ce0-3a1d-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-7724cf20-3a39-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-7724cf20-3a39-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-7d68f730-3a39-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-7d68f730-3a39-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-805d7bb0-3a10-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-805d7bb0-3a10-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-99666080-3a20-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-99666080-3a20-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-HTTPD-CPU.json", + "path": "apache-1.1.0/kibana/visualization/apache-HTTPD-CPU.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-HTTPD-Load1-slash-5-slash-15.json", + "path": "apache-1.1.0/kibana/visualization/apache-HTTPD-Load1-slash-5-slash-15.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-HTTPD-Scoreboard.json", + "path": "apache-1.1.0/kibana/visualization/apache-HTTPD-Scoreboard.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-a45311f0-3a34-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-a45311f0-3a34-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-access-unique-IPs-map.json", + "path": "apache-1.1.0/kibana/visualization/apache-access-unique-IPs-map.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-browsers.json", + "path": "apache-1.1.0/kibana/visualization/apache-browsers.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-ed44f820-3a10-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-ed44f820-3a10-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-error-logs-over-time.json", + "path": "apache-1.1.0/kibana/visualization/apache-error-logs-over-time.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-f4ffec70-3a36-11eb-8946-296aab7b13db.json", + "path": "apache-1.1.0/kibana/visualization/apache-f4ffec70-3a36-11eb-8946-296aab7b13db.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-operating-systems.json", + "path": "apache-1.1.0/kibana/visualization/apache-operating-systems.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-response-codes-of-top-URLs.json", + "path": "apache-1.1.0/kibana/visualization/apache-response-codes-of-top-URLs.json" + }, + { + "pkgkey": "apache-1.1.0", + "service": "kibana", + "type": "visualization", + "file": "apache-response-codes-over-time.json", + "path": "apache-1.1.0/kibana/visualization/apache-response-codes-over-time.json" + } + ] + }, + "elasticsearch": { + "ingest_pipeline": [ + { + "pkgkey": "apache-1.1.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "default.yml", + "dataset": "access", + "path": "apache-1.1.0/data_stream/access/elasticsearch/ingest_pipeline/default.yml" + }, + { + "pkgkey": "apache-1.1.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "third-party.yml", + "dataset": "access", + "path": "apache-1.1.0/data_stream/access/elasticsearch/ingest_pipeline/third-party.yml" + }, + { + "pkgkey": "apache-1.1.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "default.yml", + "dataset": "error", + "path": "apache-1.1.0/data_stream/error/elasticsearch/ingest_pipeline/default.yml" + }, + { + "pkgkey": "apache-1.1.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "third-party.yml", + "dataset": "error", + "path": "apache-1.1.0/data_stream/error/elasticsearch/ingest_pipeline/third-party.yml" + } + ] + } + }, + "policy_templates": [ + { + "name": "apache", + "title": "Apache logs and metrics", + "description": "Collect logs and metrics from Apache instances", + "inputs": [ + { + "type": "logfile", + "title": "Collect logs from Apache instances", + "description": "Collecting Apache access and error logs" + }, + { + "type": "httpjson", + "vars": [ + { + "name": "url", + "type": "text", + "title": "URL of Splunk Enterprise Server", + "description": "i.e. scheme://host:port, path is automatic", + "multi": false, + "required": true, + "show_user": true, + "default": "https://server.example.com:8089" + }, + { + "name": "username", + "type": "text", + "title": "Splunk REST API Username", + "multi": false, + "required": false, + "show_user": true + }, + { + "name": "password", + "type": "password", + "title": "Splunk REST API Password", + "multi": false, + "required": false, + "show_user": true + }, + { + "name": "token", + "type": "password", + "title": "Splunk Authorization Token", + "description": "Bearer Token or Session Key, e.g. \"Bearer eyJFd3e46...\"\nor \"Splunk 192fd3e...\". Cannot be used with username\nand password.\n", + "multi": false, + "required": false, + "show_user": true + }, + { + "name": "ssl", + "type": "yaml", + "title": "SSL Configuration", + "description": "i.e. certificate_authorities, supported_protocols, verification_mode etc.", + "multi": false, + "required": false, + "show_user": false, + "default": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n" + } + ], + "title": "Collect logs from third-party REST API (experimental)", + "description": "Collect logs from third-party REST API (experimental)" + }, + { + "type": "apache/metrics", + "vars": [ + { + "name": "hosts", + "type": "text", + "title": "Hosts", + "multi": true, + "required": true, + "show_user": true, + "default": [ + "http://127.0.0.1" + ] + } + ], + "title": "Collect metrics from Apache instances", + "description": "Collecting Apache status metrics" + } + ], + "multiple": true + } + ], + "data_streams": [ + { + "type": "logs", + "dataset": "apache.access", + "title": "Apache access logs", + "release": "experimental", + "ingest_pipeline": "default", + "streams": [ + { + "input": "logfile", + "vars": [ + { + "name": "paths", + "type": "text", + "title": "Paths", + "multi": true, + "required": true, + "show_user": true, + "default": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ] + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": true, + "show_user": false, + "default": [ + "apache-access" + ] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n", + "multi": false, + "required": false, + "show_user": false + } + ], + "template_path": "log.yml.hbs", + "title": "Apache access logs", + "description": "Collect Apache access logs", + "enabled": true + }, + { + "input": "httpjson", + "vars": [ + { + "name": "interval", + "type": "text", + "title": "Interval to query Splunk Enterprise REST API", + "description": "Go Duration syntax (eg. 10s)", + "multi": false, + "required": true, + "show_user": true, + "default": "10s" + }, + { + "name": "search", + "type": "text", + "title": "Splunk search string", + "multi": false, + "required": true, + "show_user": true, + "default": "search sourcetype=\"access*\"" + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": false, + "show_user": false, + "default": [ + "forwarded", + "apache-access" + ] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n", + "multi": false, + "required": false, + "show_user": false + } + ], + "template_path": "httpjson.yml.hbs", + "title": "Apache access logs via Splunk Enterprise REST API", + "description": "Collect apache access logs via Splunk Enterprise REST API", + "enabled": false + } + ], + "package": "apache", + "path": "access" + }, + { + "type": "logs", + "dataset": "apache.error", + "title": "Apache error logs", + "release": "experimental", + "ingest_pipeline": "default", + "streams": [ + { + "input": "logfile", + "vars": [ + { + "name": "paths", + "type": "text", + "title": "Paths", + "multi": true, + "required": true, + "show_user": true, + "default": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ] + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": true, + "show_user": false, + "default": [ + "apache-error" + ] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n", + "multi": false, + "required": false, + "show_user": false + } + ], + "template_path": "log.yml.hbs", + "title": "Apache error logs", + "description": "Collect Apache error logs", + "enabled": true + }, + { + "input": "httpjson", + "vars": [ + { + "name": "interval", + "type": "text", + "title": "Interval to query Splunk Enterprise REST API", + "description": "Go Duration syntax (eg. 10s)", + "multi": false, + "required": true, + "show_user": true, + "default": "10s" + }, + { + "name": "search", + "type": "text", + "title": "Splunk search string", + "multi": false, + "required": true, + "show_user": true, + "default": "search sourcetype=apache:error OR sourcetype=apache_error" + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": false, + "show_user": false, + "default": [ + "forwarded", + "apache-error" + ] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n", + "multi": false, + "required": false, + "show_user": false + } + ], + "template_path": "httpjson.yml.hbs", + "title": "Apache error logs via Splunk Enterprise REST API", + "description": "Collect apache error logs via Splunk Enterprise REST API", + "enabled": false + } + ], + "package": "apache", + "path": "error" + }, + { + "type": "metrics", + "dataset": "apache.status", + "title": "Apache status metrics", + "release": "experimental", + "streams": [ + { + "input": "apache/metrics", + "vars": [ + { + "name": "period", + "type": "text", + "title": "Period", + "multi": false, + "required": true, + "show_user": true, + "default": "30s" + }, + { + "name": "server_status_path", + "type": "text", + "title": "Server Status Path", + "multi": false, + "required": true, + "show_user": false, + "default": "/server-status" + } + ], + "template_path": "stream.yml.hbs", + "title": "Apache status metrics", + "description": "Collect Apache status metrics", + "enabled": true + } + ], + "package": "apache", + "path": "status" + } + ], + "owner": { + "github": "elastic/integrations" + }, + "latestVersion": "1.1.0", + "removable": true, + "status": "installed", + "savedObject": { + "id": "apache", + "type": "epm-packages", + "namespaces": [], + "updated_at": "2021-09-30T10:47:12.961Z", + "version": "WzI1NjgsMV0=", + "attributes": { + "installed_kibana": [ + { + "id": "apache-Logs-Apache-Dashboard", + "type": "dashboard" + }, + { + "id": "apache-Metrics-Apache-HTTPD-server-status", + "type": "dashboard" + }, + { + "id": "apache-22057f20-3a12-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-320cd980-3a36-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-47820ce0-3a1d-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-7724cf20-3a39-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-7d68f730-3a39-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-805d7bb0-3a10-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-99666080-3a20-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-HTTPD-CPU", + "type": "visualization" + }, + { + "id": "apache-HTTPD-Load1-slash-5-slash-15", + "type": "visualization" + }, + { + "id": "apache-HTTPD-Scoreboard", + "type": "visualization" + }, + { + "id": "apache-a45311f0-3a34-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-access-unique-IPs-map", + "type": "visualization" + }, + { + "id": "apache-browsers", + "type": "visualization" + }, + { + "id": "apache-ed44f820-3a10-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-error-logs-over-time", + "type": "visualization" + }, + { + "id": "apache-f4ffec70-3a36-11eb-8946-296aab7b13db", + "type": "visualization" + }, + { + "id": "apache-operating-systems", + "type": "visualization" + }, + { + "id": "apache-response-codes-of-top-URLs", + "type": "visualization" + }, + { + "id": "apache-response-codes-over-time", + "type": "visualization" + }, + { + "id": "apache-HTTPD", + "type": "search" + }, + { + "id": "apache-access-logs", + "type": "search" + }, + { + "id": "apache-errors-log", + "type": "search" + }, + { + "id": "apache-Logs-ml", + "type": "ml-module" + } + ], + "installed_es": [ + { + "id": "logs-apache.access-1.1.0", + "type": "ingest_pipeline" + }, + { + "id": "logs-apache.access-1.1.0-third-party", + "type": "ingest_pipeline" + }, + { + "id": "logs-apache.error-1.1.0", + "type": "ingest_pipeline" + }, + { + "id": "logs-apache.error-1.1.0-third-party", + "type": "ingest_pipeline" + }, + { + "id": "logs-apache.access", + "type": "index_template" + }, + { + "id": "logs-apache.access@settings", + "type": "component_template" + }, + { + "id": "logs-apache.access@custom", + "type": "component_template" + }, + { + "id": "logs-apache.error", + "type": "index_template" + }, + { + "id": "logs-apache.error@settings", + "type": "component_template" + }, + { + "id": "logs-apache.error@custom", + "type": "component_template" + }, + { + "id": "metrics-apache.status", + "type": "index_template" + }, + { + "id": "metrics-apache.status@settings", + "type": "component_template" + }, + { + "id": "metrics-apache.status@custom", + "type": "component_template" + } + ], + "package_assets": [ + { + "id": "c99057a8-c51a-5795-9e00-b4b09237f780", + "type": "epm-packages-assets" + }, + { + "id": "1388d2c7-254a-5cd4-882d-89b3e8b681cd", + "type": "epm-packages-assets" + }, + { + "id": "c3068bcb-5a74-5044-91f6-c8e99eefb003", + "type": "epm-packages-assets" + }, + { + "id": "4cea5f13-0ec6-5ecc-9012-f2dba2c86fab", + "type": "epm-packages-assets" + }, + { + "id": "6f27b654-fc39-502b-bdda-83ed13e775c1", + "type": "epm-packages-assets" + }, + { + "id": "baa6d518-fa85-530f-9cdc-b0f2207599f8", + "type": "epm-packages-assets" + }, + { + "id": "ea0cfbd9-8173-5429-a83b-6168b2cd4f27", + "type": "epm-packages-assets" + }, + { + "id": "3745632e-1306-5ac6-84ee-0fceae577988", + "type": "epm-packages-assets" + }, + { + "id": "079a3007-eec5-504e-a993-8c489ccc992c", + "type": "epm-packages-assets" + }, + { + "id": "625ba117-a66d-5eba-9172-201e4f03fbf0", + "type": "epm-packages-assets" + }, + { + "id": "f0dd03dd-3dee-51da-881b-425e76966139", + "type": "epm-packages-assets" + }, + { + "id": "c356fb2c-395b-595e-bdf4-51c5750d6efe", + "type": "epm-packages-assets" + }, + { + "id": "861a6d88-8e80-5282-8cc4-b74b13da22f8", + "type": "epm-packages-assets" + }, + { + "id": "49186533-1536-5d2d-a45a-b51a4db1eeca", + "type": "epm-packages-assets" + }, + { + "id": "533a5c29-648c-593c-9444-df3d03c4aae0", + "type": "epm-packages-assets" + }, + { + "id": "9d34d784-f5a7-5213-a711-37bf2af21da5", + "type": "epm-packages-assets" + }, + { + "id": "4d5fa019-7503-5a89-95af-a03227622ecd", + "type": "epm-packages-assets" + }, + { + "id": "edc0c10d-f7f4-5523-8dac-ce9c64aff44d", + "type": "epm-packages-assets" + }, + { + "id": "5792421c-b31c-59a3-891c-1566bc85447b", + "type": "epm-packages-assets" + }, + { + "id": "7a72f59a-27a6-5514-9489-1258de496199", + "type": "epm-packages-assets" + }, + { + "id": "69dffce3-96d1-5c71-b4ae-41b6d61fdd4a", + "type": "epm-packages-assets" + }, + { + "id": "0b971e05-221e-5430-87e6-fbebbc8d4a23", + "type": "epm-packages-assets" + }, + { + "id": "5d7fb7e1-e775-5832-95a7-074d692fb176", + "type": "epm-packages-assets" + }, + { + "id": "4a50c74b-e4ce-511c-badd-54997537b6b8", + "type": "epm-packages-assets" + }, + { + "id": "54e21b74-9ea5-537f-8cce-673b10b8ac39", + "type": "epm-packages-assets" + }, + { + "id": "c9fd9a64-722c-59f7-a686-4d92d4395be0", + "type": "epm-packages-assets" + }, + { + "id": "5a53ca55-23ec-59bc-8d04-be12f1776358", + "type": "epm-packages-assets" + }, + { + "id": "b2652216-a523-5183-8eaa-c26f9ba4bbee", + "type": "epm-packages-assets" + }, + { + "id": "97f717d7-78d6-5b8c-acde-edf80aa27201", + "type": "epm-packages-assets" + }, + { + "id": "6b27939a-1f2a-536d-8d84-560ed372d21a", + "type": "epm-packages-assets" + }, + { + "id": "7d68617a-88b0-5d34-8a98-8f51d3c49568", + "type": "epm-packages-assets" + }, + { + "id": "8e212777-acac-5068-acbb-143e0cbfb3eb", + "type": "epm-packages-assets" + }, + { + "id": "436ed6b2-aa68-55d4-912a-346e14903d7b", + "type": "epm-packages-assets" + }, + { + "id": "5169ccd9-75f9-5d84-8116-2f2bac0dd93f", + "type": "epm-packages-assets" + }, + { + "id": "a36f82fe-4aa0-508f-92e4-e33d779c1ed2", + "type": "epm-packages-assets" + }, + { + "id": "96d9ae25-0ee7-59aa-b8a0-4fbb929cce4a", + "type": "epm-packages-assets" + }, + { + "id": "05e1449f-3723-5d3c-a76f-5e307d88c35b", + "type": "epm-packages-assets" + }, + { + "id": "a0e8abee-4777-5a7f-bb9a-c2c60d49d060", + "type": "epm-packages-assets" + }, + { + "id": "4c77c830-b4e2-5c77-a3dd-941249799ce7", + "type": "epm-packages-assets" + }, + { + "id": "e082c4c2-3215-5fb0-a485-b261a774314e", + "type": "epm-packages-assets" + }, + { + "id": "1f4467ca-6aa9-5fcb-a346-f334e018db3f", + "type": "epm-packages-assets" + }, + { + "id": "fc831e85-d43f-5402-8780-c9fb3b040b34", + "type": "epm-packages-assets" + }, + { + "id": "208cc640-7cb1-5dd0-902e-47d82fe273af", + "type": "epm-packages-assets" + }, + { + "id": "65e211ff-9497-5882-88cc-ebfd79578cff", + "type": "epm-packages-assets" + }, + { + "id": "a6ea40cc-bb98-5039-8d52-151ac69cbfb5", + "type": "epm-packages-assets" + }, + { + "id": "d9e1d1e6-1c31-5164-8805-b8b2249bd8b5", + "type": "epm-packages-assets" + }, + { + "id": "aa843dec-f345-5c94-99e3-8bd2bffb9b4e", + "type": "epm-packages-assets" + }, + { + "id": "2b019917-8d4c-5da9-80b2-5005524a1290", + "type": "epm-packages-assets" + }, + { + "id": "617effde-ae31-5f48-928a-acdf7b6bc0bb", + "type": "epm-packages-assets" + }, + { + "id": "10245259-aff6-5cc9-b60b-9d88a230894e", + "type": "epm-packages-assets" + }, + { + "id": "753a2e77-13fe-5aa8-94a7-08e9357e64f0", + "type": "epm-packages-assets" + }, + { + "id": "4132f76c-78bc-5d70-a7cd-421910242f96", + "type": "epm-packages-assets" + }, + { + "id": "74230ee0-f671-57fc-bf3a-1c1be03acf22", + "type": "epm-packages-assets" + }, + { + "id": "a2465b23-c15e-56f9-acad-e2d5387cae48", + "type": "epm-packages-assets" + }, + { + "id": "94586e3f-78a0-5cf8-b4c2-923f4516153a", + "type": "epm-packages-assets" + }, + { + "id": "7b356571-eb79-541c-ba99-e6fdebf74e98", + "type": "epm-packages-assets" + }, + { + "id": "babd82eb-7317-58c0-a5fc-4d14ca1f2d17", + "type": "epm-packages-assets" + }, + { + "id": "aa68dd98-4844-5162-b96f-e6b5eae5f987", + "type": "epm-packages-assets" + } + ], + "es_index_patterns": { + "access": "logs-apache.access-*", + "error": "logs-apache.error-*", + "status": "metrics-apache.status-*" + }, + "name": "apache", + "version": "1.1.0", + "internal": false, + "removable": true, + "install_version": "1.1.0", + "install_status": "installed", + "install_started_at": "2021-09-30T10:46:58.713Z", + "install_source": "registry" + }, + "references": [], + "migrationVersion": { + "epm-packages": "7.14.1" + }, + "coreMigrationVersion": "8.0.0" + } + } +} \ No newline at end of file diff --git a/x-pack/plugins/fleet/cypress/fixtures/integrations/create_integration_response.json b/x-pack/plugins/fleet/cypress/fixtures/integrations/create_integration_response.json new file mode 100644 index 0000000000000..6820aadd01fb1 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/fixtures/integrations/create_integration_response.json @@ -0,0 +1,255 @@ +{ + "item": { + "id": "1", + "version": "WzI4NDAsMV0=", + "name": "apache-1", + "description": "", + "namespace": "default", + "policy_id": "9ced27e0-20ff-11ec-b353-dd9d66c6f483", + "enabled": true, + "output_id": "", + "inputs": [ + { + "type": "logfile", + "policy_template": "apache", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "apache.access" + }, + "vars": { + "paths": { + "value": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ], + "type": "text" + }, + "tags": { + "value": [ + "apache-access" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "logfile-apache.access-1c588150-010b-448a-b2b8-820d1b33811e", + "compiled_stream": { + "paths": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ], + "tags": [ + "apache-access" + ], + "exclude_files": [ + ".gz$" + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "apache.error" + }, + "vars": { + "paths": { + "value": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ], + "type": "text" + }, + "tags": { + "value": [ + "apache-error" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "logfile-apache.error-1c588150-010b-448a-b2b8-820d1b33811e", + "compiled_stream": { + "paths": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ], + "exclude_files": [ + ".gz$" + ], + "tags": [ + "apache-error" + ], + "processors": [ + { + "add_locale": null + } + ] + } + } + ] + }, + { + "type": "httpjson", + "policy_template": "apache", + "enabled": false, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "apache.access" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"access*\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded", + "apache-access" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "httpjson-apache.access-1c588150-010b-448a-b2b8-820d1b33811e" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "apache.error" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=apache:error OR sourcetype=apache_error", + "type": "text" + }, + "tags": { + "value": [ + "forwarded", + "apache-error" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "httpjson-apache.error-1c588150-010b-448a-b2b8-820d1b33811e" + } + ], + "vars": { + "url": { + "value": "https://server.example.com:8089", + "type": "text" + }, + "username": { + "type": "text" + }, + "password": { + "type": "password" + }, + "token": { + "type": "password" + }, + "ssl": { + "value": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n", + "type": "yaml" + } + } + }, + { + "type": "apache/metrics", + "policy_template": "apache", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "apache.status" + }, + "vars": { + "period": { + "value": "30s", + "type": "text" + }, + "server_status_path": { + "value": "/server-status", + "type": "text" + } + }, + "id": "apache/metrics-apache.status-1c588150-010b-448a-b2b8-820d1b33811e", + "compiled_stream": { + "metricsets": [ + "status" + ], + "hosts": [ + "http://127.0.0.1" + ], + "period": "30s", + "server_status_path": "/server-status" + } + } + ], + "vars": { + "hosts": { + "value": [ + "http://127.0.0.1" + ], + "type": "text" + } + } + } + ], + "package": { + "name": "apache", + "title": "Apache", + "version": "1.1.0" + }, + "revision": 1, + "created_at": "2021-09-29T09:12:55.869Z", + "created_by": "elastic", + "updated_at": "2021-09-29T09:12:55.869Z", + "updated_by": "elastic" + } +} \ No newline at end of file diff --git a/x-pack/plugins/fleet/cypress/fixtures/integrations/list.json b/x-pack/plugins/fleet/cypress/fixtures/integrations/list.json new file mode 100644 index 0000000000000..73c3ff54c5d95 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/fixtures/integrations/list.json @@ -0,0 +1,260 @@ +{ + "items": [ + { + "id": "1", + "version": "WzczOSwxXQ==", + "name": "apache-1", + "description": "", + "namespace": "default", + "policy_id": "30e16140-2106-11ec-a289-25321523992d", + "enabled": true, + "output_id": "", + "inputs": [ + { + "type": "logfile", + "policy_template": "apache", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "apache.access" + }, + "vars": { + "paths": { + "value": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ], + "type": "text" + }, + "tags": { + "value": [ + "apache-access" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "logfile-apache.access-63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "compiled_stream": { + "paths": [ + "/var/log/apache2/access.log*", + "/var/log/apache2/other_vhosts_access.log*", + "/var/log/httpd/access_log*" + ], + "tags": [ + "apache-access" + ], + "exclude_files": [ + ".gz$" + ] + } + }, + { + "enabled": true, + "data_stream": { + "type": "logs", + "dataset": "apache.error" + }, + "vars": { + "paths": { + "value": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ], + "type": "text" + }, + "tags": { + "value": [ + "apache-error" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "logfile-apache.error-63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "compiled_stream": { + "paths": [ + "/var/log/apache2/error.log*", + "/var/log/httpd/error_log*" + ], + "exclude_files": [ + ".gz$" + ], + "tags": [ + "apache-error" + ], + "processors": [ + { + "add_locale": null + } + ] + } + } + ] + }, + { + "type": "httpjson", + "policy_template": "apache", + "enabled": false, + "streams": [ + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "apache.access" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=\"access*\"", + "type": "text" + }, + "tags": { + "value": [ + "forwarded", + "apache-access" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "httpjson-apache.access-63172a6b-4f00-4376-b5e6-fe9b3f00fc79" + }, + { + "enabled": false, + "data_stream": { + "type": "logs", + "dataset": "apache.error" + }, + "vars": { + "interval": { + "value": "10s", + "type": "text" + }, + "search": { + "value": "search sourcetype=apache:error OR sourcetype=apache_error", + "type": "text" + }, + "tags": { + "value": [ + "forwarded", + "apache-error" + ], + "type": "text" + }, + "preserve_original_event": { + "value": false, + "type": "bool" + }, + "processors": { + "type": "yaml" + } + }, + "id": "httpjson-apache.error-63172a6b-4f00-4376-b5e6-fe9b3f00fc79" + } + ], + "vars": { + "url": { + "value": "https://server.example.com:8089", + "type": "text" + }, + "username": { + "type": "text" + }, + "password": { + "type": "password" + }, + "token": { + "type": "password" + }, + "ssl": { + "value": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n", + "type": "yaml" + } + } + }, + { + "type": "apache/metrics", + "policy_template": "apache", + "enabled": true, + "streams": [ + { + "enabled": true, + "data_stream": { + "type": "metrics", + "dataset": "apache.status" + }, + "vars": { + "period": { + "value": "30s", + "type": "text" + }, + "server_status_path": { + "value": "/server-status", + "type": "text" + } + }, + "id": "apache/metrics-apache.status-63172a6b-4f00-4376-b5e6-fe9b3f00fc79", + "compiled_stream": { + "metricsets": [ + "status" + ], + "hosts": [ + "http://127.0.0.1" + ], + "period": "30s", + "server_status_path": "/server-status" + } + } + ], + "vars": { + "hosts": { + "value": [ + "http://127.0.0.1" + ], + "type": "text" + } + } + } + ], + "package": { + "name": "apache", + "title": "Apache", + "version": "1.1.0" + }, + "revision": 1, + "created_at": "2021-09-29T09:52:12.865Z", + "created_by": "elastic", + "updated_at": "2021-09-29T09:52:12.865Z", + "updated_by": "elastic" + } + ], + "total": 1, + "page": 1, + "perPage": 20 +} \ No newline at end of file diff --git a/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts b/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts new file mode 100644 index 0000000000000..804fe56510c1d --- /dev/null +++ b/x-pack/plugins/fleet/cypress/integration/fleet_startup.spec.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ADD_AGENT_BUTTON, AGENT_POLICIES_TAB, ENROLLMENT_TOKENS_TAB } from '../screens/fleet'; +import { FLEET, navigateTo } from '../tasks/navigation'; + +describe('Fleet startup', () => { + before(() => { + navigateTo(FLEET); + }); + + it('should display Add agent button and Healthy agent once Fleet Agent page loaded', () => { + cy.getBySel(ADD_AGENT_BUTTON).contains('Add agent'); + cy.get('.euiBadge').contains('Healthy'); + }); + + it('should display default agent policies on agent policies tab', () => { + cy.getBySel(AGENT_POLICIES_TAB).click(); + cy.get('.euiLink').contains('Default policy'); + cy.get('.euiLink').contains('Default Fleet Server policy'); + }); + + it('should display default tokens on enrollment tokens tab', () => { + cy.getBySel(ENROLLMENT_TOKENS_TAB).click(); + cy.get('.euiTableRow').should('have.length', 2); + cy.get('.euiTableRowCell').contains('Default policy'); + cy.get('.euiTableRowCell').contains('Default Fleet Server policy'); + }); +}); diff --git a/x-pack/plugins/fleet/cypress/integration/integrations.spec.ts b/x-pack/plugins/fleet/cypress/integration/integrations.spec.ts new file mode 100644 index 0000000000000..88769ece39f2f --- /dev/null +++ b/x-pack/plugins/fleet/cypress/integration/integrations.spec.ts @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { INTEGRATIONS, navigateTo } from '../tasks/navigation'; +import { + addIntegration, + installPackageWithVersion, + deleteIntegrations, + clickIfVisible, +} from '../tasks/integrations'; +import { + CONFIRM_MODAL_BTN, + FLYOUT_CLOSE_BTN_SEL, + INTEGRATIONS_CARD, + INTEGRATION_NAME_LINK, + LATEST_VERSION, + PACKAGE_VERSION, + POLICIES_TAB, + SETTINGS_TAB, + UPDATE_PACKAGE_BTN, +} from '../screens/integrations'; + +describe('Add Integration', () => { + const integration = 'Apache'; + + describe('Real API', () => { + afterEach(() => { + deleteIntegrations(integration); + }); + it('should display Apache integration in the Policies list once installed ', () => { + addAndVerifyIntegration(); + }); + + it('should upgrade policies with integration update', () => { + const oldVersion = '0.3.3'; + installPackageWithVersion('apache', oldVersion); + navigateTo(`app/integrations/detail/apache-${oldVersion}/policies`); + + addIntegration(); + + cy.getBySel(INTEGRATION_NAME_LINK).contains('apache-'); + cy.getBySel(PACKAGE_VERSION).contains(oldVersion); + + clickIfVisible(FLYOUT_CLOSE_BTN_SEL); + + cy.getBySel(SETTINGS_TAB).click(); + cy.getBySel(UPDATE_PACKAGE_BTN).click(); + cy.getBySel(CONFIRM_MODAL_BTN).click(); + + cy.getBySel(LATEST_VERSION).then(($title) => { + const newVersion = $title.text(); + cy.get('#upgradePoliciesCheckbox').should('not.exist'); + cy.getBySel(POLICIES_TAB).click(); + cy.getBySel(PACKAGE_VERSION).contains(oldVersion).should('not.exist'); + cy.getBySel(PACKAGE_VERSION).contains(newVersion); + }); + }); + }); + + function addAndVerifyIntegration() { + cy.intercept('GET', '/api/fleet/epm/packages?*').as('packages'); + navigateTo(INTEGRATIONS); + cy.wait('@packages'); + cy.get('.euiLoadingSpinner').should('not.exist'); + cy.get('input[placeholder="Search for integrations"]').type('Apache'); + cy.get(INTEGRATIONS_CARD).contains(integration).click(); + addIntegration(); + cy.getBySel(INTEGRATION_NAME_LINK).contains('apache-'); + } + + it.skip('[Mocked requests] should display Apache integration in the Policies list once installed ', () => { + cy.intercept('POST', '/api/fleet/package_policies', { + fixture: 'integrations/create_integration_response.json', + }); + cy.intercept( + 'GET', + '/api/fleet/package_policies?page=1&perPage=20&kuery=ingest-package-policies.package.name%3A%20apache', + { fixture: 'integrations/list.json' } + ); + cy.intercept('GET', '/api/fleet/agent_policies?*', { + fixture: 'integrations/agent_policies.json', + }); + cy.intercept('GET', '/api/fleet/agent_policies/30e16140-2106-11ec-a289-25321523992d', { + fixture: 'integrations/agent_policy.json', + }); + // TODO fixture includes 1 package policy, should be empty initially + cy.intercept('GET', '/api/fleet/epm/packages/apache-1.1.0', { + fixture: 'integrations/apache.json', + }); + addAndVerifyIntegration(); + }); +}); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.js b/x-pack/plugins/fleet/cypress/plugins/index.ts similarity index 91% rename from x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.js rename to x-pack/plugins/fleet/cypress/plugins/index.ts index aeeb88c6d1279..a30fd07912cf8 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.js +++ b/x-pack/plugins/fleet/cypress/plugins/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -/// +// / // *********************************************************** // This example plugins/index.js can be used to load plugins // @@ -22,7 +22,7 @@ /** * @type {Cypress.PluginConfig} */ -module.exports = () => { +module.exports = (_on: any, _config: any) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config }; diff --git a/x-pack/plugins/fleet/cypress/screens/fleet.ts b/x-pack/plugins/fleet/cypress/screens/fleet.ts new file mode 100644 index 0000000000000..6be51e5ed24bc --- /dev/null +++ b/x-pack/plugins/fleet/cypress/screens/fleet.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const ADD_AGENT_BUTTON = 'addAgentButton'; + +export const AGENT_POLICIES_TAB = 'fleet-agent-policies-tab'; +export const ENROLLMENT_TOKENS_TAB = 'fleet-enrollment-tokens-tab'; diff --git a/x-pack/plugins/fleet/cypress/screens/integrations.ts b/x-pack/plugins/fleet/cypress/screens/integrations.ts new file mode 100644 index 0000000000000..d42fb904b3224 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/screens/integrations.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const ADD_POLICY_BTN = 'addIntegrationPolicyButton'; +export const CREATE_PACKAGE_POLICY_SAVE_BTN = 'createPackagePolicySaveButton'; +export const INTEGRATIONS_CARD = '.euiCard__titleAnchor'; + +export const INTEGRATION_NAME_LINK = 'integrationNameLink'; + +export const CONFIRM_MODAL_BTN = 'confirmModalConfirmButton'; +export const CONFIRM_MODAL_BTN_SEL = `[data-test-subj=${CONFIRM_MODAL_BTN}]`; + +export const FLYOUT_CLOSE_BTN_SEL = '[data-test-subj="euiFlyoutCloseButton"]'; + +export const SETTINGS_TAB = 'tab-settings'; +export const POLICIES_TAB = 'tab-policies'; + +export const UPDATE_PACKAGE_BTN = 'updatePackageBtn'; +export const LATEST_VERSION = 'latestVersion'; + +export const PACKAGE_VERSION = 'packageVersionText'; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/archives_metadata.ts b/x-pack/plugins/fleet/cypress/screens/navigation.ts similarity index 62% rename from x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/archives_metadata.ts rename to x-pack/plugins/fleet/cypress/screens/navigation.ts index 3382f0f8ee460..fee38161b6b2b 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_archiver/archives_metadata.ts +++ b/x-pack/plugins/fleet/cypress/screens/navigation.ts @@ -5,10 +5,4 @@ * 2.0. */ -/* eslint-disable-next-line*/ - export default { - 'apm_8.0.0': { - start: '2021-08-03T06:50:15.910Z', - end: '2021-08-03T07:20:15.910Z', - }, -}; +export const TOGGLE_NAVIGATION_BTN = '[data-test-subj="toggleNavButton"]'; diff --git a/x-pack/plugins/fleet/cypress/support/commands.ts b/x-pack/plugins/fleet/cypress/support/commands.ts new file mode 100644 index 0000000000000..54cc44f0057f3 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/support/commands.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// diff --git a/x-pack/plugins/fleet/cypress/support/index.ts b/x-pack/plugins/fleet/cypress/support/index.ts new file mode 100644 index 0000000000000..f074e424d93c3 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/support/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// / + +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + interface Chainable { + getBySel(value: string): Chainable; + } + } +} + +function getBySel(selector: string, ...args: any[]) { + return cy.get(`[data-test-subj=${selector}]`, ...args); +} + +Cypress.Commands.add('getBySel', getBySel); + +// Alternatively you can use CommonJS syntax: +// require('./commands') +Cypress.on('uncaught:exception', () => { + return false; +}); diff --git a/x-pack/plugins/fleet/cypress/tasks/integrations.ts b/x-pack/plugins/fleet/cypress/tasks/integrations.ts new file mode 100644 index 0000000000000..f1c891fa1186c --- /dev/null +++ b/x-pack/plugins/fleet/cypress/tasks/integrations.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + ADD_POLICY_BTN, + CONFIRM_MODAL_BTN, + CREATE_PACKAGE_POLICY_SAVE_BTN, + FLYOUT_CLOSE_BTN_SEL, + INTEGRATION_NAME_LINK, +} from '../screens/integrations'; + +export const addIntegration = () => { + cy.getBySel(ADD_POLICY_BTN).click(); + cy.getBySel(CREATE_PACKAGE_POLICY_SAVE_BTN).click(); + // sometimes agent is assigned to default policy, sometimes not + cy.getBySel(CONFIRM_MODAL_BTN).click(); + + cy.getBySel(CREATE_PACKAGE_POLICY_SAVE_BTN).should('not.exist'); + clickIfVisible(FLYOUT_CLOSE_BTN_SEL); +}; + +export function clickIfVisible(selector: string) { + cy.get('body').then(($body) => { + if ($body.find(selector).length) { + cy.get(selector).click(); + } + }); +} + +export const deleteIntegrations = async (integration: string) => { + const ids: string[] = []; + cy.getBySel(INTEGRATION_NAME_LINK) + .each(($a) => { + const href = $a.attr('href') as string; + ids.push(href.substr(href.lastIndexOf('/') + 1)); + }) + .then(() => { + cy.request({ + url: `/api/fleet/package_policies/delete`, + headers: { 'kbn-xsrf': 'cypress' }, + body: `{ "packagePolicyIds": ${JSON.stringify(ids)} }`, + method: 'POST', + }); + }); +}; + +export const installPackageWithVersion = (integration: string, version: string) => { + cy.request({ + url: `/api/fleet/epm/packages/${integration}-${version}`, + headers: { 'kbn-xsrf': 'cypress' }, + body: '{ "force": true }', + method: 'POST', + }); +}; diff --git a/x-pack/plugins/fleet/cypress/tasks/navigation.ts b/x-pack/plugins/fleet/cypress/tasks/navigation.ts new file mode 100644 index 0000000000000..a2dd131b647a6 --- /dev/null +++ b/x-pack/plugins/fleet/cypress/tasks/navigation.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TOGGLE_NAVIGATION_BTN } from '../screens/navigation'; + +export const INTEGRATIONS = 'app/integrations#/'; +export const FLEET = 'app/fleet/'; + +export const navigateTo = (page: string) => { + cy.visit(page); +}; + +export const openNavigationFlyout = () => { + cy.get(TOGGLE_NAVIGATION_BTN).click(); +}; diff --git a/x-pack/plugins/fleet/cypress/tsconfig.json b/x-pack/plugins/fleet/cypress/tsconfig.json new file mode 100644 index 0000000000000..1adb067fe682e --- /dev/null +++ b/x-pack/plugins/fleet/cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.base.json", + "include": [ + "**/*" + ], + "exclude": [ + "target/**/*" + ], + "compilerOptions": { + "outDir": "target/types", + "types": [ + "cypress", + "node" + ], + "resolveJsonModule": true, + }, + } diff --git a/x-pack/plugins/fleet/package.json b/x-pack/plugins/fleet/package.json index e374dabb82458..ef15c2fc6bb66 100644 --- a/x-pack/plugins/fleet/package.json +++ b/x-pack/plugins/fleet/package.json @@ -3,5 +3,11 @@ "name": "fleet", "version": "8.0.0", "private": true, - "license": "Elastic-License" + "license": "Elastic-License", + "scripts": { + "cypress:open": "../../../node_modules/.bin/cypress open --config-file ./cypress/cypress.json", + "cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/fleet_cypress/visual_config.ts", + "cypress:run": "../../../node_modules/.bin/cypress run --config-file ./cypress/cypress.json", + "cypress:run-as-ci": "node ../../../scripts/functional_tests --config ../../test/fleet_cypress/cli_config.ts" + } } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx index d6a6210bc8673..5fa60eb72b2e5 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx @@ -224,6 +224,7 @@ export const SearchAndFilterBar: React.FunctionComponent<{ fill iconType="plusInCircle" onClick={() => setIsEnrollmentFlyoutOpen(true)} + data-test-subj="addAgentButton" > diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/components/package_policy_agents_cell.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/components/package_policy_agents_cell.tsx index 0ecab3290051e..fc3007b174ced 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/components/package_policy_agents_cell.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/components/package_policy_agents_cell.tsx @@ -22,8 +22,12 @@ const AddAgentButton = ({ onAddAgent }: { onAddAgent: () => void }) => ( ); const AddAgentButtonWithPopover = ({ onAddAgent }: { onAddAgent: () => void }) => { - const button = ; const [isHelpOpen, setIsHelpOpen] = useState(true); + const onAddAgentCloseHelp = () => { + setIsHelpOpen(false); + onAddAgent(); + }; + const button = ; return ( - + = memo(({ packageInfo }: Props) => { /> - + {installedVersion} @@ -262,7 +262,7 @@ export const SettingsPage: React.FC = memo(({ packageInfo }: Props) => { /> - + {latestVersion} diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/update_button.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/update_button.tsx index b5a8394fa2cb2..48d4ef5d846d4 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/update_button.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/update_button.tsx @@ -289,6 +289,7 @@ export const UpdateButton: React.FunctionComponent = ({ onClick={ upgradePackagePolicies ? () => setIsUpdateModalVisible(true) : handleClickUpdate } + data-test-subj="updatePackageBtn" > ; }) => { const { docLinks } = useStartServices(); - + const theme = useTheme() as EuiTheme; const optionalProps: { offset?: number } = {}; if (offset !== undefined) { @@ -55,6 +58,7 @@ export const AddAgentHelpPopover = ({ /> } + zIndex={theme.eui.euiZLevel1 - 1} // put popover behind any modals that happen to be open isStepOpen={isOpen} minWidth={300} onFinish={() => {}} diff --git a/x-pack/plugins/fleet/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts index 46747762213f1..b6207316829ee 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.test.ts @@ -1843,6 +1843,100 @@ describe('Package policy service', () => { expect(logfileStream?.enabled).toBe(false); }); }); + + describe('when a datastream is deleted from an input', () => { + it('it remove the non existing datastream', () => { + const basePackagePolicy: NewPackagePolicy = { + name: 'base-package-policy', + description: 'Base Package Policy', + namespace: 'default', + enabled: true, + policy_id: 'xxxx', + output_id: 'xxxx', + package: { + name: 'test-package', + title: 'Test Package', + version: '0.0.1', + }, + inputs: [ + { + type: 'logs', + policy_template: 'template_1', + enabled: true, + vars: { + path: { + type: 'text', + value: ['/var/log/logfile.log'], + }, + }, + streams: [ + { + enabled: true, + data_stream: { dataset: 'dataset.test123', type: 'log' }, + }, + ], + }, + ], + }; + + const packageInfo: PackageInfo = { + name: 'test-package', + description: 'Test Package', + title: 'Test Package', + version: '0.0.1', + latestVersion: '0.0.1', + release: 'experimental', + format_version: '1.0.0', + owner: { github: 'elastic/fleet' }, + policy_templates: [ + { + name: 'template_1', + title: 'Template 1', + description: 'Template 1', + inputs: [ + { + type: 'logs', + title: 'Log', + description: 'Log Input', + vars: [ + { + name: 'path', + type: 'text', + }, + ], + }, + ], + }, + ], + // @ts-ignore + assets: {}, + }; + + const inputsOverride: NewPackagePolicyInput[] = [ + { + type: 'logs', + enabled: true, + streams: [], + vars: { + path: { + type: 'text', + value: '/var/log/new-logfile.log', + }, + }, + }, + ]; + + const result = overridePackageInputs( + basePackagePolicy, + packageInfo, + // TODO: Update this type assertion when the `InputsOverride` type is updated such + // that it no longer causes unresolvable type errors when used directly + inputsOverride as InputsOverride[], + false + ); + expect(result.inputs[0]?.vars?.path.value).toEqual(['/var/log/logfile.log']); + }); + }); }); }); diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index c03ccfc43ebd8..39902d35feb08 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -404,6 +404,7 @@ class PackagePolicyService { pkgName: packagePolicy.package.name, pkgVersion: packagePolicy.package.version, }); + const registryPkgInfo = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version); inputs = await this._compilePackagePolicyInputs( registryPkgInfo, @@ -1111,7 +1112,9 @@ export function overridePackageInputs( } if (override.vars) { - originalInput = deepMergeVars(originalInput, override) as NewPackagePolicyInput; + const indexOfInput = inputs.indexOf(originalInput); + inputs[indexOfInput] = deepMergeVars(originalInput, override) as NewPackagePolicyInput; + originalInput = inputs[indexOfInput]; } if (override.streams) { @@ -1130,10 +1133,24 @@ export function overridePackageInputs( } if (stream.vars) { - originalStream = deepMergeVars(originalStream, stream as InputsOverride); + const indexOfStream = originalInput.streams.indexOf(originalStream); + originalInput.streams[indexOfStream] = deepMergeVars( + originalStream, + stream as InputsOverride + ); + originalStream = originalInput.streams[indexOfStream]; } } } + + // Filter all stream that have been removed from the input + originalInput.streams = originalInput.streams.filter((originalStream) => { + return ( + override.streams?.some( + (s) => s.data_stream.dataset === originalStream.data_stream.dataset + ) ?? false + ); + }); } const resultingPackagePolicy: NewPackagePolicy = { diff --git a/x-pack/plugins/graph/public/helpers/format_http_error.ts b/x-pack/plugins/graph/public/helpers/format_http_error.ts index 79c1bc8a45638..13ab8c02848bf 100644 --- a/x-pack/plugins/graph/public/helpers/format_http_error.ts +++ b/x-pack/plugins/graph/public/helpers/format_http_error.ts @@ -6,9 +6,11 @@ */ import { i18n } from '@kbn/i18n'; -import { IHttpFetchError } from 'kibana/public'; +import { IHttpFetchError, ResponseErrorBody } from 'kibana/public'; -export function formatHttpError(error: IHttpFetchError) { +export function formatHttpError( + error: IHttpFetchError +) { if (!error.response) { return i18n.translate('xpack.graph.fatalError.unavailableServerErrorMessage', { defaultMessage: @@ -20,9 +22,9 @@ export function formatHttpError(error: IHttpFetchError) { return i18n.translate('xpack.graph.fatalError.errorStatusMessage', { defaultMessage: 'Error {errStatus} {errStatusText}: {errMessage}', values: { - errStatus: error.body.status, - errStatusText: error.body.statusText, - errMessage: error.body.message, + errStatus: error.body?.status, + errStatusText: error.body?.statusText, + errMessage: error.body?.message, }, }); } diff --git a/x-pack/plugins/graph/public/helpers/use_graph_loader.ts b/x-pack/plugins/graph/public/helpers/use_graph_loader.ts index c133f6bf260cd..c895d4156fa7b 100644 --- a/x-pack/plugins/graph/public/helpers/use_graph_loader.ts +++ b/x-pack/plugins/graph/public/helpers/use_graph_loader.ts @@ -7,7 +7,7 @@ import { useCallback, useState } from 'react'; import { ToastsStart } from 'kibana/public'; -import { IHttpFetchError, CoreStart } from 'kibana/public'; +import { IHttpFetchError, ResponseErrorBody, CoreStart } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { ExploreRequest, GraphExploreCallback, GraphSearchCallback, SearchRequest } from '../types'; import { formatHttpError } from './format_http_error'; @@ -21,7 +21,7 @@ export const useGraphLoader = ({ toastNotifications, coreStart }: UseGraphLoader const [loading, setLoading] = useState(false); const handleHttpError = useCallback( - (error: IHttpFetchError) => { + (error: IHttpFetchError) => { toastNotifications.addDanger(formatHttpError(error)); }, [toastNotifications] @@ -59,10 +59,10 @@ export const useGraphLoader = ({ toastNotifications, coreStart }: UseGraphLoader }; setLoading(true); return coreStart.http - .post('../api/graph/graphExplore', request) + .post<{ resp: { timed_out: unknown } }>('../api/graph/graphExplore', request) .then(function (data) { const response = data.resp; - if (response.timed_out) { + if (response?.timed_out) { toastNotifications.addWarning( i18n.translate('xpack.graph.exploreGraph.timedOutWarningText', { defaultMessage: 'Exploration timed out', @@ -88,7 +88,7 @@ export const useGraphLoader = ({ toastNotifications, coreStart }: UseGraphLoader }; setLoading(true); coreStart.http - .post('../api/graph/searchProxy', request) + .post<{ resp: unknown }>('../api/graph/searchProxy', request) .then(function (data) { const response = data.resp; responseHandler(response); diff --git a/x-pack/plugins/graph/public/services/fetch_top_nodes.ts b/x-pack/plugins/graph/public/services/fetch_top_nodes.ts index 34d34317d7116..1b1e91ac7277b 100644 --- a/x-pack/plugins/graph/public/services/fetch_top_nodes.ts +++ b/x-pack/plugins/graph/public/services/fetch_top_nodes.ts @@ -96,8 +96,8 @@ export async function fetchTopNodes( .reduce((allAggs, subAgg) => ({ ...allAggs, ...subAgg })); const body = createSamplerSearchBody(aggs); - const response: TopTermsAggResponse = ( - await post('../api/graph/searchProxy', { + const response = ( + await post<{ resp: TopTermsAggResponse }>('../api/graph/searchProxy', { body: JSON.stringify({ index, body }), }) ).resp; diff --git a/x-pack/plugins/graph/server/sample_data/ecommerce.ts b/x-pack/plugins/graph/server/sample_data/ecommerce.ts index 36e125864600d..fe2f319acef88 100644 --- a/x-pack/plugins/graph/server/sample_data/ecommerce.ts +++ b/x-pack/plugins/graph/server/sample_data/ecommerce.ts @@ -348,7 +348,6 @@ const wsState: any = { maxValuesPerDoc: 1, minDocCount: 3, }, - indexPatternRefName: 'indexPattern_0', }; export function registerEcommerceSampleData(sampleDataRegistry: SampleDataRegistrySetup) { @@ -365,16 +364,11 @@ export function registerEcommerceSampleData(sampleDataRegistry: SampleDataRegist numVertices: 12, version: 1, wsState: JSON.stringify(JSON.stringify(wsState)), + legacyIndexPatternRef: 'kibana_sample_data_ecommerce', }, - references: [ - { - name: 'indexPattern_0', - type: 'index-pattern', - id: 'kibana_sample_data_ecommerce', - }, - ], + references: [], migrationVersion: { - 'graph-workspace': '7.0.0', + 'graph-workspace': '7.11.0', }, updated_at: '2020-01-09T16:40:36.122Z', }, @@ -383,7 +377,11 @@ export function registerEcommerceSampleData(sampleDataRegistry: SampleDataRegist export function registerEcommerceSampleDataLink(sampleDataRegistry: SampleDataRegistrySetup) { sampleDataRegistry.addAppLinksToSampleDataset(datasetId, [ { - path: createWorkspacePath('46fa9d30-319c-11ea-bbe4-818d9c786051'), + sampleObject: { + type: 'graph-workspace', + id: '46fa9d30-319c-11ea-bbe4-818d9c786051', + }, + getPath: createWorkspacePath, label: i18n.translate('xpack.graph.sampleData.label', { defaultMessage: 'Graph' }), icon: APP_ICON, }, diff --git a/x-pack/plugins/graph/server/sample_data/flights.ts b/x-pack/plugins/graph/server/sample_data/flights.ts index 61beacc3552f7..f378c916e4b87 100644 --- a/x-pack/plugins/graph/server/sample_data/flights.ts +++ b/x-pack/plugins/graph/server/sample_data/flights.ts @@ -1602,7 +1602,6 @@ const wsState: any = { maxValuesPerDoc: 1, minDocCount: 3, }, - indexPatternRefName: 'indexPattern_0', }; export function registerFlightsSampleData(sampleDataRegistry: SampleDataRegistrySetup) { @@ -1619,16 +1618,11 @@ export function registerFlightsSampleData(sampleDataRegistry: SampleDataRegistry numVertices: 91, version: 1, wsState: JSON.stringify(JSON.stringify(wsState)), + legacyIndexPatternRef: 'kibana_sample_data_flights', }, - references: [ - { - name: 'indexPattern_0', - type: 'index-pattern', - id: 'kibana_sample_data_flights', - }, - ], + references: [], migrationVersion: { - 'graph-workspace': '7.0.0', + 'graph-workspace': '7.11.0', }, updated_at: '2020-01-09T15:55:24.013Z', }, @@ -1637,7 +1631,11 @@ export function registerFlightsSampleData(sampleDataRegistry: SampleDataRegistry export function registerFlightsSampleDataLink(sampleDataRegistry: SampleDataRegistrySetup) { sampleDataRegistry.addAppLinksToSampleDataset(datasetId, [ { - path: createWorkspacePath('5dc018d0-32f8-11ea-bbe4-818d9c786051'), + sampleObject: { + type: 'graph-workspace', + id: '5dc018d0-32f8-11ea-bbe4-818d9c786051', + }, + getPath: createWorkspacePath, label: i18n.translate('xpack.graph.sampleData.label', { defaultMessage: 'Graph' }), icon: APP_ICON, }, diff --git a/x-pack/plugins/graph/server/sample_data/logs.ts b/x-pack/plugins/graph/server/sample_data/logs.ts index fbbbd8b493cee..af1132f5d37bc 100644 --- a/x-pack/plugins/graph/server/sample_data/logs.ts +++ b/x-pack/plugins/graph/server/sample_data/logs.ts @@ -419,7 +419,6 @@ const wsState: any = { maxValuesPerDoc: 1, minDocCount: 3, }, - indexPatternRefName: 'indexPattern_0', }; export function registerLogsSampleData(sampleDataRegistry: SampleDataRegistrySetup) { @@ -436,16 +435,11 @@ export function registerLogsSampleData(sampleDataRegistry: SampleDataRegistrySet numVertices: 27, version: 1, wsState: JSON.stringify(JSON.stringify(wsState)), + legacyIndexPatternRef: 'kibana_sample_data_logs', }, - references: [ - { - name: 'indexPattern_0', - type: 'index-pattern', - id: 'kibana_sample_data_logs', - }, - ], + references: [], migrationVersion: { - 'graph-workspace': '7.0.0', + 'graph-workspace': '7.11.0', }, updated_at: '2020-01-09T16:40:36.122Z', }, @@ -454,7 +448,11 @@ export function registerLogsSampleData(sampleDataRegistry: SampleDataRegistrySet export function registerLogsSampleDataLink(sampleDataRegistry: SampleDataRegistrySetup) { sampleDataRegistry.addAppLinksToSampleDataset(datasetId, [ { - path: createWorkspacePath('e2141080-32fa-11ea-bbe4-818d9c786051'), + sampleObject: { + type: 'graph-workspace', + id: 'e2141080-32fa-11ea-bbe4-818d9c786051', + }, + getPath: createWorkspacePath, label: i18n.translate('xpack.graph.sampleData.label', { defaultMessage: 'Graph' }), icon: APP_ICON, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts index fc37b62e30eb2..5fcc0054cdeb0 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts @@ -5,10 +5,15 @@ * 2.0. */ -import { IHttpFetchError } from 'src/core/public'; +import { IHttpFetchError, ResponseErrorBody } from 'src/core/public'; import { fatalErrors, toasts } from './notification'; -function createToastConfig(error: IHttpFetchError, errorTitle: string) { +interface CommonErrorBody extends ResponseErrorBody { + error: string; + attributes: { causes: unknown[] }; +} + +function createToastConfig(error: IHttpFetchError, errorTitle: string) { if (error && error.body) { // Error body shape is defined by the API. const { error: errorString, statusCode, message: errorMessage, attributes } = error.body; @@ -23,7 +28,7 @@ function createToastConfig(error: IHttpFetchError, errorTitle: string) { } } -export function showApiWarning(error: IHttpFetchError, errorTitle: string) { +export function showApiWarning(error: IHttpFetchError, errorTitle: string) { const toastConfig = createToastConfig(error, errorTitle); if (toastConfig) { @@ -35,7 +40,7 @@ export function showApiWarning(error: IHttpFetchError, errorTitle: string) { return fatalErrors.add(error, errorTitle); } -export function showApiError(error: IHttpFetchError, errorTitle: string) { +export function showApiError(error: IHttpFetchError, errorTitle: string) { const toastConfig = createToastConfig(error, errorTitle); if (toastConfig) { diff --git a/x-pack/plugins/index_management/public/application/services/api.ts b/x-pack/plugins/index_management/public/application/services/api.ts index 5929df2f2821d..5cfb881cb22cf 100644 --- a/x-pack/plugins/index_management/public/application/services/api.ts +++ b/x-pack/plugins/index_management/public/application/services/api.ts @@ -76,7 +76,7 @@ export async function deleteDataStreams(dataStreams: string[]) { } export async function loadIndices() { - const response = await httpService.httpClient.get(`${API_BASE_PATH}/indices`); + const response = await httpService.httpClient.get(`${API_BASE_PATH}/indices`); return response.data ? response.data : response; } @@ -87,7 +87,7 @@ export async function reloadIndices( const body = JSON.stringify({ indexNames, }); - const response = await httpService.httpClient.post(`${API_BASE_PATH}/indices/reload`, { + const response = await httpService.httpClient.post(`${API_BASE_PATH}/indices/reload`, { body, asSystemRequest, }); diff --git a/x-pack/plugins/infra/public/pages/link_to/use_host_ip_to_name.ts b/x-pack/plugins/infra/public/pages/link_to/use_host_ip_to_name.ts index f42e17c147a45..e2c25ba6fcfe2 100644 --- a/x-pack/plugins/infra/public/pages/link_to/use_host_ip_to_name.ts +++ b/x-pack/plugins/infra/public/pages/link_to/use_host_ip_to_name.ts @@ -24,7 +24,7 @@ export const useHostIpToName = (ipAddress: string | null, indexPattern: string | throw new Error('HTTP service is unavailable'); } if (ipAddress && indexPattern) { - const response = await fetch('/api/infra/ip_to_host', { + const response = await fetch('/api/infra/ip_to_host', { method: 'POST', body: JSON.stringify({ ip: ipAddress, diff --git a/x-pack/plugins/infra/server/plugin.ts b/x-pack/plugins/infra/server/plugin.ts index 247888fc2ae70..26d9f115405a6 100644 --- a/x-pack/plugins/infra/server/plugin.ts +++ b/x-pack/plugins/infra/server/plugin.ts @@ -158,7 +158,8 @@ export class InfraServerPlugin implements Plugin { plugins.home.sampleData.addAppLinksToSampleDataset('logs', [ { - path: `/app/logs`, + sampleObject: null, // indicates that there is no sample object associated with this app link's path + getPath: () => `/app/logs`, label: logsSampleDataLinkLabel, icon: 'logsApp', }, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.scss index b9f233d2b2950..37a4a88c32f22 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.scss @@ -1,10 +1,6 @@ @import '../../mixins'; @import '../../variables'; -.lnsSuggestionPanel__title { - margin-left: $euiSizeXS / 2; -} - .lnsSuggestionPanel__suggestions { @include euiScrollBar; @include lnsOverflowShadowHorizontal; @@ -16,7 +12,10 @@ // Padding / negative margins to make room for overflow shadow padding-left: $euiSizeXS; margin-left: -$euiSizeXS; - padding-bottom: $euiSizeXS; +} + +.lnsSuggestionPanel { + padding-bottom: $euiSizeS; } .lnsSuggestionPanel__button { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx index 26e0be3555714..47070822a8080 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx @@ -18,7 +18,7 @@ import { act } from 'react-dom/test-utils'; import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; import { SuggestionPanel, SuggestionPanelProps, SuggestionPanelWrapper } from './suggestion_panel'; import { getSuggestions, Suggestion } from './suggestion_helpers'; -import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui'; +import { EuiIcon, EuiPanel, EuiToolTip, EuiAccordion } from '@elastic/eui'; import { LensIconChartDatatable } from '../../assets/chart_datatable'; import { mountWithProvider } from '../../mocks'; import { LensAppState, PreviewState, setState, setToggleFullscreen } from '../../state_management'; @@ -264,8 +264,10 @@ describe('suggestion_panel', () => { preloadedState, }); - expect(instance.find(EuiIcon)).toHaveLength(1); - expect(instance.find(EuiIcon).prop('type')).toEqual(LensIconChartDatatable); + expect(instance.find('[data-test-subj="lnsSuggestionsPanel"]').find(EuiIcon)).toHaveLength(1); + expect( + instance.find('[data-test-subj="lnsSuggestionsPanel"]').find(EuiIcon).prop('type') + ).toEqual(LensIconChartDatatable); }); it('should return no suggestion if visualization has missing index-patterns', async () => { @@ -292,6 +294,16 @@ describe('suggestion_panel', () => { expect(instance.html()).toEqual(null); }); + it('should hide the selections when the accordion is hidden', async () => { + const { instance } = await mountWithProvider(); + expect(instance.find(EuiAccordion)).toHaveLength(1); + act(() => { + instance.find(EuiAccordion).at(0).simulate('change'); + }); + + expect(instance.find('[data-test-subj="lnsSuggestionsPanel"]')).toEqual({}); + }); + it('should render preview expression if there is one', () => { mockDatasource.getLayers.mockReturnValue(['first']); (getSuggestions as jest.Mock).mockReturnValue([ diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 5e5e19ea29e84..2f5ca01774ba1 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -8,17 +8,17 @@ import './suggestion_panel.scss'; import { camelCase, pick } from 'lodash'; -import React, { useState, useEffect, useMemo, useRef } from 'react'; +import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; import { EuiIcon, EuiTitle, EuiPanel, EuiIconTip, EuiToolTip, - EuiFlexGroup, - EuiFlexItem, EuiButtonEmpty, + EuiAccordion, } from '@elastic/eui'; import { IconType } from '@elastic/eui/src/components/icon/icon'; import { Ast, toExpression } from '@kbn/interpreter/common'; @@ -58,6 +58,7 @@ import { } from '../../state_management'; const MAX_SUGGESTIONS_DISPLAYED = 5; +const LOCAL_STORAGE_SUGGESTIONS_PANEL = 'LENS_SUGGESTIONS_PANEL_HIDDEN'; export interface SuggestionPanelProps { datasourceMap: DatasourceMap; @@ -189,6 +190,15 @@ export function SuggestionPanel({ const existsStagedPreview = useLensSelector((state) => Boolean(state.lens.stagedPreview)); const currentVisualization = useLensSelector(selectCurrentVisualization); const currentDatasourceStates = useLensSelector(selectCurrentDatasourceStates); + // get user's selection from localStorage, this key defines if the suggestions panel will be hidden or not + const [hideSuggestions, setHideSuggestions] = useLocalStorage( + LOCAL_STORAGE_SUGGESTIONS_PANEL, + false + ); + + const toggleSuggestions = useCallback(() => { + setHideSuggestions(!hideSuggestions); + }, [setHideSuggestions, hideSuggestions]); const missingIndexPatterns = getMissingIndexPattern( activeDatasourceId ? datasourceMap[activeDatasourceId] : null, @@ -322,9 +332,10 @@ export function SuggestionPanel({ return (
- - - +

-
- {existsStagedPreview && ( - + } + forceState={hideSuggestions ? 'closed' : 'open'} + onToggle={toggleSuggestions} + extraAction={ + existsStagedPreview && + !hideSuggestions && ( - - )} -
- -
- {currentVisualization.activeId && ( - - )} - {suggestions.map((suggestion, index) => { - return ( + ) + } + > +
+ {currentVisualization.activeId && !hideSuggestions && ( { - trackUiEvent('suggestion_clicked'); - if (lastSelectedSuggestion === index) { - rollbackToCurrentVisualization(); - } else { - setLastSelectedSuggestion(index); - switchToSuggestion(dispatchLens, suggestion); - } - }} - selected={index === lastSelectedSuggestion} + onSelect={rollbackToCurrentVisualization} + selected={lastSelectedSuggestion === -1} + showTitleAsLabel /> - ); - })} -
+ )} + {!hideSuggestions && + suggestions.map((suggestion, index) => { + return ( + { + trackUiEvent('suggestion_clicked'); + if (lastSelectedSuggestion === index) { + rollbackToCurrentVisualization(); + } else { + setLastSelectedSuggestion(index); + switchToSuggestion(dispatchLens, suggestion); + } + }} + selected={index === lastSelectedSuggestion} + /> + ); + })} +
+
); } 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 7aa972612c82f..5d8ba778e30d1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -165,7 +165,7 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) { setState((s) => ({ ...s, isLoading: true })); core.http - .post(`/api/lens/index_stats/${indexPattern.id}/field`, { + .post>(`/api/lens/index_stats/${indexPattern.id}/field`, { body: JSON.stringify({ dslQuery: esQuery.buildEsQuery( indexPattern, @@ -178,7 +178,7 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) { fieldName: field.name, }), }) - .then((results: FieldStatsResponse) => { + .then((results) => { setState((s) => ({ ...s, isLoading: false, diff --git a/x-pack/plugins/lens/public/visualization_container.scss b/x-pack/plugins/lens/public/visualization_container.scss index c3c15eff3819a..9fc16a0afc365 100644 --- a/x-pack/plugins/lens/public/visualization_container.scss +++ b/x-pack/plugins/lens/public/visualization_container.scss @@ -1,6 +1,6 @@ .lnsVisualizationContainer { @include euiScrollBar; - overflow: auto; + overflow: auto hidden; user-select: text; } diff --git a/x-pack/plugins/licensing/public/plugin.ts b/x-pack/plugins/licensing/public/plugin.ts index 1db463a47dbf0..f147b560ad5d3 100644 --- a/x-pack/plugins/licensing/public/plugin.ts +++ b/x-pack/plugins/licensing/public/plugin.ts @@ -14,6 +14,7 @@ import { createLicenseUpdate } from '../common/license_update'; import { License } from '../common/license'; import { mountExpiredBanner } from './expired_banner'; import { FeatureUsageService } from './services'; +import type { PublicLicenseJSON } from '../common/types'; export const licensingSessionStorageKey = 'xpack.licensing'; @@ -148,9 +149,9 @@ export class LicensingPlugin implements Plugin => { + private fetchLicense = async (core: CoreSetup): Promise => { try { - const response = await core.http.get({ + const response = await core.http.get({ path: this.infoEndpoint, asSystemRequest: true, }); diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 8f681cc9de70d..4d687969308bb 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -32,6 +32,13 @@ export type TileMetaFeature = Feature & { properties: { 'hits.total.relation': string; 'hits.total.value': number; + + // For _mvt requests with "aggs" property in request: aggregation statistics returned in the pattern outined below + // aggregations._count.min + // aggregations._count.max + // aggregations..min + // aggregations..max + [key: string]: number | string; }; }; diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts index aba25a6d0babf..ed8830a7c56b6 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts @@ -7,6 +7,7 @@ import { IndexPattern } from 'src/plugins/data/public'; import { AGG_TYPE } from '../../../../common/constants'; +import { TileMetaFeature } from '../../../../common/descriptor_types'; import { CountAggField } from './count_agg_field'; import { isMetricCountable } from '../../util/is_metric_countable'; import { CountAggFieldParams } from './agg_field_types'; @@ -104,4 +105,17 @@ export class AggField extends CountAggField { async getCategoricalFieldMetaRequest(size: number): Promise { return this._esDocField ? await this._esDocField.getCategoricalFieldMetaRequest(size) : null; } + + pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature) { + const minField = `aggregations.${this.getName()}.min`; + const maxField = `aggregations.${this.getName()}.max`; + return metaFeature.properties && + typeof metaFeature.properties[minField] === 'number' && + typeof metaFeature.properties[maxField] === 'number' + ? { + min: metaFeature.properties[minField] as number, + max: metaFeature.properties[maxField] as number, + } + : null; + } } diff --git a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts index d8301ccd35353..7f38379c1075b 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts @@ -9,6 +9,7 @@ import { IndexPattern } from 'src/plugins/data/public'; import { IESAggSource } from '../../sources/es_agg_source'; import { IVectorSource } from '../../sources/vector_source'; import { AGG_TYPE, FIELD_ORIGIN } from '../../../../common/constants'; +import { TileMetaFeature } from '../../../../common/descriptor_types'; import { ITooltipProperty, TooltipProperty } from '../../tooltips/tooltip_property'; import { ESAggTooltipProperty } from '../../tooltips/es_agg_tooltip_property'; import { IESAggField, CountAggFieldParams } from './agg_field_types'; @@ -109,4 +110,17 @@ export class CountAggField implements IESAggField { isEqual(field: IESAggField) { return field.getName() === this.getName(); } + + pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature) { + const minField = `aggregations._count.min`; + const maxField = `aggregations._count.max`; + return metaFeature.properties && + typeof metaFeature.properties[minField] === 'number' && + typeof metaFeature.properties[maxField] === 'number' + ? { + min: metaFeature.properties[minField] as number, + max: metaFeature.properties[maxField] as number, + } + : null; + } } diff --git a/x-pack/plugins/maps/public/classes/fields/agg/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/top_term_percentage_field.ts index ccb1cae201548..d0618f64a5e71 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/top_term_percentage_field.ts @@ -9,6 +9,7 @@ import { IESAggField } from './agg_field_types'; import { IVectorSource } from '../../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../../tooltips/tooltip_property'; import { TOP_TERM_PERCENTAGE_SUFFIX, FIELD_ORIGIN } from '../../../../common/constants'; +import { TileMetaFeature } from '../../../../common/descriptor_types'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; @@ -90,4 +91,8 @@ export class TopTermPercentageField implements IESAggField { isEqual(field: IESAggField) { return field.getName() === this.getName(); } + + pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature) { + return null; + } } diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index dcf6ac54dc836..96d42a91319e1 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { TileMetaFeature } from '../../../common/descriptor_types'; import { FIELD_ORIGIN } from '../../../common/constants'; import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; @@ -39,6 +40,8 @@ export interface IField { supportsFieldMetaFromEs(): boolean; isEqual(field: IField): boolean; + + pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature): { min: number; max: number } | null; } export class AbstractField implements IField { @@ -114,4 +117,8 @@ export class AbstractField implements IField { isEqual(field: IField) { return this._origin === field.getOrigin() && this._fieldName === field.getName(); } + + pluckRangeFromTileMetaFeature(metaFeature: TileMetaFeature) { + return null; + } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx index 5a08db3656136..488cafd07b694 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx @@ -460,14 +460,13 @@ export class ESSearchSource extends AbstractESSource implements ITiledSingleLaye if (!(this.indexPattern && this.indexPattern.title)) { return []; } - let success; - let matchingIndexes; try { - ({ success, matchingIndexes } = await getMatchingIndexes(this.indexPattern.title)); + const { success, matchingIndexes } = await getMatchingIndexes(this.indexPattern.title); + return success ? matchingIndexes : []; } catch (e) { // Fail silently + return []; } - return success ? matchingIndexes : []; } async supportsFeatureEditing(): Promise { diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/util/feature_edit.ts b/x-pack/plugins/maps/public/classes/sources/es_search_source/util/feature_edit.ts index af39019c2d14c..c4e12ee177f67 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/util/feature_edit.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/util/feature_edit.ts @@ -42,7 +42,10 @@ export const deleteFeatureFromIndex = async (indexName: string, featureId: strin }; export const getMatchingIndexes = async (indexPattern: string) => { - return await getHttp().fetch({ + return await getHttp().fetch<{ + success: boolean; + matchingIndexes: string[]; + }>({ path: GET_MATCHING_INDEXES_PATH, method: 'GET', query: { indexPattern }, @@ -50,7 +53,10 @@ export const getMatchingIndexes = async (indexPattern: string) => { }; export const getIsDrawLayer = async (index: string) => { - return await getHttp().fetch({ + return await getHttp().fetch<{ + success: boolean; + isDrawingIndex: boolean; + }>({ path: CHECK_IS_DRAWING_INDEX, method: 'GET', query: { index }, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index adf92a307a552..577fe60aa2e13 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -309,24 +309,17 @@ export class DynamicStyleProperty pluckOrdinalStyleMetaFromTileMetaFeatures( metaFeatures: TileMetaFeature[] ): RangeFieldMeta | null { - if (!this.isOrdinal()) { + if (!this._field || !this.isOrdinal()) { return null; } - const mbFieldName = this.getMbFieldName(); let min = Infinity; let max = -Infinity; for (let i = 0; i < metaFeatures.length; i++) { - const fieldMeta = metaFeatures[i].properties; - const minField = `aggregations.${mbFieldName}.min`; - const maxField = `aggregations.${mbFieldName}.max`; - if ( - fieldMeta && - typeof fieldMeta[minField] === 'number' && - typeof fieldMeta[maxField] === 'number' - ) { - min = Math.min(fieldMeta[minField] as number, min); - max = Math.max(fieldMeta[maxField] as number, max); + const range = this._field.pluckRangeFromTileMetaFeature(metaFeatures[i]); + if (range) { + min = Math.min(range.min, min); + max = Math.max(range.max, max); } } diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 8145b2bd8bb28..b98f7a8d55e03 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -77,7 +77,11 @@ export class MapsPlugin implements Plugin { home.sampleData.addAppLinksToSampleDataset('ecommerce', [ { - path: getFullPath('2c9c1f60-1909-11e9-919b-ffe5949a18d2'), + sampleObject: { + type: MAP_SAVED_OBJECT_TYPE, + id: '2c9c1f60-1909-11e9-919b-ffe5949a18d2', + }, + getPath: getFullPath, label: sampleDataLinkLabel, icon: APP_ICON, }, @@ -99,7 +103,11 @@ export class MapsPlugin implements Plugin { home.sampleData.addAppLinksToSampleDataset('flights', [ { - path: getFullPath('5dd88580-1906-11e9-919b-ffe5949a18d2'), + sampleObject: { + type: MAP_SAVED_OBJECT_TYPE, + id: '5dd88580-1906-11e9-919b-ffe5949a18d2', + }, + getPath: getFullPath, label: sampleDataLinkLabel, icon: APP_ICON, }, @@ -120,7 +128,11 @@ export class MapsPlugin implements Plugin { home.sampleData.addSavedObjectsToSampleDataset('logs', getWebLogsSavedObjects()); home.sampleData.addAppLinksToSampleDataset('logs', [ { - path: getFullPath('de71f4f0-1902-11e9-919b-ffe5949a18d2'), + sampleObject: { + type: MAP_SAVED_OBJECT_TYPE, + id: 'de71f4f0-1902-11e9-919b-ffe5949a18d2', + }, + getPath: getFullPath, label: sampleDataLinkLabel, icon: APP_ICON, }, diff --git a/x-pack/plugins/ml/server/lib/log.ts b/x-pack/plugins/ml/server/lib/log.ts index afa5e977d9056..3efd651e91d5b 100644 --- a/x-pack/plugins/ml/server/lib/log.ts +++ b/x-pack/plugins/ml/server/lib/log.ts @@ -25,7 +25,7 @@ export let mlLog: MlLog; export function initMlServerLog(logInitialization: LogInitialization) { mlLog = { fatal: (message: string) => logInitialization.log.fatal(message), - error: (message: string) => logInitialization.log.error(message), + error: (message: string | Error) => logInitialization.log.error(message), warn: (message: string) => logInitialization.log.warn(message), info: (message: string) => logInitialization.log.info(message), debug: (message: string) => logInitialization.log.debug(message), diff --git a/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts b/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts index 91c4327f953ff..8833f2eb617a6 100644 --- a/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts +++ b/x-pack/plugins/ml/server/lib/sample_data_sets/sample_data_sets.ts @@ -15,10 +15,16 @@ export function initSampleDataSets(mlLicense: MlLicense, plugins: PluginsSetup) defaultMessage: 'ML jobs', }); const { addAppLinksToSampleDataset } = plugins.home.sampleData; + const getCreateJobPath = (jobId: string, dataViewId: string) => + `/app/ml/modules/check_view_or_create?id=${jobId}&index=${dataViewId}`; addAppLinksToSampleDataset('ecommerce', [ { - path: '/app/ml/modules/check_view_or_create?id=sample_data_ecommerce&index=ff959d40-b880-11e8-a6d9-e546fe2bba5f', + sampleObject: { + type: 'index-pattern', + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + }, + getPath: (objectId) => getCreateJobPath('sample_data_ecommerce', objectId), label: sampleDataLinkLabel, icon: 'machineLearningApp', }, @@ -26,7 +32,11 @@ export function initSampleDataSets(mlLicense: MlLicense, plugins: PluginsSetup) addAppLinksToSampleDataset('logs', [ { - path: '/app/ml/modules/check_view_or_create?id=sample_data_weblogs&index=90943e30-9a47-11e8-b64d-95841ca0b247', + sampleObject: { + type: 'index-pattern', + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + }, + getPath: (objectId) => getCreateJobPath('sample_data_weblogs', objectId), label: sampleDataLinkLabel, icon: 'machineLearningApp', }, diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts index b404f517e4b6f..fb8480d621d55 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts @@ -49,7 +49,11 @@ export function modelsProvider( modelIds.map((id: string) => [id, null]) ); - const { body } = await client.asCurrentUser.ingest.getPipeline(); + const { body, statusCode } = await client.asCurrentUser.ingest.getPipeline(); + + if (statusCode !== 200) { + return modelIdsMap; + } for (const [pipelineName, pipelineDefinition] of Object.entries(body)) { const { processors } = pipelineDefinition as { processors: Array> }; diff --git a/x-pack/plugins/ml/server/routes/trained_models.ts b/x-pack/plugins/ml/server/routes/trained_models.ts index a20a97a3fcb42..1837f9e88edf3 100644 --- a/x-pack/plugins/ml/server/routes/trained_models.ts +++ b/x-pack/plugins/ml/server/routes/trained_models.ts @@ -15,6 +15,7 @@ import { import { modelsProvider } from '../models/data_frame_analytics'; import { TrainedModelConfigResponse } from '../../common/types/trained_models'; import { memoryOverviewServiceProvider } from '../models/memory_overview'; +import { mlLog } from '../lib/log'; export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) { /** @@ -77,8 +78,7 @@ export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) } } catch (e) { // the user might not have required permissions to fetch pipelines - // eslint-disable-next-line no-console - console.log(e); + mlLog.error(e); } return response.ok({ diff --git a/x-pack/plugins/monitoring/public/application/hooks/use_alerts_modal.ts b/x-pack/plugins/monitoring/public/application/hooks/use_alerts_modal.ts index 123dd39f7b54d..db692889e1140 100644 --- a/x-pack/plugins/monitoring/public/application/hooks/use_alerts_modal.ts +++ b/x-pack/plugins/monitoring/public/application/hooks/use_alerts_modal.ts @@ -5,8 +5,8 @@ * 2.0. */ import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; -import { showAlertsToast } from '../../alerts/lib/alerts_toast'; import { useRequestErrorHandler } from './use_request_error_handler'; +import { EnableAlertResponse, showAlertsToast } from '../../alerts/lib/alerts_toast'; export const useAlertsModal = () => { const { services } = useKibana(); @@ -29,7 +29,14 @@ export const useAlertsModal = () => { async function enableAlerts() { try { - const response = await services.http?.post('../api/monitoring/v1/alerts/enable', {}); + if (!services.http?.post) { + throw new Error('HTTP service is unavailable'); + } + + const response = await services.http.post( + '../api/monitoring/v1/alerts/enable', + {} + )!; window.localStorage.setItem('ALERTS_MODAL_DECISION_MADE', 'true'); showAlertsToast(response); } catch (err) { diff --git a/x-pack/plugins/monitoring/public/application/hooks/use_request_error_handler.tsx b/x-pack/plugins/monitoring/public/application/hooks/use_request_error_handler.tsx index 6c7c86a330135..b4c2a4e86d374 100644 --- a/x-pack/plugins/monitoring/public/application/hooks/use_request_error_handler.tsx +++ b/x-pack/plugins/monitoring/public/application/hooks/use_request_error_handler.tsx @@ -7,14 +7,14 @@ import React, { useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import { includes } from 'lodash'; -import { IHttpFetchError } from 'kibana/public'; +import { IHttpFetchError, ResponseErrorBody } from 'kibana/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, EuiSpacer, EuiText } from '@elastic/eui'; import { formatMsg } from '../../../../../../src/plugins/kibana_legacy/public'; import { toMountPoint, useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { MonitoringStartPluginDependencies } from '../../types'; -export function formatMonitoringError(err: IHttpFetchError) { +export function formatMonitoringError(err: IHttpFetchError) { if (err.response?.status && err.response?.status !== -1) { return ( @@ -37,7 +37,7 @@ export const useRequestErrorHandler = () => { const { services } = useKibana(); const history = useHistory(); return useCallback( - (err: IHttpFetchError) => { + (err: IHttpFetchError) => { if (err.response?.status === 403) { // redirect to error message view history.push('/access-denied'); diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx index 3fa7819c5e417..9f8260b4fa0d9 100644 --- a/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx @@ -59,7 +59,7 @@ export const ApmInstancePage: React.FC = ({ clusters }) => { const getPageData = useCallback(async () => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm/${instance}`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ apmSummary: { name: string } }>(url, { method: 'POST', body: JSON.stringify({ ccs, @@ -71,7 +71,7 @@ export const ApmInstancePage: React.FC = ({ clusters }) => { }); setData(response); - setInstanceName(response.apmSummary.name); + setInstanceName(response?.apmSummary.name || ''); }, [ccs, clusterUuid, instance, services.data?.query.timefilter.timefilter, services.http]); return ( diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx index 2543b054ee5bb..fa3420d439eca 100644 --- a/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx @@ -60,7 +60,7 @@ export const ApmInstancesPage: React.FC = ({ clusters }) => { const getPageData = useCallback(async () => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm/instances`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ stats: { total: number } }>(url, { method: 'POST', body: JSON.stringify({ ccs, @@ -72,7 +72,7 @@ export const ApmInstancesPage: React.FC = ({ clusters }) => { }); setData(response); - updateTotalItemCount(response.stats.total); + updateTotalItemCount(response?.stats.total); }, [ ccs, clusterUuid, diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx index 516c293c53546..39144505d9818 100644 --- a/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx @@ -50,7 +50,7 @@ export const ApmOverviewPage: React.FC = ({ clusters }) => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/beats/instance.tsx b/x-pack/plugins/monitoring/public/application/pages/beats/instance.tsx index 4c66bbba631fb..70dba8d5f0d3c 100644 --- a/x-pack/plugins/monitoring/public/application/pages/beats/instance.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/beats/instance.tsx @@ -59,7 +59,7 @@ export const BeatsInstancePage: React.FC = ({ clusters }) => { const getPageData = useCallback(async () => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/beats/beat/${instance}`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ summary: { name: string } }>(url, { method: 'POST', body: JSON.stringify({ ccs, @@ -71,7 +71,7 @@ export const BeatsInstancePage: React.FC = ({ clusters }) => { }); setData(response); - setBeatName(response.summary.name); + setBeatName(response?.summary.name || ''); }, [ccs, clusterUuid, instance, services.data?.query.timefilter.timefilter, services.http]); return ( diff --git a/x-pack/plugins/monitoring/public/application/pages/beats/instances.tsx b/x-pack/plugins/monitoring/public/application/pages/beats/instances.tsx index b33789f510f2e..a677d22cbd3a7 100644 --- a/x-pack/plugins/monitoring/public/application/pages/beats/instances.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/beats/instances.tsx @@ -49,7 +49,7 @@ export const BeatsInstancesPage: React.FC = ({ clusters }) => { const getPageData = useCallback(async () => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/beats/beats`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ stats: { total: number } }>(url, { method: 'POST', body: JSON.stringify({ ccs, @@ -61,7 +61,7 @@ export const BeatsInstancesPage: React.FC = ({ clusters }) => { }); setData(response); - updateTotalItemCount(response.stats.total); + updateTotalItemCount(response?.stats.total); }, [ ccs, clusterUuid, diff --git a/x-pack/plugins/monitoring/public/application/pages/beats/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/beats/overview.tsx index aec89c92055c4..fad66cd03e444 100644 --- a/x-pack/plugins/monitoring/public/application/pages/beats/overview.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/beats/overview.tsx @@ -50,7 +50,7 @@ export const BeatsOverviewPage: React.FC = ({ clusters }) => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/beats`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx index db8c40ba22943..5a3a48bdfe17f 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx @@ -69,7 +69,7 @@ export const ElasticsearchIndexPage: React.FC = ({ clusters }) = const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/indices/${index}`; if (services.http?.fetch && clusterUuid) { - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ shards: unknown[]; nodes: unknown[] }>(url, { method: 'POST', body: JSON.stringify({ timeRange: { diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ml_jobs_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ml_jobs_page.tsx index 46bb4cc20242f..0f002323c310f 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ml_jobs_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ml_jobs_page.tsx @@ -56,7 +56,7 @@ export const ElasticsearchMLJobsPage: React.FC = ({ clusters }) const getPageData = useCallback(async () => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/ml_jobs`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ rows: MLJobs; clusterStatus: unknown }>(url, { method: 'POST', body: JSON.stringify({ ccs, @@ -67,8 +67,8 @@ export const ElasticsearchMLJobsPage: React.FC = ({ clusters }) }), }); setData({ - clusterStatus: response.clusterStatus, - jobs: (response.rows as MLJobs).map((job) => { + clusterStatus: response?.clusterStatus, + jobs: response?.rows?.map((job) => { if ('ml' in job && job.ml?.job) { return { ...job.ml.job, diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx index f6402dd8cba63..e09a1a2343c7b 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx @@ -82,7 +82,7 @@ export const ElasticsearchNodePage: React.FC = ({ clusters }) => const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/nodes/${node}`; if (services.http?.fetch && clusterUuid) { - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ shards: unknown[]; nodes: unknown[] }>(url, { method: 'POST', body: JSON.stringify({ showSystemIndices, diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/nodes_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/nodes_page.tsx index 9933188b887d5..5d5fa4df458e1 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/nodes_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/nodes_page.tsx @@ -66,7 +66,7 @@ export const ElasticsearchNodesPage: React.FC = ({ clusters }) = const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/nodes`; if (services.http?.fetch && clusterUuid) { setIsLoading(true); - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ totalNodeCount: number }>(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/overview.tsx index d093ba6e6f0da..16fa6de24b6b7 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/overview.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/overview.tsx @@ -57,7 +57,7 @@ export const ElasticsearchOverviewPage: React.FC = ({ clusters } const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/kibana/instance.tsx b/x-pack/plugins/monitoring/public/application/pages/kibana/instance.tsx index 2d2fe99758ff7..262590b6806af 100644 --- a/x-pack/plugins/monitoring/public/application/pages/kibana/instance.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/kibana/instance.tsx @@ -138,7 +138,7 @@ export const KibanaInstancePage: React.FC = ({ clusters }) => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/kibana/${instance}`; if (services.http?.fetch && clusterUuid) { - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ kibanaSummary: { name: string } }>(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/kibana/instances.tsx b/x-pack/plugins/monitoring/public/application/pages/kibana/instances.tsx index a27c1418eabc1..f20099b286808 100644 --- a/x-pack/plugins/monitoring/public/application/pages/kibana/instances.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/kibana/instances.tsx @@ -54,7 +54,7 @@ export const KibanaInstancesPage: React.FC = ({ clusters }) => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/kibana/instances`; if (services.http?.fetch && clusterUuid) { - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch<{ kibanas: { length: number } }>(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx index 5ac5fe356db9f..35f4c0ce2ac44 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx @@ -62,7 +62,7 @@ export const LogStashNodePipelinesPage: React.FC = ({ clusters } const getPageData = useCallback(async () => { const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/logstash/node/${match.params.uuid}/pipelines`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx index 1412f7b9c55fb..60c9463d39bda 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx @@ -41,7 +41,7 @@ export const LogStashOverviewPage: React.FC = ({ clusters }) => const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/logstash`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx index cf9b5628222f4..7d057863ba3fc 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx @@ -65,7 +65,7 @@ export const LogStashPipelinePage: React.FC = ({ clusters }) => ? `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}/${pipelineHash}` : `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx index 7c876c1e950cb..ace8c23a480ba 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx @@ -49,7 +49,7 @@ export const LogStashPipelinesPage: React.FC = ({ clusters }) => const bounds = services.data?.query.timefilter.timefilter.getBounds(); const url = `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipelines`; - const response = await services.http?.fetch(url, { + const response = await services.http?.fetch(url, { method: 'POST', body: JSON.stringify({ ccs, diff --git a/x-pack/plugins/monitoring/public/application/pages/page_template.tsx b/x-pack/plugins/monitoring/public/application/pages/page_template.tsx index a508714612c28..c951d325c13f4 100644 --- a/x-pack/plugins/monitoring/public/application/pages/page_template.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/page_template.tsx @@ -8,7 +8,7 @@ import { EuiTab, EuiTabs } from '@elastic/eui'; import React, { useContext, useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { IHttpFetchError } from 'kibana/public'; +import { IHttpFetchError, ResponseErrorBody } from 'kibana/public'; import { useTitle } from '../hooks/use_title'; import { MonitoringToolbar } from '../../components/shared/toolbar'; import { MonitoringTimeContainer } from '../hooks/use_monitoring_time'; @@ -66,7 +66,7 @@ export const PageTemplate: React.FC = ({ setIsRequestPending(true); getPageData?.() .then(getPageDataResponseHandler) - .catch((err: IHttpFetchError) => { + .catch((err: IHttpFetchError) => { handleRequestError(err); setHasError(true); }) diff --git a/x-pack/plugins/monitoring/public/lib/setup_mode.tsx b/x-pack/plugins/monitoring/public/lib/setup_mode.tsx index e582f4aa40812..2fae120012d73 100644 --- a/x-pack/plugins/monitoring/public/lib/setup_mode.tsx +++ b/x-pack/plugins/monitoring/public/lib/setup_mode.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { render } from 'react-dom'; import { get, includes } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { HttpStart, IHttpFetchError } from 'kibana/public'; +import { HttpStart, IHttpFetchError, ResponseErrorBody } from 'kibana/public'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { Legacy } from '../legacy_shims'; import { SetupModeEnterButton } from '../components/setup_mode/enter_button'; @@ -23,7 +23,7 @@ function isOnPage(hash: string) { let globalState: GlobalState; let httpService: HttpStart; -let errorHandler: (error: IHttpFetchError) => void; +let errorHandler: (error: IHttpFetchError) => void; interface ISetupModeState { enabled: boolean; @@ -162,7 +162,7 @@ export const setSetupModeMenuItem = () => { export const initSetupModeState = async ( state: GlobalState, http: HttpStart, - handleErrors: (error: IHttpFetchError) => void, + handleErrors: (error: IHttpFetchError) => void, callback?: () => void ) => { globalState = state; diff --git a/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts b/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts index e8ba66c332778..56e5610e1b117 100644 --- a/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts +++ b/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts @@ -28,7 +28,7 @@ export const useFetchAlertDetail = (alertId: string): [boolean, TopAlert | null] const fetchData = async () => { try { setLoading(true); - const response = await http.get('/internal/rac/alerts', { + const response = await http.get>('/internal/rac/alerts', { query: { id: alertId, }, diff --git a/x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx b/x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx index 5ad4804f88d5e..3adfb0a1d9c89 100644 --- a/x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/default_cell_actions.tsx @@ -7,58 +7,16 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { ObservabilityPublicPluginsStart } from '../..'; import { getMappedNonEcsValue } from './render_cell_value'; import FilterForValueButton from './filter_for_value'; -import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { TimelineNonEcsData } from '../../../../timelines/common/search_strategy'; import { TGridCellAction } from '../../../../timelines/common/types/timeline'; -import { getPageRowIndex, TimelinesUIStart } from '../../../../timelines/public'; +import { getPageRowIndex } from '../../../../timelines/public'; export const FILTER_FOR_VALUE = i18n.translate('xpack.observability.hoverActions.filterForValue', { defaultMessage: 'Filter for value', }); -/** a hook to eliminate the verbose boilerplate required to use common services */ -const useKibanaServices = () => { - const { timelines } = useKibana<{ timelines: TimelinesUIStart }>().services; - const { - services: { - data: { - query: { filterManager }, - }, - }, - } = useKibana(); - - return { timelines, filterManager }; -}; - -/** actions common to all cells (e.g. copy to clipboard) */ -const commonCellActions: TGridCellAction[] = [ - ({ data, pageSize }: { data: TimelineNonEcsData[][]; pageSize: number }) => - ({ rowIndex, columnId, Component }) => { - const { timelines } = useKibanaServices(); - - const value = getMappedNonEcsValue({ - data: data[getPageRowIndex(rowIndex, pageSize)], - fieldName: columnId, - }); - - return ( - <> - {timelines.getHoverActions().getCopyButton({ - Component, - field: columnId, - isHoverAction: false, - ownFocus: false, - showTooltip: false, - value, - })} - - ); - }, -]; - /** actions for adding filters to the search bar */ const buildFilterCellActions = (addToQuery: (value: string) => void): TGridCellAction[] => [ ({ data, pageSize }: { data: TimelineNonEcsData[][]; pageSize: number }) => @@ -80,7 +38,5 @@ const buildFilterCellActions = (addToQuery: (value: string) => void): TGridCellA ]; /** returns the default actions shown in `EuiDataGrid` cells */ -export const getDefaultCellActions = ({ addToQuery }: { addToQuery: (value: string) => void }) => [ - ...buildFilterCellActions(addToQuery), - ...commonCellActions, -]; +export const getDefaultCellActions = ({ addToQuery }: { addToQuery: (value: string) => void }) => + buildFilterCellActions(addToQuery); diff --git a/x-pack/plugins/observability/public/pages/alerts/filter_for_value.tsx b/x-pack/plugins/observability/public/pages/alerts/filter_for_value.tsx index 77cac9d482a37..f75ae488c9b28 100644 --- a/x-pack/plugins/observability/public/pages/alerts/filter_for_value.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/filter_for_value.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; export const filterForValueButtonLabel = i18n.translate( 'xpack.observability.hoverActions.filterForValueButtonLabel', { - defaultMessage: 'Filter for value', + defaultMessage: 'Filter in', } ); diff --git a/x-pack/plugins/osquery/common/schemas/common/schemas.ts b/x-pack/plugins/osquery/common/schemas/common/schemas.ts index 2ffb6c5feae54..4547db731ce1b 100644 --- a/x-pack/plugins/osquery/common/schemas/common/schemas.ts +++ b/x-pack/plugins/osquery/common/schemas/common/schemas.ts @@ -55,8 +55,9 @@ export type SavedQueryIdOrUndefined = t.TypeOf; export const ecsMapping = t.record( t.string, - t.type({ + t.partial({ field: t.string, + value: t.string, }) ); export type ECSMapping = t.TypeOf; diff --git a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx index 9da9ac72f273a..e04f783608420 100644 --- a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx +++ b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx @@ -13,7 +13,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { AgentIdToName } from '../agents/agent_id_to_name'; import { useActionResults } from './use_action_results'; -import { useAllResults } from '../results/use_all_results'; import { Direction } from '../../common/search_strategy'; import { useActionResultsPrivileges } from './use_action_privileges'; @@ -70,38 +69,8 @@ const ActionResultsSummaryComponent: React.FC = ({ }); } - const { data: logsResults } = useAllResults({ - actionId, - activePage: pageIndex, - limit: pageSize, - sort: [ - { - field: '@timestamp', - direction: Direction.asc, - }, - ], - isLive, - skip: !hasActionResultsPrivileges, - }); - const renderAgentIdColumn = useCallback((agentId) => , []); - - const renderRowsColumn = useCallback( - (_, item) => { - if (!logsResults) return '-'; - const agentId = item.fields.agent_id[0]; - - return ( - // @ts-expect-error update types - logsResults?.rawResponse?.aggregations?.count_by_agent_id?.buckets?.find( - // @ts-expect-error update types - (bucket) => bucket.key === agentId - )?.doc_count ?? '-' - ); - }, - [logsResults] - ); - + const renderRowsColumn = useCallback((rowsCount) => rowsCount ?? '-', []); const renderStatusColumn = useCallback( (_, item) => { if (!item.fields.completed_at) { @@ -145,7 +114,7 @@ const ActionResultsSummaryComponent: React.FC = ({ render: renderAgentIdColumn, }, { - field: 'fields.rows[0]', + field: '_source.action_response.osquery.count', name: i18n.translate( 'xpack.osquery.liveQueryActionResults.table.resultRowsNumberColumnTitle', { @@ -177,18 +146,9 @@ const ActionResultsSummaryComponent: React.FC = ({ setIsLive(() => { if (!agentIds?.length || expired) return false; - const uniqueAgentsRepliedCount = - // @ts-expect-error update types - logsResults?.rawResponse.aggregations?.unique_agents.value ?? 0; - - return !!(uniqueAgentsRepliedCount !== agentIds?.length - aggregations.failed); + return !!(aggregations.totalResponded !== agentIds?.length); }); - }, [ - agentIds?.length, - aggregations.failed, - expired, - logsResults?.rawResponse.aggregations?.unique_agents, - ]); + }, [agentIds?.length, aggregations.totalResponded, expired]); return edges.length ? ( diff --git a/x-pack/plugins/osquery/public/action_results/use_action_results.ts b/x-pack/plugins/osquery/public/action_results/use_action_results.ts index 29bff0819956a..e4b6ef14eb1e9 100644 --- a/x-pack/plugins/osquery/public/action_results/use_action_results.ts +++ b/x-pack/plugins/osquery/public/action_results/use_action_results.ts @@ -84,6 +84,9 @@ export const useActionResults = ({ const totalResponded = // @ts-expect-error update types responseData.rawResponse?.aggregations?.aggs.responses_by_action_id?.doc_count ?? 0; + const totalRowCount = + // @ts-expect-error update types + responseData.rawResponse?.aggregations?.aggs.responses_by_action_id?.rows_count?.value ?? 0; const aggsBuckets = // @ts-expect-error update types responseData.rawResponse?.aggregations?.aggs.responses_by_action_id?.responses.buckets; @@ -100,6 +103,7 @@ export const useActionResults = ({ ...responseData, edges: reverse(uniqBy('fields.agent_id[0]', flatten([responseData.edges, previousEdges]))), aggregations: { + totalRowCount, totalResponded, // @ts-expect-error update types successful: aggsBuckets?.find((bucket) => bucket.key === 'success')?.doc_count ?? 0, diff --git a/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts b/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts index 15f1e48f1536e..678ea76ea5e84 100644 --- a/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts +++ b/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts @@ -21,7 +21,7 @@ export const useAgentPolicy = ({ policyId, skip, silent }: UseAgentPolicy) => { const { http } = useKibana().services; const setErrorToast = useErrorToast(); - return useQuery( + return useQuery( ['agentPolicy', { policyId }], () => http.get(`/internal/osquery/fleet_wrapper/agent_policies/${policyId}`), { diff --git a/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts b/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts index cf777092da5cf..759e9f22c71b8 100644 --- a/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts +++ b/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts @@ -18,10 +18,12 @@ export const useOsqueryPolicies = () => { const { isLoading: osqueryPoliciesLoading, data: osqueryPolicies = [] } = useQuery( ['osqueryPolicies'], - () => http.get('/internal/osquery/fleet_wrapper/package_policies'), + () => + http.get<{ items: Array<{ policy_id: string }> }>( + '/internal/osquery/fleet_wrapper/package_policies' + ), { - select: (response) => - uniq(response.items.map((p: { policy_id: string }) => p.policy_id)), + select: (response) => uniq(response.items.map((p) => p.policy_id)), onSuccess: () => setErrorToast(), onError: (error: Error) => setErrorToast(error, { diff --git a/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx b/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx index 1994ea348e30c..92f32d6535b4c 100644 --- a/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx +++ b/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx @@ -15,14 +15,21 @@ export const useOsqueryIntegrationStatus = () => { const { http } = useKibana().services; const setErrorToast = useErrorToast(); - return useQuery('integration', () => http.get('/internal/osquery/status'), { - onError: (error: Error) => - setErrorToast(error, { - title: i18n.translate('xpack.osquery.osquery_integration.fetchError', { - defaultMessage: 'Error while fetching osquery integration', + return useQuery( + 'integration', + () => + http.get<{ name: string; version: string; title: string; install_status: string }>( + '/internal/osquery/status' + ), + { + onError: (error: Error) => + setErrorToast(error, { + title: i18n.translate('xpack.osquery.osquery_integration.fetchError', { + defaultMessage: 'Error while fetching osquery integration', + }), }), - }), - refetchOnReconnect: false, - refetchOnWindowFocus: false, - }); + refetchOnReconnect: false, + refetchOnWindowFocus: false, + } + ); }; diff --git a/x-pack/plugins/osquery/public/common/schemas/ecs/v1.12.1.json b/x-pack/plugins/osquery/public/common/schemas/ecs/v1.12.1.json index 2b4a3c8c92f2f..a613c8b576524 100644 --- a/x-pack/plugins/osquery/public/common/schemas/ecs/v1.12.1.json +++ b/x-pack/plugins/osquery/public/common/schemas/ecs/v1.12.1.json @@ -1 +1 @@ -[{"field":"labels","type":"object","description":"Custom key/value pairs."},{"field":"message","type":"match_only_text","description":"Log message optimized for viewing in a log viewer."},{"field":"tags","type":"keyword","description":"List of keywords used to tag each event."},{"field":"agent.build.original","type":"keyword","description":"Extended build information for the agent."},{"field":"client.address","type":"keyword","description":"Client network address."},{"field":"client.as.number","type":"long","description":"Unique number allocated to the autonomous system."},{"field":"client.as.organization.name","type":"keyword","description":"Organization name."},{"field":"client.as.organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"client.bytes","type":"long","description":"Bytes sent from the client to the server."},{"field":"client.domain","type":"keyword","description":"Client domain."},{"field":"client.geo.city_name","type":"keyword","description":"City name."},{"field":"client.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"client.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"client.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"client.geo.country_name","type":"keyword","description":"Country name."},{"field":"client.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"client.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"client.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"client.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"client.geo.region_name","type":"keyword","description":"Region name."},{"field":"client.geo.timezone","type":"keyword","description":"Time zone."},{"field":"client.ip","type":"ip","description":"IP address of the client."},{"field":"client.mac","type":"keyword","description":"MAC address of the client."},{"field":"client.nat.ip","type":"ip","description":"Client NAT ip address"},{"field":"client.nat.port","type":"long","description":"Client NAT port"},{"field":"client.packets","type":"long","description":"Packets sent from the client to the server."},{"field":"client.port","type":"long","description":"Port of the client."},{"field":"client.registered_domain","type":"keyword","description":"The highest registered client domain, stripped of the subdomain."},{"field":"client.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"client.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"client.user.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"client.user.email","type":"keyword","description":"User email address."},{"field":"client.user.full_name","type":"keyword","description":"User's full name, if available."},{"field":"client.user.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"client.user.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"client.user.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"client.user.group.name","type":"keyword","description":"Name of the group."},{"field":"client.user.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"client.user.id","type":"keyword","description":"Unique identifier of the user."},{"field":"client.user.name","type":"keyword","description":"Short name or login of the user."},{"field":"client.user.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"client.user.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"cloud.account.id","type":"keyword","description":"The cloud account or organization id."},{"field":"cloud.account.name","type":"keyword","description":"The cloud account name."},{"field":"cloud.availability_zone","type":"keyword","description":"Availability zone in which this host, resource, or service is located."},{"field":"cloud.instance.id","type":"keyword","description":"Instance ID of the host machine."},{"field":"cloud.instance.name","type":"keyword","description":"Instance name of the host machine."},{"field":"cloud.machine.type","type":"keyword","description":"Machine type of the host machine."},{"field":"cloud.project.id","type":"keyword","description":"The cloud project id."},{"field":"cloud.project.name","type":"keyword","description":"The cloud project name."},{"field":"cloud.provider","type":"keyword","description":"Name of the cloud provider."},{"field":"cloud.region","type":"keyword","description":"Region in which this host, resource, or service is located."},{"field":"cloud.service.name","type":"keyword","description":"The cloud service name."},{"field":"container.id","type":"keyword","description":"Unique container id."},{"field":"container.image.name","type":"keyword","description":"Name of the image the container was built on."},{"field":"container.image.tag","type":"keyword","description":"Container image tags."},{"field":"container.labels","type":"object","description":"Image labels."},{"field":"container.name","type":"keyword","description":"Container name."},{"field":"container.runtime","type":"keyword","description":"Runtime managing this container."},{"field":"data_stream.dataset","type":"constant_keyword","description":"The field can contain anything that makes sense to signify the source of the data."},{"field":"data_stream.namespace","type":"constant_keyword","description":"A user defined namespace. Namespaces are useful to allow grouping of data."},{"field":"data_stream.type","type":"constant_keyword","description":"An overarching type for the data stream."},{"field":"destination.address","type":"keyword","description":"Destination network address."},{"field":"destination.as.number","type":"long","description":"Unique number allocated to the autonomous system."},{"field":"destination.as.organization.name","type":"keyword","description":"Organization name."},{"field":"destination.as.organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"destination.bytes","type":"long","description":"Bytes sent from the destination to the source."},{"field":"destination.domain","type":"keyword","description":"Destination domain."},{"field":"destination.geo.city_name","type":"keyword","description":"City name."},{"field":"destination.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"destination.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"destination.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"destination.geo.country_name","type":"keyword","description":"Country name."},{"field":"destination.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"destination.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"destination.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"destination.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"destination.geo.region_name","type":"keyword","description":"Region name."},{"field":"destination.geo.timezone","type":"keyword","description":"Time zone."},{"field":"destination.ip","type":"ip","description":"IP address of the destination."},{"field":"destination.mac","type":"keyword","description":"MAC address of the destination."},{"field":"destination.nat.ip","type":"ip","description":"Destination NAT ip"},{"field":"destination.nat.port","type":"long","description":"Destination NAT Port"},{"field":"destination.packets","type":"long","description":"Packets sent from the destination to the source."},{"field":"destination.port","type":"long","description":"Port of the destination."},{"field":"destination.registered_domain","type":"keyword","description":"The highest registered destination domain, stripped of the subdomain."},{"field":"destination.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"destination.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"destination.user.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"destination.user.email","type":"keyword","description":"User email address."},{"field":"destination.user.full_name","type":"keyword","description":"User's full name, if available."},{"field":"destination.user.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"destination.user.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"destination.user.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"destination.user.group.name","type":"keyword","description":"Name of the group."},{"field":"destination.user.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"destination.user.id","type":"keyword","description":"Unique identifier of the user."},{"field":"destination.user.name","type":"keyword","description":"Short name or login of the user."},{"field":"destination.user.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"destination.user.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"dll.code_signature.digest_algorithm","type":"keyword","description":"Hashing algorithm used to sign the process."},{"field":"dll.code_signature.exists","type":"boolean","description":"Boolean to capture if a signature is present."},{"field":"dll.code_signature.signing_id","type":"keyword","description":"The identifier used to sign the process."},{"field":"dll.code_signature.status","type":"keyword","description":"Additional information about the certificate status."},{"field":"dll.code_signature.subject_name","type":"keyword","description":"Subject name of the code signer"},{"field":"dll.code_signature.team_id","type":"keyword","description":"The team identifier used to sign the process."},{"field":"dll.code_signature.timestamp","type":"date","description":"When the signature was generated and signed."},{"field":"dll.code_signature.trusted","type":"boolean","description":"Stores the trust status of the certificate chain."},{"field":"dll.code_signature.valid","type":"boolean","description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"dll.hash.md5","type":"keyword","description":"MD5 hash."},{"field":"dll.hash.sha1","type":"keyword","description":"SHA1 hash."},{"field":"dll.hash.sha256","type":"keyword","description":"SHA256 hash."},{"field":"dll.hash.sha512","type":"keyword","description":"SHA512 hash."},{"field":"dll.hash.ssdeep","type":"keyword","description":"SSDEEP hash."},{"field":"dll.name","type":"keyword","description":"Name of the library."},{"field":"dll.path","type":"keyword","description":"Full file path of the library."},{"field":"dll.pe.architecture","type":"keyword","description":"CPU architecture target for the file."},{"field":"dll.pe.company","type":"keyword","description":"Internal company name of the file, provided at compile-time."},{"field":"dll.pe.description","type":"keyword","description":"Internal description of the file, provided at compile-time."},{"field":"dll.pe.file_version","type":"keyword","description":"Process name."},{"field":"dll.pe.imphash","type":"keyword","description":"A hash of the imports in a PE file."},{"field":"dll.pe.original_file_name","type":"keyword","description":"Internal name of the file, provided at compile-time."},{"field":"dll.pe.product","type":"keyword","description":"Internal product name of the file, provided at compile-time."},{"field":"dns.answers","type":"object","description":"Array of DNS answers."},{"field":"dns.answers.class","type":"keyword","description":"The class of DNS data contained in this resource record."},{"field":"dns.answers.data","type":"keyword","description":"The data describing the resource."},{"field":"dns.answers.name","type":"keyword","description":"The domain name to which this resource record pertains."},{"field":"dns.answers.ttl","type":"long","description":"The time interval in seconds that this resource record may be cached before it should be discarded."},{"field":"dns.answers.type","type":"keyword","description":"The type of data contained in this resource record."},{"field":"dns.header_flags","type":"keyword","description":"Array of DNS header flags."},{"field":"dns.id","type":"keyword","description":"The DNS packet identifier assigned by the program that generated the query. The identifier is copied to the response."},{"field":"dns.op_code","type":"keyword","description":"The DNS operation code that specifies the kind of query in the message."},{"field":"dns.question.class","type":"keyword","description":"The class of records being queried."},{"field":"dns.question.name","type":"keyword","description":"The name being queried."},{"field":"dns.question.registered_domain","type":"keyword","description":"The highest registered domain, stripped of the subdomain."},{"field":"dns.question.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"dns.question.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"dns.question.type","type":"keyword","description":"The type of record being queried."},{"field":"dns.resolved_ip","type":"ip","description":"Array containing all IPs seen in answers.data"},{"field":"dns.response_code","type":"keyword","description":"The DNS response code."},{"field":"dns.type","type":"keyword","description":"The type of DNS event captured, query or answer."},{"field":"error.code","type":"keyword","description":"Error code describing the error."},{"field":"error.id","type":"keyword","description":"Unique identifier for the error."},{"field":"error.message","type":"match_only_text","description":"Error message."},{"field":"error.stack_trace","type":"wildcard","description":"The stack trace of this error in plain text."},{"field":"error.stack_trace.text","type":"match_only_text","description":"The stack trace of this error in plain text."},{"field":"error.type","type":"keyword","description":"The type of the error, for example the class name of the exception."},{"field":"event.action","type":"keyword","description":"The action captured by the event."},{"field":"event.category","type":"keyword","description":"Event category. The second categorization field in the hierarchy."},{"field":"event.code","type":"keyword","description":"Identification code for this event."},{"field":"event.created","type":"date","description":"Time when the event was first read by an agent or by your pipeline."},{"field":"event.dataset","type":"keyword","description":"Name of the dataset."},{"field":"event.duration","type":"long","description":"Duration of the event in nanoseconds."},{"field":"event.end","type":"date","description":"event.end contains the date when the event ended or when the activity was last observed."},{"field":"event.hash","type":"keyword","description":"Hash (perhaps logstash fingerprint) of raw field to be able to demonstrate log integrity."},{"field":"event.id","type":"keyword","description":"Unique ID to describe the event."},{"field":"event.kind","type":"keyword","description":"The kind of the event. The highest categorization field in the hierarchy."},{"field":"event.original","type":"keyword","description":"Raw text message of entire event."},{"field":"event.outcome","type":"keyword","description":"The outcome of the event. The lowest level categorization field in the hierarchy."},{"field":"event.provider","type":"keyword","description":"Source of the event."},{"field":"event.reason","type":"keyword","description":"Reason why this event happened, according to the source"},{"field":"event.reference","type":"keyword","description":"Event reference URL"},{"field":"event.risk_score","type":"float","description":"Risk score or priority of the event (e.g. security solutions). Use your system's original value here."},{"field":"event.risk_score_norm","type":"float","description":"Normalized risk score or priority of the event (0-100)."},{"field":"event.sequence","type":"long","description":"Sequence number of the event."},{"field":"event.severity","type":"long","description":"Numeric severity of the event."},{"field":"event.start","type":"date","description":"event.start contains the date when the event started or when the activity was first observed."},{"field":"event.timezone","type":"keyword","description":"Event time zone."},{"field":"event.type","type":"keyword","description":"Event type. The third categorization field in the hierarchy."},{"field":"event.url","type":"keyword","description":"Event investigation URL"},{"field":"file.accessed","type":"date","description":"Last time the file was accessed."},{"field":"file.attributes","type":"keyword","description":"Array of file attributes."},{"field":"file.code_signature.digest_algorithm","type":"keyword","description":"Hashing algorithm used to sign the process."},{"field":"file.code_signature.exists","type":"boolean","description":"Boolean to capture if a signature is present."},{"field":"file.code_signature.signing_id","type":"keyword","description":"The identifier used to sign the process."},{"field":"file.code_signature.status","type":"keyword","description":"Additional information about the certificate status."},{"field":"file.code_signature.subject_name","type":"keyword","description":"Subject name of the code signer"},{"field":"file.code_signature.team_id","type":"keyword","description":"The team identifier used to sign the process."},{"field":"file.code_signature.timestamp","type":"date","description":"When the signature was generated and signed."},{"field":"file.code_signature.trusted","type":"boolean","description":"Stores the trust status of the certificate chain."},{"field":"file.code_signature.valid","type":"boolean","description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"file.created","type":"date","description":"File creation time."},{"field":"file.ctime","type":"date","description":"Last time the file attributes or metadata changed."},{"field":"file.device","type":"keyword","description":"Device that is the source of the file."},{"field":"file.directory","type":"keyword","description":"Directory where the file is located."},{"field":"file.drive_letter","type":"keyword","description":"Drive letter where the file is located."},{"field":"file.elf.architecture","type":"keyword","description":"Machine architecture of the ELF file."},{"field":"file.elf.byte_order","type":"keyword","description":"Byte sequence of ELF file."},{"field":"file.elf.cpu_type","type":"keyword","description":"CPU type of the ELF file."},{"field":"file.elf.creation_date","type":"date","description":"Build or compile date."},{"field":"file.elf.exports","type":"flattened","description":"List of exported element names and types."},{"field":"file.elf.header.abi_version","type":"keyword","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"file.elf.header.class","type":"keyword","description":"Header class of the ELF file."},{"field":"file.elf.header.data","type":"keyword","description":"Data table of the ELF header."},{"field":"file.elf.header.entrypoint","type":"long","description":"Header entrypoint of the ELF file."},{"field":"file.elf.header.object_version","type":"keyword","description":"0x1\" for original ELF files."},{"field":"file.elf.header.os_abi","type":"keyword","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"file.elf.header.type","type":"keyword","description":"Header type of the ELF file."},{"field":"file.elf.header.version","type":"keyword","description":"Version of the ELF header."},{"field":"file.elf.imports","type":"flattened","description":"List of imported element names and types."},{"field":"file.elf.sections","type":"nested","description":"Section information of the ELF file."},{"field":"file.elf.sections.chi2","type":"long","description":"Chi-square probability distribution of the section."},{"field":"file.elf.sections.entropy","type":"long","description":"Shannon entropy calculation from the section."},{"field":"file.elf.sections.flags","type":"keyword","description":"ELF Section List flags."},{"field":"file.elf.sections.name","type":"keyword","description":"ELF Section List name."},{"field":"file.elf.sections.physical_offset","type":"keyword","description":"ELF Section List offset."},{"field":"file.elf.sections.physical_size","type":"long","description":"ELF Section List physical size."},{"field":"file.elf.sections.type","type":"keyword","description":"ELF Section List type."},{"field":"file.elf.sections.virtual_address","type":"long","description":"ELF Section List virtual address."},{"field":"file.elf.sections.virtual_size","type":"long","description":"ELF Section List virtual size."},{"field":"file.elf.segments","type":"nested","description":"ELF object segment list."},{"field":"file.elf.segments.sections","type":"keyword","description":"ELF object segment sections."},{"field":"file.elf.segments.type","type":"keyword","description":"ELF object segment type."},{"field":"file.elf.shared_libraries","type":"keyword","description":"List of shared libraries used by this ELF object."},{"field":"file.elf.telfhash","type":"keyword","description":"telfhash hash for ELF file."},{"field":"file.extension","type":"keyword","description":"File extension, excluding the leading dot."},{"field":"file.fork_name","type":"keyword","description":"A fork is additional data associated with a filesystem object."},{"field":"file.gid","type":"keyword","description":"Primary group ID (GID) of the file."},{"field":"file.group","type":"keyword","description":"Primary group name of the file."},{"field":"file.hash.md5","type":"keyword","description":"MD5 hash."},{"field":"file.hash.sha1","type":"keyword","description":"SHA1 hash."},{"field":"file.hash.sha256","type":"keyword","description":"SHA256 hash."},{"field":"file.hash.sha512","type":"keyword","description":"SHA512 hash."},{"field":"file.hash.ssdeep","type":"keyword","description":"SSDEEP hash."},{"field":"file.inode","type":"keyword","description":"Inode representing the file in the filesystem."},{"field":"file.mime_type","type":"keyword","description":"Media type of file, document, or arrangement of bytes."},{"field":"file.mode","type":"keyword","description":"Mode of the file in octal representation."},{"field":"file.mtime","type":"date","description":"Last time the file content was modified."},{"field":"file.name","type":"keyword","description":"Name of the file including the extension, without the directory."},{"field":"file.owner","type":"keyword","description":"File owner's username."},{"field":"file.path","type":"keyword","description":"Full path to the file, including the file name."},{"field":"file.path.text","type":"match_only_text","description":"Full path to the file, including the file name."},{"field":"file.pe.architecture","type":"keyword","description":"CPU architecture target for the file."},{"field":"file.pe.company","type":"keyword","description":"Internal company name of the file, provided at compile-time."},{"field":"file.pe.description","type":"keyword","description":"Internal description of the file, provided at compile-time."},{"field":"file.pe.file_version","type":"keyword","description":"Process name."},{"field":"file.pe.imphash","type":"keyword","description":"A hash of the imports in a PE file."},{"field":"file.pe.original_file_name","type":"keyword","description":"Internal name of the file, provided at compile-time."},{"field":"file.pe.product","type":"keyword","description":"Internal product name of the file, provided at compile-time."},{"field":"file.size","type":"long","description":"File size in bytes."},{"field":"file.target_path","type":"keyword","description":"Target path for symlinks."},{"field":"file.target_path.text","type":"match_only_text","description":"Target path for symlinks."},{"field":"file.type","type":"keyword","description":"File type (file, dir, or symlink)."},{"field":"file.uid","type":"keyword","description":"The user ID (UID) or security identifier (SID) of the file owner."},{"field":"file.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"file.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"file.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"file.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"file.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"file.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"file.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"file.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"file.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"file.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"file.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"file.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"file.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"file.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"file.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"file.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"file.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"file.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"file.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"file.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"file.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"file.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"file.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"file.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"group.name","type":"keyword","description":"Name of the group."},{"field":"host.cpu.usage","type":"scaled_float","description":"Percent CPU used, between 0 and 1."},{"field":"host.disk.read.bytes","type":"long","description":"The number of bytes read by all disks."},{"field":"host.disk.write.bytes","type":"long","description":"The number of bytes written on all disks."},{"field":"host.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"host.geo.city_name","type":"keyword","description":"City name."},{"field":"host.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"host.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"host.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"host.geo.country_name","type":"keyword","description":"Country name."},{"field":"host.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"host.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"host.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"host.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"host.geo.region_name","type":"keyword","description":"Region name."},{"field":"host.geo.timezone","type":"keyword","description":"Time zone."},{"field":"host.name","type":"keyword","description":"Name of the host."},{"field":"host.network.egress.bytes","type":"long","description":"The number of bytes sent on all network interfaces."},{"field":"host.network.egress.packets","type":"long","description":"The number of packets sent on all network interfaces."},{"field":"host.network.ingress.bytes","type":"long","description":"The number of bytes received on all network interfaces."},{"field":"host.network.ingress.packets","type":"long","description":"The number of packets received on all network interfaces."},{"field":"host.os.full","type":"keyword","description":"Operating system name, including the version or code name."},{"field":"host.os.full.text","type":"match_only_text","description":"Operating system name, including the version or code name."},{"field":"host.os.name.text","type":"match_only_text","description":"Operating system name, without the version."},{"field":"host.os.platform","type":"keyword","description":"Operating system platform (such centos, ubuntu, windows)."},{"field":"host.type","type":"keyword","description":"Type of host."},{"field":"host.uptime","type":"long","description":"Seconds the host has been up."},{"field":"host.user.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"host.user.email","type":"keyword","description":"User email address."},{"field":"host.user.full_name","type":"keyword","description":"User's full name, if available."},{"field":"host.user.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"host.user.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"host.user.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"host.user.group.name","type":"keyword","description":"Name of the group."},{"field":"host.user.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"host.user.id","type":"keyword","description":"Unique identifier of the user."},{"field":"host.user.name","type":"keyword","description":"Short name or login of the user."},{"field":"host.user.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"host.user.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"http.request.body.bytes","type":"long","description":"Size in bytes of the request body."},{"field":"http.request.body.content","type":"wildcard","description":"The full HTTP request body."},{"field":"http.request.body.content.text","type":"match_only_text","description":"The full HTTP request body."},{"field":"http.request.bytes","type":"long","description":"Total size in bytes of the request (body and headers)."},{"field":"http.request.id","type":"keyword","description":"HTTP request ID."},{"field":"http.request.method","type":"keyword","description":"HTTP request method."},{"field":"http.request.mime_type","type":"keyword","description":"Mime type of the body of the request."},{"field":"http.request.referrer","type":"keyword","description":"Referrer for this HTTP request."},{"field":"http.response.body.bytes","type":"long","description":"Size in bytes of the response body."},{"field":"http.response.body.content","type":"wildcard","description":"The full HTTP response body."},{"field":"http.response.body.content.text","type":"match_only_text","description":"The full HTTP response body."},{"field":"http.response.bytes","type":"long","description":"Total size in bytes of the response (body and headers)."},{"field":"http.response.mime_type","type":"keyword","description":"Mime type of the body of the response."},{"field":"http.response.status_code","type":"long","description":"HTTP response status code."},{"field":"http.version","type":"keyword","description":"HTTP version."},{"field":"log.file.path","type":"keyword","description":"Full path to the log file this event came from."},{"field":"log.level","type":"keyword","description":"Log level of the log event."},{"field":"log.logger","type":"keyword","description":"Name of the logger."},{"field":"log.origin.file.line","type":"integer","description":"The line number of the file which originated the log event."},{"field":"log.origin.file.name","type":"keyword","description":"The code file which originated the log event."},{"field":"log.origin.function","type":"keyword","description":"The function which originated the log event."},{"field":"log.original","type":"keyword","description":"Deprecated original log message with light interpretation only (encoding, newlines)."},{"field":"log.syslog","type":"object","description":"Syslog metadata"},{"field":"log.syslog.facility.code","type":"long","description":"Syslog numeric facility of the event."},{"field":"log.syslog.facility.name","type":"keyword","description":"Syslog text-based facility of the event."},{"field":"log.syslog.priority","type":"long","description":"Syslog priority of the event."},{"field":"log.syslog.severity.code","type":"long","description":"Syslog numeric severity of the event."},{"field":"log.syslog.severity.name","type":"keyword","description":"Syslog text-based severity of the event."},{"field":"network.application","type":"keyword","description":"Application level protocol name."},{"field":"network.bytes","type":"long","description":"Total bytes transferred in both directions."},{"field":"network.community_id","type":"keyword","description":"A hash of source and destination IPs and ports."},{"field":"network.direction","type":"keyword","description":"Direction of the network traffic."},{"field":"network.forwarded_ip","type":"ip","description":"Host IP address when the source IP address is the proxy."},{"field":"network.iana_number","type":"keyword","description":"IANA Protocol Number."},{"field":"network.inner","type":"object","description":"Inner VLAN tag information"},{"field":"network.inner.vlan.id","type":"keyword","description":"VLAN ID as reported by the observer."},{"field":"network.inner.vlan.name","type":"keyword","description":"Optional VLAN name as reported by the observer."},{"field":"network.name","type":"keyword","description":"Name given by operators to sections of their network."},{"field":"network.packets","type":"long","description":"Total packets transferred in both directions."},{"field":"network.protocol","type":"keyword","description":"L7 Network protocol name."},{"field":"network.transport","type":"keyword","description":"Protocol Name corresponding to the field `iana_number`."},{"field":"network.type","type":"keyword","description":"In the OSI Model this would be the Network Layer. ipv4, ipv6, ipsec, pim, etc"},{"field":"network.vlan.id","type":"keyword","description":"VLAN ID as reported by the observer."},{"field":"network.vlan.name","type":"keyword","description":"Optional VLAN name as reported by the observer."},{"field":"observer.egress","type":"object","description":"Object field for egress information"},{"field":"observer.egress.interface.alias","type":"keyword","description":"Interface alias"},{"field":"observer.egress.interface.id","type":"keyword","description":"Interface ID"},{"field":"observer.egress.interface.name","type":"keyword","description":"Interface name"},{"field":"observer.egress.vlan.id","type":"keyword","description":"VLAN ID as reported by the observer."},{"field":"observer.egress.vlan.name","type":"keyword","description":"Optional VLAN name as reported by the observer."},{"field":"observer.egress.zone","type":"keyword","description":"Observer Egress zone"},{"field":"observer.geo.city_name","type":"keyword","description":"City name."},{"field":"observer.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"observer.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"observer.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"observer.geo.country_name","type":"keyword","description":"Country name."},{"field":"observer.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"observer.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"observer.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"observer.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"observer.geo.region_name","type":"keyword","description":"Region name."},{"field":"observer.geo.timezone","type":"keyword","description":"Time zone."},{"field":"observer.hostname","type":"keyword","description":"Hostname of the observer."},{"field":"observer.ingress","type":"object","description":"Object field for ingress information"},{"field":"observer.ingress.interface.alias","type":"keyword","description":"Interface alias"},{"field":"observer.ingress.interface.id","type":"keyword","description":"Interface ID"},{"field":"observer.ingress.interface.name","type":"keyword","description":"Interface name"},{"field":"observer.ingress.vlan.id","type":"keyword","description":"VLAN ID as reported by the observer."},{"field":"observer.ingress.vlan.name","type":"keyword","description":"Optional VLAN name as reported by the observer."},{"field":"observer.ingress.zone","type":"keyword","description":"Observer ingress zone"},{"field":"observer.ip","type":"ip","description":"IP addresses of the observer."},{"field":"observer.mac","type":"keyword","description":"MAC addresses of the observer."},{"field":"observer.name","type":"keyword","description":"Custom name of the observer."},{"field":"observer.os.family","type":"keyword","description":"OS family (such as redhat, debian, freebsd, windows)."},{"field":"observer.os.full","type":"keyword","description":"Operating system name, including the version or code name."},{"field":"observer.os.full.text","type":"match_only_text","description":"Operating system name, including the version or code name."},{"field":"observer.os.kernel","type":"keyword","description":"Operating system kernel version as a raw string."},{"field":"observer.os.name","type":"keyword","description":"Operating system name, without the version."},{"field":"observer.os.name.text","type":"match_only_text","description":"Operating system name, without the version."},{"field":"observer.os.platform","type":"keyword","description":"Operating system platform (such centos, ubuntu, windows)."},{"field":"observer.os.type","type":"keyword","description":"Which commercial OS family (one of: linux, macos, unix or windows)."},{"field":"observer.os.version","type":"keyword","description":"Operating system version as a raw string."},{"field":"observer.product","type":"keyword","description":"The product name of the observer."},{"field":"observer.serial_number","type":"keyword","description":"Observer serial number."},{"field":"observer.type","type":"keyword","description":"The type of the observer the data is coming from."},{"field":"observer.vendor","type":"keyword","description":"Vendor name of the observer."},{"field":"observer.version","type":"keyword","description":"Observer version."},{"field":"orchestrator.api_version","type":"keyword","description":"API version being used to carry out the action"},{"field":"orchestrator.cluster.name","type":"keyword","description":"Name of the cluster."},{"field":"orchestrator.cluster.url","type":"keyword","description":"URL of the API used to manage the cluster."},{"field":"orchestrator.cluster.version","type":"keyword","description":"The version of the cluster."},{"field":"orchestrator.namespace","type":"keyword","description":"Namespace in which the action is taking place."},{"field":"orchestrator.organization","type":"keyword","description":"Organization affected by the event (for multi-tenant orchestrator setups)."},{"field":"orchestrator.resource.name","type":"keyword","description":"Name of the resource being acted upon."},{"field":"orchestrator.resource.type","type":"keyword","description":"Type of resource being acted upon."},{"field":"orchestrator.type","type":"keyword","description":"Orchestrator cluster type (e.g. kubernetes, nomad or cloudfoundry)."},{"field":"organization.id","type":"keyword","description":"Unique identifier for the organization."},{"field":"organization.name","type":"keyword","description":"Organization name."},{"field":"organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"package.architecture","type":"keyword","description":"Package architecture."},{"field":"package.build_version","type":"keyword","description":"Build version information"},{"field":"package.checksum","type":"keyword","description":"Checksum of the installed package for verification."},{"field":"package.description","type":"keyword","description":"Description of the package."},{"field":"package.install_scope","type":"keyword","description":"Indicating how the package was installed, e.g. user-local, global."},{"field":"package.installed","type":"date","description":"Time when package was installed."},{"field":"package.license","type":"keyword","description":"Package license"},{"field":"package.name","type":"keyword","description":"Package name"},{"field":"package.path","type":"keyword","description":"Path where the package is installed."},{"field":"package.reference","type":"keyword","description":"Package home page or reference URL"},{"field":"package.size","type":"long","description":"Package size in bytes."},{"field":"package.type","type":"keyword","description":"Package type"},{"field":"package.version","type":"keyword","description":"Package version"},{"field":"process.args","type":"keyword","description":"Array of process arguments."},{"field":"process.args_count","type":"long","description":"Length of the process.args array."},{"field":"process.code_signature.digest_algorithm","type":"keyword","description":"Hashing algorithm used to sign the process."},{"field":"process.code_signature.exists","type":"boolean","description":"Boolean to capture if a signature is present."},{"field":"process.code_signature.signing_id","type":"keyword","description":"The identifier used to sign the process."},{"field":"process.code_signature.status","type":"keyword","description":"Additional information about the certificate status."},{"field":"process.code_signature.subject_name","type":"keyword","description":"Subject name of the code signer"},{"field":"process.code_signature.team_id","type":"keyword","description":"The team identifier used to sign the process."},{"field":"process.code_signature.timestamp","type":"date","description":"When the signature was generated and signed."},{"field":"process.code_signature.trusted","type":"boolean","description":"Stores the trust status of the certificate chain."},{"field":"process.code_signature.valid","type":"boolean","description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"process.command_line","type":"wildcard","description":"Full command line that started the process."},{"field":"process.command_line.text","type":"match_only_text","description":"Full command line that started the process."},{"field":"process.elf.architecture","type":"keyword","description":"Machine architecture of the ELF file."},{"field":"process.elf.byte_order","type":"keyword","description":"Byte sequence of ELF file."},{"field":"process.elf.cpu_type","type":"keyword","description":"CPU type of the ELF file."},{"field":"process.elf.creation_date","type":"date","description":"Build or compile date."},{"field":"process.elf.exports","type":"flattened","description":"List of exported element names and types."},{"field":"process.elf.header.abi_version","type":"keyword","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"process.elf.header.class","type":"keyword","description":"Header class of the ELF file."},{"field":"process.elf.header.data","type":"keyword","description":"Data table of the ELF header."},{"field":"process.elf.header.entrypoint","type":"long","description":"Header entrypoint of the ELF file."},{"field":"process.elf.header.object_version","type":"keyword","description":"0x1\" for original ELF files."},{"field":"process.elf.header.os_abi","type":"keyword","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"process.elf.header.type","type":"keyword","description":"Header type of the ELF file."},{"field":"process.elf.header.version","type":"keyword","description":"Version of the ELF header."},{"field":"process.elf.imports","type":"flattened","description":"List of imported element names and types."},{"field":"process.elf.sections","type":"nested","description":"Section information of the ELF file."},{"field":"process.elf.sections.chi2","type":"long","description":"Chi-square probability distribution of the section."},{"field":"process.elf.sections.entropy","type":"long","description":"Shannon entropy calculation from the section."},{"field":"process.elf.sections.flags","type":"keyword","description":"ELF Section List flags."},{"field":"process.elf.sections.name","type":"keyword","description":"ELF Section List name."},{"field":"process.elf.sections.physical_offset","type":"keyword","description":"ELF Section List offset."},{"field":"process.elf.sections.physical_size","type":"long","description":"ELF Section List physical size."},{"field":"process.elf.sections.type","type":"keyword","description":"ELF Section List type."},{"field":"process.elf.sections.virtual_address","type":"long","description":"ELF Section List virtual address."},{"field":"process.elf.sections.virtual_size","type":"long","description":"ELF Section List virtual size."},{"field":"process.elf.segments","type":"nested","description":"ELF object segment list."},{"field":"process.elf.segments.sections","type":"keyword","description":"ELF object segment sections."},{"field":"process.elf.segments.type","type":"keyword","description":"ELF object segment type."},{"field":"process.elf.shared_libraries","type":"keyword","description":"List of shared libraries used by this ELF object."},{"field":"process.elf.telfhash","type":"keyword","description":"telfhash hash for ELF file."},{"field":"process.end","type":"date","description":"The time the process ended."},{"field":"process.entity_id","type":"keyword","description":"Unique identifier for the process."},{"field":"process.executable","type":"keyword","description":"Absolute path to the process executable."},{"field":"process.executable.text","type":"match_only_text","description":"Absolute path to the process executable."},{"field":"process.exit_code","type":"long","description":"The exit code of the process."},{"field":"process.hash.md5","type":"keyword","description":"MD5 hash."},{"field":"process.hash.sha1","type":"keyword","description":"SHA1 hash."},{"field":"process.hash.sha256","type":"keyword","description":"SHA256 hash."},{"field":"process.hash.sha512","type":"keyword","description":"SHA512 hash."},{"field":"process.hash.ssdeep","type":"keyword","description":"SSDEEP hash."},{"field":"process.name","type":"keyword","description":"Process name."},{"field":"process.name.text","type":"match_only_text","description":"Process name."},{"field":"process.parent.args","type":"keyword","description":"Array of process arguments."},{"field":"process.parent.args_count","type":"long","description":"Length of the process.args array."},{"field":"process.parent.code_signature.digest_algorithm","type":"keyword","description":"Hashing algorithm used to sign the process."},{"field":"process.parent.code_signature.exists","type":"boolean","description":"Boolean to capture if a signature is present."},{"field":"process.parent.code_signature.signing_id","type":"keyword","description":"The identifier used to sign the process."},{"field":"process.parent.code_signature.status","type":"keyword","description":"Additional information about the certificate status."},{"field":"process.parent.code_signature.subject_name","type":"keyword","description":"Subject name of the code signer"},{"field":"process.parent.code_signature.team_id","type":"keyword","description":"The team identifier used to sign the process."},{"field":"process.parent.code_signature.timestamp","type":"date","description":"When the signature was generated and signed."},{"field":"process.parent.code_signature.trusted","type":"boolean","description":"Stores the trust status of the certificate chain."},{"field":"process.parent.code_signature.valid","type":"boolean","description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"process.parent.command_line","type":"wildcard","description":"Full command line that started the process."},{"field":"process.parent.command_line.text","type":"match_only_text","description":"Full command line that started the process."},{"field":"process.parent.elf.architecture","type":"keyword","description":"Machine architecture of the ELF file."},{"field":"process.parent.elf.byte_order","type":"keyword","description":"Byte sequence of ELF file."},{"field":"process.parent.elf.cpu_type","type":"keyword","description":"CPU type of the ELF file."},{"field":"process.parent.elf.creation_date","type":"date","description":"Build or compile date."},{"field":"process.parent.elf.exports","type":"flattened","description":"List of exported element names and types."},{"field":"process.parent.elf.header.abi_version","type":"keyword","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"process.parent.elf.header.class","type":"keyword","description":"Header class of the ELF file."},{"field":"process.parent.elf.header.data","type":"keyword","description":"Data table of the ELF header."},{"field":"process.parent.elf.header.entrypoint","type":"long","description":"Header entrypoint of the ELF file."},{"field":"process.parent.elf.header.object_version","type":"keyword","description":"0x1\" for original ELF files."},{"field":"process.parent.elf.header.os_abi","type":"keyword","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"process.parent.elf.header.type","type":"keyword","description":"Header type of the ELF file."},{"field":"process.parent.elf.header.version","type":"keyword","description":"Version of the ELF header."},{"field":"process.parent.elf.imports","type":"flattened","description":"List of imported element names and types."},{"field":"process.parent.elf.sections","type":"nested","description":"Section information of the ELF file."},{"field":"process.parent.elf.sections.chi2","type":"long","description":"Chi-square probability distribution of the section."},{"field":"process.parent.elf.sections.entropy","type":"long","description":"Shannon entropy calculation from the section."},{"field":"process.parent.elf.sections.flags","type":"keyword","description":"ELF Section List flags."},{"field":"process.parent.elf.sections.name","type":"keyword","description":"ELF Section List name."},{"field":"process.parent.elf.sections.physical_offset","type":"keyword","description":"ELF Section List offset."},{"field":"process.parent.elf.sections.physical_size","type":"long","description":"ELF Section List physical size."},{"field":"process.parent.elf.sections.type","type":"keyword","description":"ELF Section List type."},{"field":"process.parent.elf.sections.virtual_address","type":"long","description":"ELF Section List virtual address."},{"field":"process.parent.elf.sections.virtual_size","type":"long","description":"ELF Section List virtual size."},{"field":"process.parent.elf.segments","type":"nested","description":"ELF object segment list."},{"field":"process.parent.elf.segments.sections","type":"keyword","description":"ELF object segment sections."},{"field":"process.parent.elf.segments.type","type":"keyword","description":"ELF object segment type."},{"field":"process.parent.elf.shared_libraries","type":"keyword","description":"List of shared libraries used by this ELF object."},{"field":"process.parent.elf.telfhash","type":"keyword","description":"telfhash hash for ELF file."},{"field":"process.parent.end","type":"date","description":"The time the process ended."},{"field":"process.parent.entity_id","type":"keyword","description":"Unique identifier for the process."},{"field":"process.parent.executable","type":"keyword","description":"Absolute path to the process executable."},{"field":"process.parent.executable.text","type":"match_only_text","description":"Absolute path to the process executable."},{"field":"process.parent.exit_code","type":"long","description":"The exit code of the process."},{"field":"process.parent.hash.md5","type":"keyword","description":"MD5 hash."},{"field":"process.parent.hash.sha1","type":"keyword","description":"SHA1 hash."},{"field":"process.parent.hash.sha256","type":"keyword","description":"SHA256 hash."},{"field":"process.parent.hash.sha512","type":"keyword","description":"SHA512 hash."},{"field":"process.parent.hash.ssdeep","type":"keyword","description":"SSDEEP hash."},{"field":"process.parent.name","type":"keyword","description":"Process name."},{"field":"process.parent.name.text","type":"match_only_text","description":"Process name."},{"field":"process.parent.pe.architecture","type":"keyword","description":"CPU architecture target for the file."},{"field":"process.parent.pe.company","type":"keyword","description":"Internal company name of the file, provided at compile-time."},{"field":"process.parent.pe.description","type":"keyword","description":"Internal description of the file, provided at compile-time."},{"field":"process.parent.pe.file_version","type":"keyword","description":"Process name."},{"field":"process.parent.pe.imphash","type":"keyword","description":"A hash of the imports in a PE file."},{"field":"process.parent.pe.original_file_name","type":"keyword","description":"Internal name of the file, provided at compile-time."},{"field":"process.parent.pe.product","type":"keyword","description":"Internal product name of the file, provided at compile-time."},{"field":"process.parent.pgid","type":"long","description":"Identifier of the group of processes the process belongs to."},{"field":"process.parent.pid","type":"long","description":"Process id."},{"field":"process.parent.ppid","type":"long","description":"Parent process' pid."},{"field":"process.parent.start","type":"date","description":"The time the process started."},{"field":"process.parent.thread.id","type":"long","description":"Thread ID."},{"field":"process.parent.thread.name","type":"keyword","description":"Thread name."},{"field":"process.parent.title","type":"keyword","description":"Process title."},{"field":"process.parent.title.text","type":"match_only_text","description":"Process title."},{"field":"process.parent.uptime","type":"long","description":"Seconds the process has been up."},{"field":"process.parent.working_directory","type":"keyword","description":"The working directory of the process."},{"field":"process.parent.working_directory.text","type":"match_only_text","description":"The working directory of the process."},{"field":"process.pe.architecture","type":"keyword","description":"CPU architecture target for the file."},{"field":"process.pe.company","type":"keyword","description":"Internal company name of the file, provided at compile-time."},{"field":"process.pe.description","type":"keyword","description":"Internal description of the file, provided at compile-time."},{"field":"process.pe.file_version","type":"keyword","description":"Process name."},{"field":"process.pe.imphash","type":"keyword","description":"A hash of the imports in a PE file."},{"field":"process.pe.original_file_name","type":"keyword","description":"Internal name of the file, provided at compile-time."},{"field":"process.pe.product","type":"keyword","description":"Internal product name of the file, provided at compile-time."},{"field":"process.pgid","type":"long","description":"Identifier of the group of processes the process belongs to."},{"field":"process.pid","type":"long","description":"Process id."},{"field":"process.ppid","type":"long","description":"Parent process' pid."},{"field":"process.start","type":"date","description":"The time the process started."},{"field":"process.thread.id","type":"long","description":"Thread ID."},{"field":"process.thread.name","type":"keyword","description":"Thread name."},{"field":"process.title","type":"keyword","description":"Process title."},{"field":"process.title.text","type":"match_only_text","description":"Process title."},{"field":"process.uptime","type":"long","description":"Seconds the process has been up."},{"field":"process.working_directory","type":"keyword","description":"The working directory of the process."},{"field":"process.working_directory.text","type":"match_only_text","description":"The working directory of the process."},{"field":"registry.data.bytes","type":"keyword","description":"Original bytes written with base64 encoding."},{"field":"registry.data.strings","type":"wildcard","description":"List of strings representing what was written to the registry."},{"field":"registry.data.type","type":"keyword","description":"Standard registry type for encoding contents"},{"field":"registry.hive","type":"keyword","description":"Abbreviated name for the hive."},{"field":"registry.key","type":"keyword","description":"Hive-relative path of keys."},{"field":"registry.path","type":"keyword","description":"Full path, including hive, key and value"},{"field":"registry.value","type":"keyword","description":"Name of the value written."},{"field":"related.hash","type":"keyword","description":"All the hashes seen on your event."},{"field":"related.hosts","type":"keyword","description":"All the host identifiers seen on your event."},{"field":"related.ip","type":"ip","description":"All of the IPs seen on your event."},{"field":"related.user","type":"keyword","description":"All the user names or other user identifiers seen on the event."},{"field":"rule.author","type":"keyword","description":"Rule author"},{"field":"rule.category","type":"keyword","description":"Rule category"},{"field":"rule.description","type":"keyword","description":"Rule description"},{"field":"rule.id","type":"keyword","description":"Rule ID"},{"field":"rule.license","type":"keyword","description":"Rule license"},{"field":"rule.name","type":"keyword","description":"Rule name"},{"field":"rule.reference","type":"keyword","description":"Rule reference URL"},{"field":"rule.ruleset","type":"keyword","description":"Rule ruleset"},{"field":"rule.uuid","type":"keyword","description":"Rule UUID"},{"field":"rule.version","type":"keyword","description":"Rule version"},{"field":"server.address","type":"keyword","description":"Server network address."},{"field":"server.as.number","type":"long","description":"Unique number allocated to the autonomous system."},{"field":"server.as.organization.name","type":"keyword","description":"Organization name."},{"field":"server.as.organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"server.bytes","type":"long","description":"Bytes sent from the server to the client."},{"field":"server.domain","type":"keyword","description":"Server domain."},{"field":"server.geo.city_name","type":"keyword","description":"City name."},{"field":"server.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"server.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"server.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"server.geo.country_name","type":"keyword","description":"Country name."},{"field":"server.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"server.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"server.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"server.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"server.geo.region_name","type":"keyword","description":"Region name."},{"field":"server.geo.timezone","type":"keyword","description":"Time zone."},{"field":"server.ip","type":"ip","description":"IP address of the server."},{"field":"server.mac","type":"keyword","description":"MAC address of the server."},{"field":"server.nat.ip","type":"ip","description":"Server NAT ip"},{"field":"server.nat.port","type":"long","description":"Server NAT port"},{"field":"server.packets","type":"long","description":"Packets sent from the server to the client."},{"field":"server.port","type":"long","description":"Port of the server."},{"field":"server.registered_domain","type":"keyword","description":"The highest registered server domain, stripped of the subdomain."},{"field":"server.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"server.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"server.user.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"server.user.email","type":"keyword","description":"User email address."},{"field":"server.user.full_name","type":"keyword","description":"User's full name, if available."},{"field":"server.user.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"server.user.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"server.user.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"server.user.group.name","type":"keyword","description":"Name of the group."},{"field":"server.user.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"server.user.id","type":"keyword","description":"Unique identifier of the user."},{"field":"server.user.name","type":"keyword","description":"Short name or login of the user."},{"field":"server.user.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"server.user.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"service.address","type":"keyword","description":"Address of this service."},{"field":"service.environment","type":"keyword","description":"Environment of the service."},{"field":"service.ephemeral_id","type":"keyword","description":"Ephemeral identifier of this service."},{"field":"service.id","type":"keyword","description":"Unique identifier of the running service."},{"field":"service.name","type":"keyword","description":"Name of the service."},{"field":"service.node.name","type":"keyword","description":"Name of the service node."},{"field":"service.state","type":"keyword","description":"Current state of the service."},{"field":"service.type","type":"keyword","description":"The type of the service."},{"field":"service.version","type":"keyword","description":"Version of the service."},{"field":"source.address","type":"keyword","description":"Source network address."},{"field":"source.as.number","type":"long","description":"Unique number allocated to the autonomous system."},{"field":"source.as.organization.name","type":"keyword","description":"Organization name."},{"field":"source.as.organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"source.bytes","type":"long","description":"Bytes sent from the source to the destination."},{"field":"source.domain","type":"keyword","description":"Source domain."},{"field":"source.geo.city_name","type":"keyword","description":"City name."},{"field":"source.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"source.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"source.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"source.geo.country_name","type":"keyword","description":"Country name."},{"field":"source.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"source.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"source.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"source.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"source.geo.region_name","type":"keyword","description":"Region name."},{"field":"source.geo.timezone","type":"keyword","description":"Time zone."},{"field":"source.ip","type":"ip","description":"IP address of the source."},{"field":"source.mac","type":"keyword","description":"MAC address of the source."},{"field":"source.nat.ip","type":"ip","description":"Source NAT ip"},{"field":"source.nat.port","type":"long","description":"Source NAT port"},{"field":"source.packets","type":"long","description":"Packets sent from the source to the destination."},{"field":"source.port","type":"long","description":"Port of the source."},{"field":"source.registered_domain","type":"keyword","description":"The highest registered source domain, stripped of the subdomain."},{"field":"source.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"source.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"source.user.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"source.user.email","type":"keyword","description":"User email address."},{"field":"source.user.full_name","type":"keyword","description":"User's full name, if available."},{"field":"source.user.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"source.user.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"source.user.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"source.user.group.name","type":"keyword","description":"Name of the group."},{"field":"source.user.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"source.user.id","type":"keyword","description":"Unique identifier of the user."},{"field":"source.user.name","type":"keyword","description":"Short name or login of the user."},{"field":"source.user.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"source.user.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"span.id","type":"keyword","description":"Unique identifier of the span within the scope of its trace."},{"field":"threat.enrichments","type":"nested","description":"List of objects containing indicators enriching the event."},{"field":"threat.enrichments.indicator","type":"object","description":"Object containing indicators enriching the event."},{"field":"threat.enrichments.indicator.as.number","type":"long","description":"Unique number allocated to the autonomous system."},{"field":"threat.enrichments.indicator.as.organization.name","type":"keyword","description":"Organization name."},{"field":"threat.enrichments.indicator.as.organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"threat.enrichments.indicator.confidence","type":"keyword","description":"Indicator confidence rating"},{"field":"threat.enrichments.indicator.description","type":"keyword","description":"Indicator description"},{"field":"threat.enrichments.indicator.email.address","type":"keyword","description":"Indicator email address"},{"field":"threat.enrichments.indicator.file.accessed","type":"date","description":"Last time the file was accessed."},{"field":"threat.enrichments.indicator.file.attributes","type":"keyword","description":"Array of file attributes."},{"field":"threat.enrichments.indicator.file.code_signature.digest_algorithm","type":"keyword","description":"Hashing algorithm used to sign the process."},{"field":"threat.enrichments.indicator.file.code_signature.exists","type":"boolean","description":"Boolean to capture if a signature is present."},{"field":"threat.enrichments.indicator.file.code_signature.signing_id","type":"keyword","description":"The identifier used to sign the process."},{"field":"threat.enrichments.indicator.file.code_signature.status","type":"keyword","description":"Additional information about the certificate status."},{"field":"threat.enrichments.indicator.file.code_signature.subject_name","type":"keyword","description":"Subject name of the code signer"},{"field":"threat.enrichments.indicator.file.code_signature.team_id","type":"keyword","description":"The team identifier used to sign the process."},{"field":"threat.enrichments.indicator.file.code_signature.timestamp","type":"date","description":"When the signature was generated and signed."},{"field":"threat.enrichments.indicator.file.code_signature.trusted","type":"boolean","description":"Stores the trust status of the certificate chain."},{"field":"threat.enrichments.indicator.file.code_signature.valid","type":"boolean","description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"threat.enrichments.indicator.file.created","type":"date","description":"File creation time."},{"field":"threat.enrichments.indicator.file.ctime","type":"date","description":"Last time the file attributes or metadata changed."},{"field":"threat.enrichments.indicator.file.device","type":"keyword","description":"Device that is the source of the file."},{"field":"threat.enrichments.indicator.file.directory","type":"keyword","description":"Directory where the file is located."},{"field":"threat.enrichments.indicator.file.drive_letter","type":"keyword","description":"Drive letter where the file is located."},{"field":"threat.enrichments.indicator.file.elf.architecture","type":"keyword","description":"Machine architecture of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.byte_order","type":"keyword","description":"Byte sequence of ELF file."},{"field":"threat.enrichments.indicator.file.elf.cpu_type","type":"keyword","description":"CPU type of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.creation_date","type":"date","description":"Build or compile date."},{"field":"threat.enrichments.indicator.file.elf.exports","type":"flattened","description":"List of exported element names and types."},{"field":"threat.enrichments.indicator.file.elf.header.abi_version","type":"keyword","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"threat.enrichments.indicator.file.elf.header.class","type":"keyword","description":"Header class of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.header.data","type":"keyword","description":"Data table of the ELF header."},{"field":"threat.enrichments.indicator.file.elf.header.entrypoint","type":"long","description":"Header entrypoint of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.header.object_version","type":"keyword","description":"0x1\" for original ELF files."},{"field":"threat.enrichments.indicator.file.elf.header.os_abi","type":"keyword","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"threat.enrichments.indicator.file.elf.header.type","type":"keyword","description":"Header type of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.header.version","type":"keyword","description":"Version of the ELF header."},{"field":"threat.enrichments.indicator.file.elf.imports","type":"flattened","description":"List of imported element names and types."},{"field":"threat.enrichments.indicator.file.elf.sections","type":"nested","description":"Section information of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.sections.chi2","type":"long","description":"Chi-square probability distribution of the section."},{"field":"threat.enrichments.indicator.file.elf.sections.entropy","type":"long","description":"Shannon entropy calculation from the section."},{"field":"threat.enrichments.indicator.file.elf.sections.flags","type":"keyword","description":"ELF Section List flags."},{"field":"threat.enrichments.indicator.file.elf.sections.name","type":"keyword","description":"ELF Section List name."},{"field":"threat.enrichments.indicator.file.elf.sections.physical_offset","type":"keyword","description":"ELF Section List offset."},{"field":"threat.enrichments.indicator.file.elf.sections.physical_size","type":"long","description":"ELF Section List physical size."},{"field":"threat.enrichments.indicator.file.elf.sections.type","type":"keyword","description":"ELF Section List type."},{"field":"threat.enrichments.indicator.file.elf.sections.virtual_address","type":"long","description":"ELF Section List virtual address."},{"field":"threat.enrichments.indicator.file.elf.sections.virtual_size","type":"long","description":"ELF Section List virtual size."},{"field":"threat.enrichments.indicator.file.elf.segments","type":"nested","description":"ELF object segment list."},{"field":"threat.enrichments.indicator.file.elf.segments.sections","type":"keyword","description":"ELF object segment sections."},{"field":"threat.enrichments.indicator.file.elf.segments.type","type":"keyword","description":"ELF object segment type."},{"field":"threat.enrichments.indicator.file.elf.shared_libraries","type":"keyword","description":"List of shared libraries used by this ELF object."},{"field":"threat.enrichments.indicator.file.elf.telfhash","type":"keyword","description":"telfhash hash for ELF file."},{"field":"threat.enrichments.indicator.file.extension","type":"keyword","description":"File extension, excluding the leading dot."},{"field":"threat.enrichments.indicator.file.fork_name","type":"keyword","description":"A fork is additional data associated with a filesystem object."},{"field":"threat.enrichments.indicator.file.gid","type":"keyword","description":"Primary group ID (GID) of the file."},{"field":"threat.enrichments.indicator.file.group","type":"keyword","description":"Primary group name of the file."},{"field":"threat.enrichments.indicator.file.hash.md5","type":"keyword","description":"MD5 hash."},{"field":"threat.enrichments.indicator.file.hash.sha1","type":"keyword","description":"SHA1 hash."},{"field":"threat.enrichments.indicator.file.hash.sha256","type":"keyword","description":"SHA256 hash."},{"field":"threat.enrichments.indicator.file.hash.sha512","type":"keyword","description":"SHA512 hash."},{"field":"threat.enrichments.indicator.file.hash.ssdeep","type":"keyword","description":"SSDEEP hash."},{"field":"threat.enrichments.indicator.file.inode","type":"keyword","description":"Inode representing the file in the filesystem."},{"field":"threat.enrichments.indicator.file.mime_type","type":"keyword","description":"Media type of file, document, or arrangement of bytes."},{"field":"threat.enrichments.indicator.file.mode","type":"keyword","description":"Mode of the file in octal representation."},{"field":"threat.enrichments.indicator.file.mtime","type":"date","description":"Last time the file content was modified."},{"field":"threat.enrichments.indicator.file.name","type":"keyword","description":"Name of the file including the extension, without the directory."},{"field":"threat.enrichments.indicator.file.owner","type":"keyword","description":"File owner's username."},{"field":"threat.enrichments.indicator.file.path","type":"keyword","description":"Full path to the file, including the file name."},{"field":"threat.enrichments.indicator.file.path.text","type":"match_only_text","description":"Full path to the file, including the file name."},{"field":"threat.enrichments.indicator.file.pe.architecture","type":"keyword","description":"CPU architecture target for the file."},{"field":"threat.enrichments.indicator.file.pe.company","type":"keyword","description":"Internal company name of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.pe.description","type":"keyword","description":"Internal description of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.pe.file_version","type":"keyword","description":"Process name."},{"field":"threat.enrichments.indicator.file.pe.imphash","type":"keyword","description":"A hash of the imports in a PE file."},{"field":"threat.enrichments.indicator.file.pe.original_file_name","type":"keyword","description":"Internal name of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.pe.product","type":"keyword","description":"Internal product name of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.size","type":"long","description":"File size in bytes."},{"field":"threat.enrichments.indicator.file.target_path","type":"keyword","description":"Target path for symlinks."},{"field":"threat.enrichments.indicator.file.target_path.text","type":"match_only_text","description":"Target path for symlinks."},{"field":"threat.enrichments.indicator.file.type","type":"keyword","description":"File type (file, dir, or symlink)."},{"field":"threat.enrichments.indicator.file.uid","type":"keyword","description":"The user ID (UID) or security identifier (SID) of the file owner."},{"field":"threat.enrichments.indicator.file.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"threat.enrichments.indicator.file.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"threat.enrichments.indicator.file.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.file.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.file.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.enrichments.indicator.file.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"threat.enrichments.indicator.file.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"threat.enrichments.indicator.file.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.enrichments.indicator.file.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.enrichments.indicator.file.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"threat.enrichments.indicator.file.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"threat.enrichments.indicator.file.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"threat.enrichments.indicator.file.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"threat.enrichments.indicator.file.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"threat.enrichments.indicator.file.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.enrichments.indicator.file.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.file.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"threat.enrichments.indicator.file.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"threat.enrichments.indicator.file.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.file.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"threat.enrichments.indicator.first_seen","type":"date","description":"Date/time indicator was first reported."},{"field":"threat.enrichments.indicator.geo.city_name","type":"keyword","description":"City name."},{"field":"threat.enrichments.indicator.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"threat.enrichments.indicator.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"threat.enrichments.indicator.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"threat.enrichments.indicator.geo.country_name","type":"keyword","description":"Country name."},{"field":"threat.enrichments.indicator.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"threat.enrichments.indicator.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"threat.enrichments.indicator.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"threat.enrichments.indicator.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"threat.enrichments.indicator.geo.region_name","type":"keyword","description":"Region name."},{"field":"threat.enrichments.indicator.geo.timezone","type":"keyword","description":"Time zone."},{"field":"threat.enrichments.indicator.ip","type":"ip","description":"Indicator IP address"},{"field":"threat.enrichments.indicator.last_seen","type":"date","description":"Date/time indicator was last reported."},{"field":"threat.enrichments.indicator.marking.tlp","type":"keyword","description":"Indicator TLP marking"},{"field":"threat.enrichments.indicator.modified_at","type":"date","description":"Date/time indicator was last updated."},{"field":"threat.enrichments.indicator.port","type":"long","description":"Indicator port"},{"field":"threat.enrichments.indicator.provider","type":"keyword","description":"Indicator provider"},{"field":"threat.enrichments.indicator.reference","type":"keyword","description":"Indicator reference URL"},{"field":"threat.enrichments.indicator.registry.data.bytes","type":"keyword","description":"Original bytes written with base64 encoding."},{"field":"threat.enrichments.indicator.registry.data.strings","type":"wildcard","description":"List of strings representing what was written to the registry."},{"field":"threat.enrichments.indicator.registry.data.type","type":"keyword","description":"Standard registry type for encoding contents"},{"field":"threat.enrichments.indicator.registry.hive","type":"keyword","description":"Abbreviated name for the hive."},{"field":"threat.enrichments.indicator.registry.key","type":"keyword","description":"Hive-relative path of keys."},{"field":"threat.enrichments.indicator.registry.path","type":"keyword","description":"Full path, including hive, key and value"},{"field":"threat.enrichments.indicator.registry.value","type":"keyword","description":"Name of the value written."},{"field":"threat.enrichments.indicator.scanner_stats","type":"long","description":"Scanner statistics"},{"field":"threat.enrichments.indicator.sightings","type":"long","description":"Number of times indicator observed"},{"field":"threat.enrichments.indicator.type","type":"keyword","description":"Type of indicator"},{"field":"threat.enrichments.indicator.url.domain","type":"keyword","description":"Domain of the url."},{"field":"threat.enrichments.indicator.url.extension","type":"keyword","description":"File extension from the request url, excluding the leading dot."},{"field":"threat.enrichments.indicator.url.fragment","type":"keyword","description":"Portion of the url after the `#`."},{"field":"threat.enrichments.indicator.url.full","type":"wildcard","description":"Full unparsed URL."},{"field":"threat.enrichments.indicator.url.full.text","type":"match_only_text","description":"Full unparsed URL."},{"field":"threat.enrichments.indicator.url.original","type":"wildcard","description":"Unmodified original url as seen in the event source."},{"field":"threat.enrichments.indicator.url.original.text","type":"match_only_text","description":"Unmodified original url as seen in the event source."},{"field":"threat.enrichments.indicator.url.password","type":"keyword","description":"Password of the request."},{"field":"threat.enrichments.indicator.url.path","type":"wildcard","description":"Path of the request, such as \"/search\"."},{"field":"threat.enrichments.indicator.url.port","type":"long","description":"Port of the request, such as 443."},{"field":"threat.enrichments.indicator.url.query","type":"keyword","description":"Query string of the request."},{"field":"threat.enrichments.indicator.url.registered_domain","type":"keyword","description":"The highest registered url domain, stripped of the subdomain."},{"field":"threat.enrichments.indicator.url.scheme","type":"keyword","description":"Scheme of the url."},{"field":"threat.enrichments.indicator.url.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"threat.enrichments.indicator.url.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"threat.enrichments.indicator.url.username","type":"keyword","description":"Username of the request."},{"field":"threat.enrichments.indicator.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"threat.enrichments.indicator.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"threat.enrichments.indicator.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.enrichments.indicator.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"threat.enrichments.indicator.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"threat.enrichments.indicator.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.enrichments.indicator.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.enrichments.indicator.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"threat.enrichments.indicator.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"threat.enrichments.indicator.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"threat.enrichments.indicator.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"threat.enrichments.indicator.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"threat.enrichments.indicator.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.enrichments.indicator.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"threat.enrichments.indicator.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"threat.enrichments.indicator.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"threat.enrichments.matched.atomic","type":"keyword","description":"Matched indicator value"},{"field":"threat.enrichments.matched.field","type":"keyword","description":"Matched indicator field"},{"field":"threat.enrichments.matched.id","type":"keyword","description":"Matched indicator identifier"},{"field":"threat.enrichments.matched.index","type":"keyword","description":"Matched indicator index"},{"field":"threat.enrichments.matched.type","type":"keyword","description":"Type of indicator match"},{"field":"threat.framework","type":"keyword","description":"Threat classification framework."},{"field":"threat.group.alias","type":"keyword","description":"Alias of the group."},{"field":"threat.group.id","type":"keyword","description":"ID of the group."},{"field":"threat.group.name","type":"keyword","description":"Name of the group."},{"field":"threat.group.reference","type":"keyword","description":"Reference URL of the group."},{"field":"threat.indicator.as.number","type":"long","description":"Unique number allocated to the autonomous system."},{"field":"threat.indicator.as.organization.name","type":"keyword","description":"Organization name."},{"field":"threat.indicator.as.organization.name.text","type":"match_only_text","description":"Organization name."},{"field":"threat.indicator.confidence","type":"keyword","description":"Indicator confidence rating"},{"field":"threat.indicator.description","type":"keyword","description":"Indicator description"},{"field":"threat.indicator.email.address","type":"keyword","description":"Indicator email address"},{"field":"threat.indicator.file.accessed","type":"date","description":"Last time the file was accessed."},{"field":"threat.indicator.file.attributes","type":"keyword","description":"Array of file attributes."},{"field":"threat.indicator.file.code_signature.digest_algorithm","type":"keyword","description":"Hashing algorithm used to sign the process."},{"field":"threat.indicator.file.code_signature.exists","type":"boolean","description":"Boolean to capture if a signature is present."},{"field":"threat.indicator.file.code_signature.signing_id","type":"keyword","description":"The identifier used to sign the process."},{"field":"threat.indicator.file.code_signature.status","type":"keyword","description":"Additional information about the certificate status."},{"field":"threat.indicator.file.code_signature.subject_name","type":"keyword","description":"Subject name of the code signer"},{"field":"threat.indicator.file.code_signature.team_id","type":"keyword","description":"The team identifier used to sign the process."},{"field":"threat.indicator.file.code_signature.timestamp","type":"date","description":"When the signature was generated and signed."},{"field":"threat.indicator.file.code_signature.trusted","type":"boolean","description":"Stores the trust status of the certificate chain."},{"field":"threat.indicator.file.code_signature.valid","type":"boolean","description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"threat.indicator.file.created","type":"date","description":"File creation time."},{"field":"threat.indicator.file.ctime","type":"date","description":"Last time the file attributes or metadata changed."},{"field":"threat.indicator.file.device","type":"keyword","description":"Device that is the source of the file."},{"field":"threat.indicator.file.directory","type":"keyword","description":"Directory where the file is located."},{"field":"threat.indicator.file.drive_letter","type":"keyword","description":"Drive letter where the file is located."},{"field":"threat.indicator.file.elf.architecture","type":"keyword","description":"Machine architecture of the ELF file."},{"field":"threat.indicator.file.elf.byte_order","type":"keyword","description":"Byte sequence of ELF file."},{"field":"threat.indicator.file.elf.cpu_type","type":"keyword","description":"CPU type of the ELF file."},{"field":"threat.indicator.file.elf.creation_date","type":"date","description":"Build or compile date."},{"field":"threat.indicator.file.elf.exports","type":"flattened","description":"List of exported element names and types."},{"field":"threat.indicator.file.elf.header.abi_version","type":"keyword","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"threat.indicator.file.elf.header.class","type":"keyword","description":"Header class of the ELF file."},{"field":"threat.indicator.file.elf.header.data","type":"keyword","description":"Data table of the ELF header."},{"field":"threat.indicator.file.elf.header.entrypoint","type":"long","description":"Header entrypoint of the ELF file."},{"field":"threat.indicator.file.elf.header.object_version","type":"keyword","description":"0x1\" for original ELF files."},{"field":"threat.indicator.file.elf.header.os_abi","type":"keyword","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"threat.indicator.file.elf.header.type","type":"keyword","description":"Header type of the ELF file."},{"field":"threat.indicator.file.elf.header.version","type":"keyword","description":"Version of the ELF header."},{"field":"threat.indicator.file.elf.imports","type":"flattened","description":"List of imported element names and types."},{"field":"threat.indicator.file.elf.sections","type":"nested","description":"Section information of the ELF file."},{"field":"threat.indicator.file.elf.sections.chi2","type":"long","description":"Chi-square probability distribution of the section."},{"field":"threat.indicator.file.elf.sections.entropy","type":"long","description":"Shannon entropy calculation from the section."},{"field":"threat.indicator.file.elf.sections.flags","type":"keyword","description":"ELF Section List flags."},{"field":"threat.indicator.file.elf.sections.name","type":"keyword","description":"ELF Section List name."},{"field":"threat.indicator.file.elf.sections.physical_offset","type":"keyword","description":"ELF Section List offset."},{"field":"threat.indicator.file.elf.sections.physical_size","type":"long","description":"ELF Section List physical size."},{"field":"threat.indicator.file.elf.sections.type","type":"keyword","description":"ELF Section List type."},{"field":"threat.indicator.file.elf.sections.virtual_address","type":"long","description":"ELF Section List virtual address."},{"field":"threat.indicator.file.elf.sections.virtual_size","type":"long","description":"ELF Section List virtual size."},{"field":"threat.indicator.file.elf.segments","type":"nested","description":"ELF object segment list."},{"field":"threat.indicator.file.elf.segments.sections","type":"keyword","description":"ELF object segment sections."},{"field":"threat.indicator.file.elf.segments.type","type":"keyword","description":"ELF object segment type."},{"field":"threat.indicator.file.elf.shared_libraries","type":"keyword","description":"List of shared libraries used by this ELF object."},{"field":"threat.indicator.file.elf.telfhash","type":"keyword","description":"telfhash hash for ELF file."},{"field":"threat.indicator.file.extension","type":"keyword","description":"File extension, excluding the leading dot."},{"field":"threat.indicator.file.fork_name","type":"keyword","description":"A fork is additional data associated with a filesystem object."},{"field":"threat.indicator.file.gid","type":"keyword","description":"Primary group ID (GID) of the file."},{"field":"threat.indicator.file.group","type":"keyword","description":"Primary group name of the file."},{"field":"threat.indicator.file.hash.md5","type":"keyword","description":"MD5 hash."},{"field":"threat.indicator.file.hash.sha1","type":"keyword","description":"SHA1 hash."},{"field":"threat.indicator.file.hash.sha256","type":"keyword","description":"SHA256 hash."},{"field":"threat.indicator.file.hash.sha512","type":"keyword","description":"SHA512 hash."},{"field":"threat.indicator.file.hash.ssdeep","type":"keyword","description":"SSDEEP hash."},{"field":"threat.indicator.file.inode","type":"keyword","description":"Inode representing the file in the filesystem."},{"field":"threat.indicator.file.mime_type","type":"keyword","description":"Media type of file, document, or arrangement of bytes."},{"field":"threat.indicator.file.mode","type":"keyword","description":"Mode of the file in octal representation."},{"field":"threat.indicator.file.mtime","type":"date","description":"Last time the file content was modified."},{"field":"threat.indicator.file.name","type":"keyword","description":"Name of the file including the extension, without the directory."},{"field":"threat.indicator.file.owner","type":"keyword","description":"File owner's username."},{"field":"threat.indicator.file.path","type":"keyword","description":"Full path to the file, including the file name."},{"field":"threat.indicator.file.path.text","type":"match_only_text","description":"Full path to the file, including the file name."},{"field":"threat.indicator.file.pe.architecture","type":"keyword","description":"CPU architecture target for the file."},{"field":"threat.indicator.file.pe.company","type":"keyword","description":"Internal company name of the file, provided at compile-time."},{"field":"threat.indicator.file.pe.description","type":"keyword","description":"Internal description of the file, provided at compile-time."},{"field":"threat.indicator.file.pe.file_version","type":"keyword","description":"Process name."},{"field":"threat.indicator.file.pe.imphash","type":"keyword","description":"A hash of the imports in a PE file."},{"field":"threat.indicator.file.pe.original_file_name","type":"keyword","description":"Internal name of the file, provided at compile-time."},{"field":"threat.indicator.file.pe.product","type":"keyword","description":"Internal product name of the file, provided at compile-time."},{"field":"threat.indicator.file.size","type":"long","description":"File size in bytes."},{"field":"threat.indicator.file.target_path","type":"keyword","description":"Target path for symlinks."},{"field":"threat.indicator.file.target_path.text","type":"match_only_text","description":"Target path for symlinks."},{"field":"threat.indicator.file.type","type":"keyword","description":"File type (file, dir, or symlink)."},{"field":"threat.indicator.file.uid","type":"keyword","description":"The user ID (UID) or security identifier (SID) of the file owner."},{"field":"threat.indicator.file.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"threat.indicator.file.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"threat.indicator.file.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.indicator.file.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.file.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.indicator.file.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"threat.indicator.file.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"threat.indicator.file.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.indicator.file.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.indicator.file.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"threat.indicator.file.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"threat.indicator.file.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"threat.indicator.file.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"threat.indicator.file.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"threat.indicator.file.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.indicator.file.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.indicator.file.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"threat.indicator.file.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"threat.indicator.file.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.file.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"threat.indicator.first_seen","type":"date","description":"Date/time indicator was first reported."},{"field":"threat.indicator.geo.city_name","type":"keyword","description":"City name."},{"field":"threat.indicator.geo.continent_code","type":"keyword","description":"Continent code."},{"field":"threat.indicator.geo.continent_name","type":"keyword","description":"Name of the continent."},{"field":"threat.indicator.geo.country_iso_code","type":"keyword","description":"Country ISO code."},{"field":"threat.indicator.geo.country_name","type":"keyword","description":"Country name."},{"field":"threat.indicator.geo.location","type":"geo_point","description":"Longitude and latitude."},{"field":"threat.indicator.geo.name","type":"keyword","description":"User-defined description of a location."},{"field":"threat.indicator.geo.postal_code","type":"keyword","description":"Postal code."},{"field":"threat.indicator.geo.region_iso_code","type":"keyword","description":"Region ISO code."},{"field":"threat.indicator.geo.region_name","type":"keyword","description":"Region name."},{"field":"threat.indicator.geo.timezone","type":"keyword","description":"Time zone."},{"field":"threat.indicator.ip","type":"ip","description":"Indicator IP address"},{"field":"threat.indicator.last_seen","type":"date","description":"Date/time indicator was last reported."},{"field":"threat.indicator.marking.tlp","type":"keyword","description":"Indicator TLP marking"},{"field":"threat.indicator.modified_at","type":"date","description":"Date/time indicator was last updated."},{"field":"threat.indicator.port","type":"long","description":"Indicator port"},{"field":"threat.indicator.provider","type":"keyword","description":"Indicator provider"},{"field":"threat.indicator.reference","type":"keyword","description":"Indicator reference URL"},{"field":"threat.indicator.registry.data.bytes","type":"keyword","description":"Original bytes written with base64 encoding."},{"field":"threat.indicator.registry.data.strings","type":"wildcard","description":"List of strings representing what was written to the registry."},{"field":"threat.indicator.registry.data.type","type":"keyword","description":"Standard registry type for encoding contents"},{"field":"threat.indicator.registry.hive","type":"keyword","description":"Abbreviated name for the hive."},{"field":"threat.indicator.registry.key","type":"keyword","description":"Hive-relative path of keys."},{"field":"threat.indicator.registry.path","type":"keyword","description":"Full path, including hive, key and value"},{"field":"threat.indicator.registry.value","type":"keyword","description":"Name of the value written."},{"field":"threat.indicator.scanner_stats","type":"long","description":"Scanner statistics"},{"field":"threat.indicator.sightings","type":"long","description":"Number of times indicator observed"},{"field":"threat.indicator.type","type":"keyword","description":"Type of indicator"},{"field":"threat.indicator.url.domain","type":"keyword","description":"Domain of the url."},{"field":"threat.indicator.url.extension","type":"keyword","description":"File extension from the request url, excluding the leading dot."},{"field":"threat.indicator.url.fragment","type":"keyword","description":"Portion of the url after the `#`."},{"field":"threat.indicator.url.full","type":"wildcard","description":"Full unparsed URL."},{"field":"threat.indicator.url.full.text","type":"match_only_text","description":"Full unparsed URL."},{"field":"threat.indicator.url.original","type":"wildcard","description":"Unmodified original url as seen in the event source."},{"field":"threat.indicator.url.original.text","type":"match_only_text","description":"Unmodified original url as seen in the event source."},{"field":"threat.indicator.url.password","type":"keyword","description":"Password of the request."},{"field":"threat.indicator.url.path","type":"wildcard","description":"Path of the request, such as \"/search\"."},{"field":"threat.indicator.url.port","type":"long","description":"Port of the request, such as 443."},{"field":"threat.indicator.url.query","type":"keyword","description":"Query string of the request."},{"field":"threat.indicator.url.registered_domain","type":"keyword","description":"The highest registered url domain, stripped of the subdomain."},{"field":"threat.indicator.url.scheme","type":"keyword","description":"Scheme of the url."},{"field":"threat.indicator.url.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"threat.indicator.url.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"threat.indicator.url.username","type":"keyword","description":"Username of the request."},{"field":"threat.indicator.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"threat.indicator.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"threat.indicator.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.indicator.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.indicator.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"threat.indicator.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"threat.indicator.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.indicator.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.indicator.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"threat.indicator.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"threat.indicator.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"threat.indicator.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"threat.indicator.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"threat.indicator.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.indicator.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"threat.indicator.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"threat.indicator.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"threat.indicator.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"threat.software.alias","type":"keyword","description":"Alias of the software"},{"field":"threat.software.id","type":"keyword","description":"ID of the software"},{"field":"threat.software.name","type":"keyword","description":"Name of the software."},{"field":"threat.software.platforms","type":"keyword","description":"Platforms of the software."},{"field":"threat.software.reference","type":"keyword","description":"Software reference URL."},{"field":"threat.software.type","type":"keyword","description":"Software type."},{"field":"threat.tactic.id","type":"keyword","description":"Threat tactic id."},{"field":"threat.tactic.name","type":"keyword","description":"Threat tactic."},{"field":"threat.tactic.reference","type":"keyword","description":"Threat tactic URL reference."},{"field":"threat.technique.id","type":"keyword","description":"Threat technique id."},{"field":"threat.technique.name","type":"keyword","description":"Threat technique name."},{"field":"threat.technique.name.text","type":"match_only_text","description":"Threat technique name."},{"field":"threat.technique.reference","type":"keyword","description":"Threat technique URL reference."},{"field":"threat.technique.subtechnique.id","type":"keyword","description":"Threat subtechnique id."},{"field":"threat.technique.subtechnique.name","type":"keyword","description":"Threat subtechnique name."},{"field":"threat.technique.subtechnique.name.text","type":"match_only_text","description":"Threat subtechnique name."},{"field":"threat.technique.subtechnique.reference","type":"keyword","description":"Threat subtechnique URL reference."},{"field":"tls.cipher","type":"keyword","description":"String indicating the cipher used during the current connection."},{"field":"tls.client.certificate","type":"keyword","description":"PEM-encoded stand-alone certificate offered by the client."},{"field":"tls.client.certificate_chain","type":"keyword","description":"Array of PEM-encoded certificates that make up the certificate chain offered by the client."},{"field":"tls.client.hash.md5","type":"keyword","description":"Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the client."},{"field":"tls.client.hash.sha1","type":"keyword","description":"Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the client."},{"field":"tls.client.hash.sha256","type":"keyword","description":"Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the client."},{"field":"tls.client.issuer","type":"keyword","description":"Distinguished name of subject of the issuer of the x.509 certificate presented by the client."},{"field":"tls.client.ja3","type":"keyword","description":"A hash that identifies clients based on how they perform an SSL/TLS handshake."},{"field":"tls.client.not_after","type":"date","description":"Date/Time indicating when client certificate is no longer considered valid."},{"field":"tls.client.not_before","type":"date","description":"Date/Time indicating when client certificate is first considered valid."},{"field":"tls.client.server_name","type":"keyword","description":"Hostname the client is trying to connect to. Also called the SNI."},{"field":"tls.client.subject","type":"keyword","description":"Distinguished name of subject of the x.509 certificate presented by the client."},{"field":"tls.client.supported_ciphers","type":"keyword","description":"Array of ciphers offered by the client during the client hello."},{"field":"tls.client.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"tls.client.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"tls.client.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"tls.client.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"tls.client.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"tls.client.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"tls.client.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"tls.client.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"tls.client.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"tls.client.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"tls.client.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"tls.client.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"tls.client.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"tls.client.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"tls.client.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"tls.client.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"tls.client.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"tls.client.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"tls.client.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"tls.client.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"tls.client.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"tls.client.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"tls.client.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"tls.client.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"tls.curve","type":"keyword","description":"String indicating the curve used for the given cipher, when applicable."},{"field":"tls.established","type":"boolean","description":"Boolean flag indicating if the TLS negotiation was successful and transitioned to an encrypted tunnel."},{"field":"tls.next_protocol","type":"keyword","description":"String indicating the protocol being tunneled."},{"field":"tls.resumed","type":"boolean","description":"Boolean flag indicating if this TLS connection was resumed from an existing TLS negotiation."},{"field":"tls.server.certificate","type":"keyword","description":"PEM-encoded stand-alone certificate offered by the server."},{"field":"tls.server.certificate_chain","type":"keyword","description":"Array of PEM-encoded certificates that make up the certificate chain offered by the server."},{"field":"tls.server.hash.md5","type":"keyword","description":"Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the server."},{"field":"tls.server.hash.sha1","type":"keyword","description":"Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the server."},{"field":"tls.server.hash.sha256","type":"keyword","description":"Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the server."},{"field":"tls.server.issuer","type":"keyword","description":"Subject of the issuer of the x.509 certificate presented by the server."},{"field":"tls.server.ja3s","type":"keyword","description":"A hash that identifies servers based on how they perform an SSL/TLS handshake."},{"field":"tls.server.not_after","type":"date","description":"Timestamp indicating when server certificate is no longer considered valid."},{"field":"tls.server.not_before","type":"date","description":"Timestamp indicating when server certificate is first considered valid."},{"field":"tls.server.subject","type":"keyword","description":"Subject of the x.509 certificate presented by the server."},{"field":"tls.server.x509.alternative_names","type":"keyword","description":"List of subject alternative names (SAN)."},{"field":"tls.server.x509.issuer.common_name","type":"keyword","description":"List of common name (CN) of issuing certificate authority."},{"field":"tls.server.x509.issuer.country","type":"keyword","description":"List of country (C) codes"},{"field":"tls.server.x509.issuer.distinguished_name","type":"keyword","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"tls.server.x509.issuer.locality","type":"keyword","description":"List of locality names (L)"},{"field":"tls.server.x509.issuer.organization","type":"keyword","description":"List of organizations (O) of issuing certificate authority."},{"field":"tls.server.x509.issuer.organizational_unit","type":"keyword","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"tls.server.x509.issuer.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"tls.server.x509.not_after","type":"date","description":"Time at which the certificate is no longer considered valid."},{"field":"tls.server.x509.not_before","type":"date","description":"Time at which the certificate is first considered valid."},{"field":"tls.server.x509.public_key_algorithm","type":"keyword","description":"Algorithm used to generate the public key."},{"field":"tls.server.x509.public_key_curve","type":"keyword","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"tls.server.x509.public_key_exponent","type":"long","description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"tls.server.x509.public_key_size","type":"long","description":"The size of the public key space in bits."},{"field":"tls.server.x509.serial_number","type":"keyword","description":"Unique serial number issued by the certificate authority."},{"field":"tls.server.x509.signature_algorithm","type":"keyword","description":"Identifier for certificate signature algorithm."},{"field":"tls.server.x509.subject.common_name","type":"keyword","description":"List of common names (CN) of subject."},{"field":"tls.server.x509.subject.country","type":"keyword","description":"List of country (C) code"},{"field":"tls.server.x509.subject.distinguished_name","type":"keyword","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"tls.server.x509.subject.locality","type":"keyword","description":"List of locality names (L)"},{"field":"tls.server.x509.subject.organization","type":"keyword","description":"List of organizations (O) of subject."},{"field":"tls.server.x509.subject.organizational_unit","type":"keyword","description":"List of organizational units (OU) of subject."},{"field":"tls.server.x509.subject.state_or_province","type":"keyword","description":"List of state or province names (ST, S, or P)"},{"field":"tls.server.x509.version_number","type":"keyword","description":"Version of x509 format."},{"field":"tls.version","type":"keyword","description":"Numeric part of the version parsed from the original string."},{"field":"tls.version_protocol","type":"keyword","description":"Normalized lowercase protocol name parsed from original string."},{"field":"trace.id","type":"keyword","description":"Unique identifier of the trace."},{"field":"transaction.id","type":"keyword","description":"Unique identifier of the transaction within the scope of its trace."},{"field":"url.domain","type":"keyword","description":"Domain of the url."},{"field":"url.extension","type":"keyword","description":"File extension from the request url, excluding the leading dot."},{"field":"url.fragment","type":"keyword","description":"Portion of the url after the `#`."},{"field":"url.full","type":"wildcard","description":"Full unparsed URL."},{"field":"url.full.text","type":"match_only_text","description":"Full unparsed URL."},{"field":"url.original","type":"wildcard","description":"Unmodified original url as seen in the event source."},{"field":"url.original.text","type":"match_only_text","description":"Unmodified original url as seen in the event source."},{"field":"url.password","type":"keyword","description":"Password of the request."},{"field":"url.path","type":"wildcard","description":"Path of the request, such as \"/search\"."},{"field":"url.port","type":"long","description":"Port of the request, such as 443."},{"field":"url.query","type":"keyword","description":"Query string of the request."},{"field":"url.registered_domain","type":"keyword","description":"The highest registered url domain, stripped of the subdomain."},{"field":"url.scheme","type":"keyword","description":"Scheme of the url."},{"field":"url.subdomain","type":"keyword","description":"The subdomain of the domain."},{"field":"url.top_level_domain","type":"keyword","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"url.username","type":"keyword","description":"Username of the request."},{"field":"user.changes.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"user.changes.email","type":"keyword","description":"User email address."},{"field":"user.changes.full_name","type":"keyword","description":"User's full name, if available."},{"field":"user.changes.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"user.changes.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"user.changes.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"user.changes.group.name","type":"keyword","description":"Name of the group."},{"field":"user.changes.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.changes.id","type":"keyword","description":"Unique identifier of the user."},{"field":"user.changes.name","type":"keyword","description":"Short name or login of the user."},{"field":"user.changes.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"user.changes.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"user.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"user.effective.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"user.effective.email","type":"keyword","description":"User email address."},{"field":"user.effective.full_name","type":"keyword","description":"User's full name, if available."},{"field":"user.effective.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"user.effective.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"user.effective.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"user.effective.group.name","type":"keyword","description":"Name of the group."},{"field":"user.effective.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.effective.id","type":"keyword","description":"Unique identifier of the user."},{"field":"user.effective.name","type":"keyword","description":"Short name or login of the user."},{"field":"user.effective.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"user.effective.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"user.email","type":"keyword","description":"User email address."},{"field":"user.full_name","type":"keyword","description":"User's full name, if available."},{"field":"user.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"user.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"user.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"user.group.name","type":"keyword","description":"Name of the group."},{"field":"user.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.id","type":"keyword","description":"Unique identifier of the user."},{"field":"user.name","type":"keyword","description":"Short name or login of the user."},{"field":"user.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"user.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"user.target.domain","type":"keyword","description":"Name of the directory the user is a member of."},{"field":"user.target.email","type":"keyword","description":"User email address."},{"field":"user.target.full_name","type":"keyword","description":"User's full name, if available."},{"field":"user.target.full_name.text","type":"match_only_text","description":"User's full name, if available."},{"field":"user.target.group.domain","type":"keyword","description":"Name of the directory the group is a member of."},{"field":"user.target.group.id","type":"keyword","description":"Unique identifier for the group on the system/platform."},{"field":"user.target.group.name","type":"keyword","description":"Name of the group."},{"field":"user.target.hash","type":"keyword","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.target.id","type":"keyword","description":"Unique identifier of the user."},{"field":"user.target.name","type":"keyword","description":"Short name or login of the user."},{"field":"user.target.name.text","type":"match_only_text","description":"Short name or login of the user."},{"field":"user.target.roles","type":"keyword","description":"Array of user roles at the time of the event."},{"field":"user_agent.device.name","type":"keyword","description":"Name of the device."},{"field":"user_agent.name","type":"keyword","description":"Name of the user agent."},{"field":"user_agent.original","type":"keyword","description":"Unparsed user_agent string."},{"field":"user_agent.original.text","type":"match_only_text","description":"Unparsed user_agent string."},{"field":"user_agent.os.family","type":"keyword","description":"OS family (such as redhat, debian, freebsd, windows)."},{"field":"user_agent.os.full","type":"keyword","description":"Operating system name, including the version or code name."},{"field":"user_agent.os.full.text","type":"match_only_text","description":"Operating system name, including the version or code name."},{"field":"user_agent.os.kernel","type":"keyword","description":"Operating system kernel version as a raw string."},{"field":"user_agent.os.name","type":"keyword","description":"Operating system name, without the version."},{"field":"user_agent.os.name.text","type":"match_only_text","description":"Operating system name, without the version."},{"field":"user_agent.os.platform","type":"keyword","description":"Operating system platform (such centos, ubuntu, windows)."},{"field":"user_agent.os.type","type":"keyword","description":"Which commercial OS family (one of: linux, macos, unix or windows)."},{"field":"user_agent.os.version","type":"keyword","description":"Operating system version as a raw string."},{"field":"user_agent.version","type":"keyword","description":"Version of the user agent."},{"field":"vulnerability.category","type":"keyword","description":"Category of a vulnerability."},{"field":"vulnerability.classification","type":"keyword","description":"Classification of the vulnerability."},{"field":"vulnerability.description","type":"keyword","description":"Description of the vulnerability."},{"field":"vulnerability.description.text","type":"match_only_text","description":"Description of the vulnerability."},{"field":"vulnerability.enumeration","type":"keyword","description":"Identifier of the vulnerability."},{"field":"vulnerability.id","type":"keyword","description":"ID of the vulnerability."},{"field":"vulnerability.reference","type":"keyword","description":"Reference of the vulnerability."},{"field":"vulnerability.report_id","type":"keyword","description":"Scan identification number."},{"field":"vulnerability.scanner.vendor","type":"keyword","description":"Name of the scanner vendor."},{"field":"vulnerability.score.base","type":"float","description":"Vulnerability Base score."},{"field":"vulnerability.score.environmental","type":"float","description":"Vulnerability Environmental score."},{"field":"vulnerability.score.temporal","type":"float","description":"Vulnerability Temporal score."},{"field":"vulnerability.score.version","type":"keyword","description":"CVSS version."},{"field":"vulnerability.severity","type":"keyword","description":"Severity of the vulnerability."}] \ No newline at end of file +[{"field":"labels","type":"object","normalization":"","example":{"application":"foo-bar","env":"production"},"description":"Custom key/value pairs."},{"field":"message","type":"match_only_text","normalization":"","example":"Hello World","description":"Log message optimized for viewing in a log viewer."},{"field":"tags","type":"keyword","normalization":"array","example":["production","env2"],"description":"List of keywords used to tag each event."},{"field":"agent.build.original","type":"keyword","normalization":"","example":"metricbeat version 7.6.0 (amd64), libbeat 7.6.0 [6a23e8f8f30f5001ba344e4e54d8d9cb82cb107c built 2020-02-05 23:10:10 +0000 UTC]","description":"Extended build information for the agent."},{"field":"client.address","type":"keyword","normalization":"","example":"","description":"Client network address."},{"field":"client.as.number","type":"long","normalization":"","example":15169,"description":"Unique number allocated to the autonomous system."},{"field":"client.as.organization.name","type":"keyword","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"client.as.organization.name.text","type":"match_only_text","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"client.bytes","type":"long","normalization":"","example":184,"description":"Bytes sent from the client to the server."},{"field":"client.domain","type":"keyword","normalization":"","example":"","description":"Client domain."},{"field":"client.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"client.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"client.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"client.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"client.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"client.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"client.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"client.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"client.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"client.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"client.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"client.ip","type":"ip","normalization":"","example":"","description":"IP address of the client."},{"field":"client.mac","type":"keyword","normalization":"","example":"00-00-5E-00-53-23","description":"MAC address of the client."},{"field":"client.nat.ip","type":"ip","normalization":"","example":"","description":"Client NAT ip address"},{"field":"client.nat.port","type":"long","normalization":"","example":"","description":"Client NAT port"},{"field":"client.packets","type":"long","normalization":"","example":12,"description":"Packets sent from the client to the server."},{"field":"client.port","type":"long","normalization":"","example":"","description":"Port of the client."},{"field":"client.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered client domain, stripped of the subdomain."},{"field":"client.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"client.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"client.user.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"client.user.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"client.user.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"client.user.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"client.user.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"client.user.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"client.user.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"client.user.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"client.user.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"client.user.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"client.user.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"client.user.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"cloud.account.id","type":"keyword","normalization":"","example":666777888999,"description":"The cloud account or organization id."},{"field":"cloud.account.name","type":"keyword","normalization":"","example":"elastic-dev","description":"The cloud account name."},{"field":"cloud.availability_zone","type":"keyword","normalization":"","example":"us-east-1c","description":"Availability zone in which this host, resource, or service is located."},{"field":"cloud.instance.id","type":"keyword","normalization":"","example":"i-1234567890abcdef0","description":"Instance ID of the host machine."},{"field":"cloud.instance.name","type":"keyword","normalization":"","example":"","description":"Instance name of the host machine."},{"field":"cloud.machine.type","type":"keyword","normalization":"","example":"t2.medium","description":"Machine type of the host machine."},{"field":"cloud.project.id","type":"keyword","normalization":"","example":"my-project","description":"The cloud project id."},{"field":"cloud.project.name","type":"keyword","normalization":"","example":"my project","description":"The cloud project name."},{"field":"cloud.provider","type":"keyword","normalization":"","example":"aws","description":"Name of the cloud provider."},{"field":"cloud.region","type":"keyword","normalization":"","example":"us-east-1","description":"Region in which this host, resource, or service is located."},{"field":"cloud.service.name","type":"keyword","normalization":"","example":"lambda","description":"The cloud service name."},{"field":"container.id","type":"keyword","normalization":"","example":"","description":"Unique container id."},{"field":"container.image.name","type":"keyword","normalization":"","example":"","description":"Name of the image the container was built on."},{"field":"container.image.tag","type":"keyword","normalization":"array","example":"","description":"Container image tags."},{"field":"container.labels","type":"object","normalization":"","example":"","description":"Image labels."},{"field":"container.name","type":"keyword","normalization":"","example":"","description":"Container name."},{"field":"container.runtime","type":"keyword","normalization":"","example":"docker","description":"Runtime managing this container."},{"field":"data_stream.dataset","type":"constant_keyword","normalization":"","example":"nginx.access","description":"The field can contain anything that makes sense to signify the source of the data."},{"field":"data_stream.namespace","type":"constant_keyword","normalization":"","example":"production","description":"A user defined namespace. Namespaces are useful to allow grouping of data."},{"field":"data_stream.type","type":"constant_keyword","normalization":"","example":"logs","description":"An overarching type for the data stream."},{"field":"destination.address","type":"keyword","normalization":"","example":"","description":"Destination network address."},{"field":"destination.as.number","type":"long","normalization":"","example":15169,"description":"Unique number allocated to the autonomous system."},{"field":"destination.as.organization.name","type":"keyword","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"destination.as.organization.name.text","type":"match_only_text","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"destination.bytes","type":"long","normalization":"","example":184,"description":"Bytes sent from the destination to the source."},{"field":"destination.domain","type":"keyword","normalization":"","example":"","description":"Destination domain."},{"field":"destination.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"destination.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"destination.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"destination.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"destination.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"destination.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"destination.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"destination.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"destination.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"destination.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"destination.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"destination.ip","type":"ip","normalization":"","example":"","description":"IP address of the destination."},{"field":"destination.mac","type":"keyword","normalization":"","example":"00-00-5E-00-53-23","description":"MAC address of the destination."},{"field":"destination.nat.ip","type":"ip","normalization":"","example":"","description":"Destination NAT ip"},{"field":"destination.nat.port","type":"long","normalization":"","example":"","description":"Destination NAT Port"},{"field":"destination.packets","type":"long","normalization":"","example":12,"description":"Packets sent from the destination to the source."},{"field":"destination.port","type":"long","normalization":"","example":"","description":"Port of the destination."},{"field":"destination.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered destination domain, stripped of the subdomain."},{"field":"destination.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"destination.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"destination.user.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"destination.user.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"destination.user.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"destination.user.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"destination.user.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"destination.user.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"destination.user.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"destination.user.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"destination.user.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"destination.user.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"destination.user.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"destination.user.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"dll.code_signature.digest_algorithm","type":"keyword","normalization":"","example":"sha256","description":"Hashing algorithm used to sign the process."},{"field":"dll.code_signature.exists","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if a signature is present."},{"field":"dll.code_signature.signing_id","type":"keyword","normalization":"","example":"com.apple.xpc.proxy","description":"The identifier used to sign the process."},{"field":"dll.code_signature.status","type":"keyword","normalization":"","example":"ERROR_UNTRUSTED_ROOT","description":"Additional information about the certificate status."},{"field":"dll.code_signature.subject_name","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Subject name of the code signer"},{"field":"dll.code_signature.team_id","type":"keyword","normalization":"","example":"EQHXZ8M8AV","description":"The team identifier used to sign the process."},{"field":"dll.code_signature.timestamp","type":"date","normalization":"","example":"2021-01-01T12:10:30Z","description":"When the signature was generated and signed."},{"field":"dll.code_signature.trusted","type":"boolean","normalization":"","example":true,"description":"Stores the trust status of the certificate chain."},{"field":"dll.code_signature.valid","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"dll.hash.md5","type":"keyword","normalization":"","example":"","description":"MD5 hash."},{"field":"dll.hash.sha1","type":"keyword","normalization":"","example":"","description":"SHA1 hash."},{"field":"dll.hash.sha256","type":"keyword","normalization":"","example":"","description":"SHA256 hash."},{"field":"dll.hash.sha512","type":"keyword","normalization":"","example":"","description":"SHA512 hash."},{"field":"dll.hash.ssdeep","type":"keyword","normalization":"","example":"","description":"SSDEEP hash."},{"field":"dll.name","type":"keyword","normalization":"","example":"kernel32.dll","description":"Name of the library."},{"field":"dll.path","type":"keyword","normalization":"","example":"C:\\Windows\\System32\\kernel32.dll","description":"Full file path of the library."},{"field":"dll.pe.architecture","type":"keyword","normalization":"","example":"x64","description":"CPU architecture target for the file."},{"field":"dll.pe.company","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Internal company name of the file, provided at compile-time."},{"field":"dll.pe.description","type":"keyword","normalization":"","example":"Paint","description":"Internal description of the file, provided at compile-time."},{"field":"dll.pe.file_version","type":"keyword","normalization":"","example":"6.3.9600.17415","description":"Process name."},{"field":"dll.pe.imphash","type":"keyword","normalization":"","example":"0c6803c4e922103c4dca5963aad36ddf","description":"A hash of the imports in a PE file."},{"field":"dll.pe.original_file_name","type":"keyword","normalization":"","example":"MSPAINT.EXE","description":"Internal name of the file, provided at compile-time."},{"field":"dll.pe.product","type":"keyword","normalization":"","example":"Microsoft® Windows® Operating System","description":"Internal product name of the file, provided at compile-time."},{"field":"dns.answers","type":"object","normalization":"array","example":"","description":"Array of DNS answers."},{"field":"dns.answers.class","type":"keyword","normalization":"","example":"IN","description":"The class of DNS data contained in this resource record."},{"field":"dns.answers.data","type":"keyword","normalization":"","example":"10.10.10.10","description":"The data describing the resource."},{"field":"dns.answers.name","type":"keyword","normalization":"","example":"www.example.com","description":"The domain name to which this resource record pertains."},{"field":"dns.answers.ttl","type":"long","normalization":"","example":180,"description":"The time interval in seconds that this resource record may be cached before it should be discarded."},{"field":"dns.answers.type","type":"keyword","normalization":"","example":"CNAME","description":"The type of data contained in this resource record."},{"field":"dns.header_flags","type":"keyword","normalization":"array","example":["RD","RA"],"description":"Array of DNS header flags."},{"field":"dns.id","type":"keyword","normalization":"","example":62111,"description":"The DNS packet identifier assigned by the program that generated the query. The identifier is copied to the response."},{"field":"dns.op_code","type":"keyword","normalization":"","example":"QUERY","description":"The DNS operation code that specifies the kind of query in the message."},{"field":"dns.question.class","type":"keyword","normalization":"","example":"IN","description":"The class of records being queried."},{"field":"dns.question.name","type":"keyword","normalization":"","example":"www.example.com","description":"The name being queried."},{"field":"dns.question.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered domain, stripped of the subdomain."},{"field":"dns.question.subdomain","type":"keyword","normalization":"","example":"www","description":"The subdomain of the domain."},{"field":"dns.question.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"dns.question.type","type":"keyword","normalization":"","example":"AAAA","description":"The type of record being queried."},{"field":"dns.resolved_ip","type":"ip","normalization":"array","example":["10.10.10.10","10.10.10.11"],"description":"Array containing all IPs seen in answers.data"},{"field":"dns.response_code","type":"keyword","normalization":"","example":"NOERROR","description":"The DNS response code."},{"field":"dns.type","type":"keyword","normalization":"","example":"answer","description":"The type of DNS event captured, query or answer."},{"field":"error.code","type":"keyword","normalization":"","example":"","description":"Error code describing the error."},{"field":"error.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the error."},{"field":"error.message","type":"match_only_text","normalization":"","example":"","description":"Error message."},{"field":"error.stack_trace","type":"wildcard","normalization":"","example":"","description":"The stack trace of this error in plain text."},{"field":"error.stack_trace.text","type":"match_only_text","normalization":"","example":"","description":"The stack trace of this error in plain text."},{"field":"error.type","type":"keyword","normalization":"","example":"java.lang.NullPointerException","description":"The type of the error, for example the class name of the exception."},{"field":"event.action","type":"keyword","normalization":"","example":"user-password-change","description":"The action captured by the event."},{"field":"event.category","type":"keyword","normalization":"array","example":"authentication","description":"Event category. The second categorization field in the hierarchy."},{"field":"event.code","type":"keyword","normalization":"","example":4648,"description":"Identification code for this event."},{"field":"event.created","type":"date","normalization":"","example":"2016-05-23T08:05:34.857Z","description":"Time when the event was first read by an agent or by your pipeline."},{"field":"event.dataset","type":"keyword","normalization":"","example":"apache.access","description":"Name of the dataset."},{"field":"event.duration","type":"long","normalization":"","example":"","description":"Duration of the event in nanoseconds."},{"field":"event.end","type":"date","normalization":"","example":"","description":"event.end contains the date when the event ended or when the activity was last observed."},{"field":"event.hash","type":"keyword","normalization":"","example":"123456789012345678901234567890ABCD","description":"Hash (perhaps logstash fingerprint) of raw field to be able to demonstrate log integrity."},{"field":"event.id","type":"keyword","normalization":"","example":"8a4f500d","description":"Unique ID to describe the event."},{"field":"event.kind","type":"keyword","normalization":"","example":"alert","description":"The kind of the event. The highest categorization field in the hierarchy."},{"field":"event.original","type":"keyword","normalization":"","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","description":"Raw text message of entire event."},{"field":"event.outcome","type":"keyword","normalization":"","example":"success","description":"The outcome of the event. The lowest level categorization field in the hierarchy."},{"field":"event.provider","type":"keyword","normalization":"","example":"kernel","description":"Source of the event."},{"field":"event.reason","type":"keyword","normalization":"","example":"Terminated an unexpected process","description":"Reason why this event happened, according to the source"},{"field":"event.reference","type":"keyword","normalization":"","example":"https://system.example.com/event/#0001234","description":"Event reference URL"},{"field":"event.risk_score","type":"float","normalization":"","example":"","description":"Risk score or priority of the event (e.g. security solutions). Use your system's original value here."},{"field":"event.risk_score_norm","type":"float","normalization":"","example":"","description":"Normalized risk score or priority of the event (0-100)."},{"field":"event.sequence","type":"long","normalization":"","example":"","description":"Sequence number of the event."},{"field":"event.severity","type":"long","normalization":"","example":7,"description":"Numeric severity of the event."},{"field":"event.start","type":"date","normalization":"","example":"","description":"event.start contains the date when the event started or when the activity was first observed."},{"field":"event.timezone","type":"keyword","normalization":"","example":"","description":"Event time zone."},{"field":"event.type","type":"keyword","normalization":"array","example":"","description":"Event type. The third categorization field in the hierarchy."},{"field":"event.url","type":"keyword","normalization":"","example":"https://mysystem.example.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe","description":"Event investigation URL"},{"field":"file.accessed","type":"date","normalization":"","example":"","description":"Last time the file was accessed."},{"field":"file.attributes","type":"keyword","normalization":"array","example":["readonly","system"],"description":"Array of file attributes."},{"field":"file.code_signature.digest_algorithm","type":"keyword","normalization":"","example":"sha256","description":"Hashing algorithm used to sign the process."},{"field":"file.code_signature.exists","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if a signature is present."},{"field":"file.code_signature.signing_id","type":"keyword","normalization":"","example":"com.apple.xpc.proxy","description":"The identifier used to sign the process."},{"field":"file.code_signature.status","type":"keyword","normalization":"","example":"ERROR_UNTRUSTED_ROOT","description":"Additional information about the certificate status."},{"field":"file.code_signature.subject_name","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Subject name of the code signer"},{"field":"file.code_signature.team_id","type":"keyword","normalization":"","example":"EQHXZ8M8AV","description":"The team identifier used to sign the process."},{"field":"file.code_signature.timestamp","type":"date","normalization":"","example":"2021-01-01T12:10:30Z","description":"When the signature was generated and signed."},{"field":"file.code_signature.trusted","type":"boolean","normalization":"","example":true,"description":"Stores the trust status of the certificate chain."},{"field":"file.code_signature.valid","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"file.created","type":"date","normalization":"","example":"","description":"File creation time."},{"field":"file.ctime","type":"date","normalization":"","example":"","description":"Last time the file attributes or metadata changed."},{"field":"file.device","type":"keyword","normalization":"","example":"sda","description":"Device that is the source of the file."},{"field":"file.directory","type":"keyword","normalization":"","example":"/home/alice","description":"Directory where the file is located."},{"field":"file.drive_letter","type":"keyword","normalization":"","example":"C","description":"Drive letter where the file is located."},{"field":"file.elf.architecture","type":"keyword","normalization":"","example":"x86-64","description":"Machine architecture of the ELF file."},{"field":"file.elf.byte_order","type":"keyword","normalization":"","example":"Little Endian","description":"Byte sequence of ELF file."},{"field":"file.elf.cpu_type","type":"keyword","normalization":"","example":"Intel","description":"CPU type of the ELF file."},{"field":"file.elf.creation_date","type":"date","normalization":"","example":"","description":"Build or compile date."},{"field":"file.elf.exports","type":"flattened","normalization":"array","example":"","description":"List of exported element names and types."},{"field":"file.elf.header.abi_version","type":"keyword","normalization":"","example":"","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"file.elf.header.class","type":"keyword","normalization":"","example":"","description":"Header class of the ELF file."},{"field":"file.elf.header.data","type":"keyword","normalization":"","example":"","description":"Data table of the ELF header."},{"field":"file.elf.header.entrypoint","type":"long","normalization":"","example":"","description":"Header entrypoint of the ELF file."},{"field":"file.elf.header.object_version","type":"keyword","normalization":"","example":"","description":"0x1\" for original ELF files."},{"field":"file.elf.header.os_abi","type":"keyword","normalization":"","example":"","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"file.elf.header.type","type":"keyword","normalization":"","example":"","description":"Header type of the ELF file."},{"field":"file.elf.header.version","type":"keyword","normalization":"","example":"","description":"Version of the ELF header."},{"field":"file.elf.imports","type":"flattened","normalization":"array","example":"","description":"List of imported element names and types."},{"field":"file.elf.sections","type":"nested","normalization":"array","example":"","description":"Section information of the ELF file."},{"field":"file.elf.sections.chi2","type":"long","normalization":"","example":"","description":"Chi-square probability distribution of the section."},{"field":"file.elf.sections.entropy","type":"long","normalization":"","example":"","description":"Shannon entropy calculation from the section."},{"field":"file.elf.sections.flags","type":"keyword","normalization":"","example":"","description":"ELF Section List flags."},{"field":"file.elf.sections.name","type":"keyword","normalization":"","example":"","description":"ELF Section List name."},{"field":"file.elf.sections.physical_offset","type":"keyword","normalization":"","example":"","description":"ELF Section List offset."},{"field":"file.elf.sections.physical_size","type":"long","normalization":"","example":"","description":"ELF Section List physical size."},{"field":"file.elf.sections.type","type":"keyword","normalization":"","example":"","description":"ELF Section List type."},{"field":"file.elf.sections.virtual_address","type":"long","normalization":"","example":"","description":"ELF Section List virtual address."},{"field":"file.elf.sections.virtual_size","type":"long","normalization":"","example":"","description":"ELF Section List virtual size."},{"field":"file.elf.segments","type":"nested","normalization":"array","example":"","description":"ELF object segment list."},{"field":"file.elf.segments.sections","type":"keyword","normalization":"","example":"","description":"ELF object segment sections."},{"field":"file.elf.segments.type","type":"keyword","normalization":"","example":"","description":"ELF object segment type."},{"field":"file.elf.shared_libraries","type":"keyword","normalization":"array","example":"","description":"List of shared libraries used by this ELF object."},{"field":"file.elf.telfhash","type":"keyword","normalization":"","example":"","description":"telfhash hash for ELF file."},{"field":"file.extension","type":"keyword","normalization":"","example":"png","description":"File extension, excluding the leading dot."},{"field":"file.fork_name","type":"keyword","normalization":"","example":"Zone.Identifer","description":"A fork is additional data associated with a filesystem object."},{"field":"file.gid","type":"keyword","normalization":"","example":1001,"description":"Primary group ID (GID) of the file."},{"field":"file.group","type":"keyword","normalization":"","example":"alice","description":"Primary group name of the file."},{"field":"file.hash.md5","type":"keyword","normalization":"","example":"","description":"MD5 hash."},{"field":"file.hash.sha1","type":"keyword","normalization":"","example":"","description":"SHA1 hash."},{"field":"file.hash.sha256","type":"keyword","normalization":"","example":"","description":"SHA256 hash."},{"field":"file.hash.sha512","type":"keyword","normalization":"","example":"","description":"SHA512 hash."},{"field":"file.hash.ssdeep","type":"keyword","normalization":"","example":"","description":"SSDEEP hash."},{"field":"file.inode","type":"keyword","normalization":"","example":256383,"description":"Inode representing the file in the filesystem."},{"field":"file.mime_type","type":"keyword","normalization":"","example":"","description":"Media type of file, document, or arrangement of bytes."},{"field":"file.mode","type":"keyword","normalization":"","example":"0640","description":"Mode of the file in octal representation."},{"field":"file.mtime","type":"date","normalization":"","example":"","description":"Last time the file content was modified."},{"field":"file.name","type":"keyword","normalization":"","example":"example.png","description":"Name of the file including the extension, without the directory."},{"field":"file.owner","type":"keyword","normalization":"","example":"alice","description":"File owner's username."},{"field":"file.path","type":"keyword","normalization":"","example":"/home/alice/example.png","description":"Full path to the file, including the file name."},{"field":"file.path.text","type":"match_only_text","normalization":"","example":"/home/alice/example.png","description":"Full path to the file, including the file name."},{"field":"file.pe.architecture","type":"keyword","normalization":"","example":"x64","description":"CPU architecture target for the file."},{"field":"file.pe.company","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Internal company name of the file, provided at compile-time."},{"field":"file.pe.description","type":"keyword","normalization":"","example":"Paint","description":"Internal description of the file, provided at compile-time."},{"field":"file.pe.file_version","type":"keyword","normalization":"","example":"6.3.9600.17415","description":"Process name."},{"field":"file.pe.imphash","type":"keyword","normalization":"","example":"0c6803c4e922103c4dca5963aad36ddf","description":"A hash of the imports in a PE file."},{"field":"file.pe.original_file_name","type":"keyword","normalization":"","example":"MSPAINT.EXE","description":"Internal name of the file, provided at compile-time."},{"field":"file.pe.product","type":"keyword","normalization":"","example":"Microsoft® Windows® Operating System","description":"Internal product name of the file, provided at compile-time."},{"field":"file.size","type":"long","normalization":"","example":16384,"description":"File size in bytes."},{"field":"file.target_path","type":"keyword","normalization":"","example":"","description":"Target path for symlinks."},{"field":"file.target_path.text","type":"match_only_text","normalization":"","example":"","description":"Target path for symlinks."},{"field":"file.type","type":"keyword","normalization":"","example":"file","description":"File type (file, dir, or symlink)."},{"field":"file.uid","type":"keyword","normalization":"","example":1001,"description":"The user ID (UID) or security identifier (SID) of the file owner."},{"field":"file.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"file.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"file.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"file.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"file.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"file.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"file.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"file.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"file.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"file.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"file.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"file.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"file.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"file.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"file.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"file.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"file.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"file.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"file.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"file.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"file.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"file.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"file.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"file.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"host.cpu.usage","type":"scaled_float","normalization":"","example":"","description":"Percent CPU used, between 0 and 1."},{"field":"host.disk.read.bytes","type":"long","normalization":"","example":"","description":"The number of bytes read by all disks."},{"field":"host.disk.write.bytes","type":"long","normalization":"","example":"","description":"The number of bytes written on all disks."},{"field":"host.domain","type":"keyword","normalization":"","example":"CONTOSO","description":"Name of the directory the group is a member of."},{"field":"host.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"host.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"host.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"host.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"host.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"host.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"host.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"host.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"host.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"host.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"host.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"host.name","type":"keyword","normalization":"","example":"","description":"Name of the host."},{"field":"host.network.egress.bytes","type":"long","normalization":"","example":"","description":"The number of bytes sent on all network interfaces."},{"field":"host.network.egress.packets","type":"long","normalization":"","example":"","description":"The number of packets sent on all network interfaces."},{"field":"host.network.ingress.bytes","type":"long","normalization":"","example":"","description":"The number of bytes received on all network interfaces."},{"field":"host.network.ingress.packets","type":"long","normalization":"","example":"","description":"The number of packets received on all network interfaces."},{"field":"host.os.full","type":"keyword","normalization":"","example":"Mac OS Mojave","description":"Operating system name, including the version or code name."},{"field":"host.os.full.text","type":"match_only_text","normalization":"","example":"Mac OS Mojave","description":"Operating system name, including the version or code name."},{"field":"host.os.name.text","type":"match_only_text","normalization":"","example":"Mac OS X","description":"Operating system name, without the version."},{"field":"host.os.platform","type":"keyword","normalization":"","example":"darwin","description":"Operating system platform (such centos, ubuntu, windows)."},{"field":"host.type","type":"keyword","normalization":"","example":"","description":"Type of host."},{"field":"host.uptime","type":"long","normalization":"","example":1325,"description":"Seconds the host has been up."},{"field":"host.user.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"host.user.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"host.user.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"host.user.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"host.user.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"host.user.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"host.user.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"host.user.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"host.user.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"host.user.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"host.user.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"host.user.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"http.request.body.bytes","type":"long","normalization":"","example":887,"description":"Size in bytes of the request body."},{"field":"http.request.body.content","type":"wildcard","normalization":"","example":"Hello world","description":"The full HTTP request body."},{"field":"http.request.body.content.text","type":"match_only_text","normalization":"","example":"Hello world","description":"The full HTTP request body."},{"field":"http.request.bytes","type":"long","normalization":"","example":1437,"description":"Total size in bytes of the request (body and headers)."},{"field":"http.request.id","type":"keyword","normalization":"","example":"123e4567-e89b-12d3-a456-426614174000","description":"HTTP request ID."},{"field":"http.request.method","type":"keyword","normalization":"","example":"GET, POST, PUT, PoST","description":"HTTP request method."},{"field":"http.request.mime_type","type":"keyword","normalization":"","example":"image/gif","description":"Mime type of the body of the request."},{"field":"http.request.referrer","type":"keyword","normalization":"","example":"https://blog.example.com/","description":"Referrer for this HTTP request."},{"field":"http.response.body.bytes","type":"long","normalization":"","example":887,"description":"Size in bytes of the response body."},{"field":"http.response.body.content","type":"wildcard","normalization":"","example":"Hello world","description":"The full HTTP response body."},{"field":"http.response.body.content.text","type":"match_only_text","normalization":"","example":"Hello world","description":"The full HTTP response body."},{"field":"http.response.bytes","type":"long","normalization":"","example":1437,"description":"Total size in bytes of the response (body and headers)."},{"field":"http.response.mime_type","type":"keyword","normalization":"","example":"image/gif","description":"Mime type of the body of the response."},{"field":"http.response.status_code","type":"long","normalization":"","example":404,"description":"HTTP response status code."},{"field":"http.version","type":"keyword","normalization":"","example":1.1,"description":"HTTP version."},{"field":"log.file.path","type":"keyword","normalization":"","example":"/var/log/fun-times.log","description":"Full path to the log file this event came from."},{"field":"log.level","type":"keyword","normalization":"","example":"error","description":"Log level of the log event."},{"field":"log.logger","type":"keyword","normalization":"","example":"org.elasticsearch.bootstrap.Bootstrap","description":"Name of the logger."},{"field":"log.origin.file.line","type":"integer","normalization":"","example":42,"description":"The line number of the file which originated the log event."},{"field":"log.origin.file.name","type":"keyword","normalization":"","example":"Bootstrap.java","description":"The code file which originated the log event."},{"field":"log.origin.function","type":"keyword","normalization":"","example":"init","description":"The function which originated the log event."},{"field":"log.original","type":"keyword","normalization":"","example":"Sep 19 08:26:10 localhost My log","description":"Deprecated original log message with light interpretation only (encoding, newlines)."},{"field":"log.syslog","type":"object","normalization":"","example":"","description":"Syslog metadata"},{"field":"log.syslog.facility.code","type":"long","normalization":"","example":23,"description":"Syslog numeric facility of the event."},{"field":"log.syslog.facility.name","type":"keyword","normalization":"","example":"local7","description":"Syslog text-based facility of the event."},{"field":"log.syslog.priority","type":"long","normalization":"","example":135,"description":"Syslog priority of the event."},{"field":"log.syslog.severity.code","type":"long","normalization":"","example":3,"description":"Syslog numeric severity of the event."},{"field":"log.syslog.severity.name","type":"keyword","normalization":"","example":"Error","description":"Syslog text-based severity of the event."},{"field":"network.application","type":"keyword","normalization":"","example":"aim","description":"Application level protocol name."},{"field":"network.bytes","type":"long","normalization":"","example":368,"description":"Total bytes transferred in both directions."},{"field":"network.community_id","type":"keyword","normalization":"","example":"1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=","description":"A hash of source and destination IPs and ports."},{"field":"network.direction","type":"keyword","normalization":"","example":"inbound","description":"Direction of the network traffic."},{"field":"network.forwarded_ip","type":"ip","normalization":"","example":"192.1.1.2","description":"Host IP address when the source IP address is the proxy."},{"field":"network.iana_number","type":"keyword","normalization":"","example":6,"description":"IANA Protocol Number."},{"field":"network.inner","type":"object","normalization":"","example":"","description":"Inner VLAN tag information"},{"field":"network.inner.vlan.id","type":"keyword","normalization":"","example":10,"description":"VLAN ID as reported by the observer."},{"field":"network.inner.vlan.name","type":"keyword","normalization":"","example":"outside","description":"Optional VLAN name as reported by the observer."},{"field":"network.name","type":"keyword","normalization":"","example":"Guest Wifi","description":"Name given by operators to sections of their network."},{"field":"network.packets","type":"long","normalization":"","example":24,"description":"Total packets transferred in both directions."},{"field":"network.protocol","type":"keyword","normalization":"","example":"http","description":"L7 Network protocol name."},{"field":"network.transport","type":"keyword","normalization":"","example":"tcp","description":"Protocol Name corresponding to the field `iana_number`."},{"field":"network.type","type":"keyword","normalization":"","example":"ipv4","description":"In the OSI Model this would be the Network Layer. ipv4, ipv6, ipsec, pim, etc"},{"field":"network.vlan.id","type":"keyword","normalization":"","example":10,"description":"VLAN ID as reported by the observer."},{"field":"network.vlan.name","type":"keyword","normalization":"","example":"outside","description":"Optional VLAN name as reported by the observer."},{"field":"observer.egress","type":"object","normalization":"","example":"","description":"Object field for egress information"},{"field":"observer.egress.interface.alias","type":"keyword","normalization":"","example":"outside","description":"Interface alias"},{"field":"observer.egress.interface.id","type":"keyword","normalization":"","example":10,"description":"Interface ID"},{"field":"observer.egress.interface.name","type":"keyword","normalization":"","example":"eth0","description":"Interface name"},{"field":"observer.egress.vlan.id","type":"keyword","normalization":"","example":10,"description":"VLAN ID as reported by the observer."},{"field":"observer.egress.vlan.name","type":"keyword","normalization":"","example":"outside","description":"Optional VLAN name as reported by the observer."},{"field":"observer.egress.zone","type":"keyword","normalization":"","example":"Public_Internet","description":"Observer Egress zone"},{"field":"observer.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"observer.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"observer.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"observer.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"observer.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"observer.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"observer.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"observer.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"observer.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"observer.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"observer.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"observer.hostname","type":"keyword","normalization":"","example":"","description":"Hostname of the observer."},{"field":"observer.ingress","type":"object","normalization":"","example":"","description":"Object field for ingress information"},{"field":"observer.ingress.interface.alias","type":"keyword","normalization":"","example":"outside","description":"Interface alias"},{"field":"observer.ingress.interface.id","type":"keyword","normalization":"","example":10,"description":"Interface ID"},{"field":"observer.ingress.interface.name","type":"keyword","normalization":"","example":"eth0","description":"Interface name"},{"field":"observer.ingress.vlan.id","type":"keyword","normalization":"","example":10,"description":"VLAN ID as reported by the observer."},{"field":"observer.ingress.vlan.name","type":"keyword","normalization":"","example":"outside","description":"Optional VLAN name as reported by the observer."},{"field":"observer.ingress.zone","type":"keyword","normalization":"","example":"DMZ","description":"Observer ingress zone"},{"field":"observer.ip","type":"ip","normalization":"array","example":"","description":"IP addresses of the observer."},{"field":"observer.mac","type":"keyword","normalization":"array","example":["00-00-5E-00-53-23","00-00-5E-00-53-24"],"description":"MAC addresses of the observer."},{"field":"observer.name","type":"keyword","normalization":"","example":"1_proxySG","description":"Custom name of the observer."},{"field":"observer.os.family","type":"keyword","normalization":"","example":"debian","description":"OS family (such as redhat, debian, freebsd, windows)."},{"field":"observer.os.full","type":"keyword","normalization":"","example":"Mac OS Mojave","description":"Operating system name, including the version or code name."},{"field":"observer.os.full.text","type":"match_only_text","normalization":"","example":"Mac OS Mojave","description":"Operating system name, including the version or code name."},{"field":"observer.os.kernel","type":"keyword","normalization":"","example":"4.4.0-112-generic","description":"Operating system kernel version as a raw string."},{"field":"observer.os.name","type":"keyword","normalization":"","example":"Mac OS X","description":"Operating system name, without the version."},{"field":"observer.os.name.text","type":"match_only_text","normalization":"","example":"Mac OS X","description":"Operating system name, without the version."},{"field":"observer.os.platform","type":"keyword","normalization":"","example":"darwin","description":"Operating system platform (such centos, ubuntu, windows)."},{"field":"observer.os.type","type":"keyword","normalization":"","example":"macos","description":"Which commercial OS family (one of: linux, macos, unix or windows)."},{"field":"observer.os.version","type":"keyword","normalization":"","example":"10.14.1","description":"Operating system version as a raw string."},{"field":"observer.product","type":"keyword","normalization":"","example":"s200","description":"The product name of the observer."},{"field":"observer.serial_number","type":"keyword","normalization":"","example":"","description":"Observer serial number."},{"field":"observer.type","type":"keyword","normalization":"","example":"firewall","description":"The type of the observer the data is coming from."},{"field":"observer.vendor","type":"keyword","normalization":"","example":"Symantec","description":"Vendor name of the observer."},{"field":"observer.version","type":"keyword","normalization":"","example":"","description":"Observer version."},{"field":"orchestrator.api_version","type":"keyword","normalization":"","example":"v1beta1","description":"API version being used to carry out the action"},{"field":"orchestrator.cluster.name","type":"keyword","normalization":"","example":"","description":"Name of the cluster."},{"field":"orchestrator.cluster.url","type":"keyword","normalization":"","example":"","description":"URL of the API used to manage the cluster."},{"field":"orchestrator.cluster.version","type":"keyword","normalization":"","example":"","description":"The version of the cluster."},{"field":"orchestrator.namespace","type":"keyword","normalization":"","example":"kube-system","description":"Namespace in which the action is taking place."},{"field":"orchestrator.organization","type":"keyword","normalization":"","example":"elastic","description":"Organization affected by the event (for multi-tenant orchestrator setups)."},{"field":"orchestrator.resource.name","type":"keyword","normalization":"","example":"test-pod-cdcws","description":"Name of the resource being acted upon."},{"field":"orchestrator.resource.type","type":"keyword","normalization":"","example":"service","description":"Type of resource being acted upon."},{"field":"orchestrator.type","type":"keyword","normalization":"","example":"kubernetes","description":"Orchestrator cluster type (e.g. kubernetes, nomad or cloudfoundry)."},{"field":"organization.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the organization."},{"field":"organization.name","type":"keyword","normalization":"","example":"","description":"Organization name."},{"field":"organization.name.text","type":"match_only_text","normalization":"","example":"","description":"Organization name."},{"field":"package.architecture","type":"keyword","normalization":"","example":"x86_64","description":"Package architecture."},{"field":"package.build_version","type":"keyword","normalization":"","example":"36f4f7e89dd61b0988b12ee000b98966867710cd","description":"Build version information"},{"field":"package.checksum","type":"keyword","normalization":"","example":"68b329da9893e34099c7d8ad5cb9c940","description":"Checksum of the installed package for verification."},{"field":"package.description","type":"keyword","normalization":"","example":"Open source programming language to build simple/reliable/efficient software.","description":"Description of the package."},{"field":"package.install_scope","type":"keyword","normalization":"","example":"global","description":"Indicating how the package was installed, e.g. user-local, global."},{"field":"package.installed","type":"date","normalization":"","example":"","description":"Time when package was installed."},{"field":"package.license","type":"keyword","normalization":"","example":"Apache License 2.0","description":"Package license"},{"field":"package.name","type":"keyword","normalization":"","example":"go","description":"Package name"},{"field":"package.path","type":"keyword","normalization":"","example":"/usr/local/Cellar/go/1.12.9/","description":"Path where the package is installed."},{"field":"package.reference","type":"keyword","normalization":"","example":"https://golang.org","description":"Package home page or reference URL"},{"field":"package.size","type":"long","normalization":"","example":62231,"description":"Package size in bytes."},{"field":"package.type","type":"keyword","normalization":"","example":"rpm","description":"Package type"},{"field":"package.version","type":"keyword","normalization":"","example":"1.12.9","description":"Package version"},{"field":"process.args","type":"keyword","normalization":"array","example":["/usr/bin/ssh","-l","user","10.0.0.16"],"description":"Array of process arguments."},{"field":"process.args_count","type":"long","normalization":"","example":4,"description":"Length of the process.args array."},{"field":"process.code_signature.digest_algorithm","type":"keyword","normalization":"","example":"sha256","description":"Hashing algorithm used to sign the process."},{"field":"process.code_signature.exists","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if a signature is present."},{"field":"process.code_signature.signing_id","type":"keyword","normalization":"","example":"com.apple.xpc.proxy","description":"The identifier used to sign the process."},{"field":"process.code_signature.status","type":"keyword","normalization":"","example":"ERROR_UNTRUSTED_ROOT","description":"Additional information about the certificate status."},{"field":"process.code_signature.subject_name","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Subject name of the code signer"},{"field":"process.code_signature.team_id","type":"keyword","normalization":"","example":"EQHXZ8M8AV","description":"The team identifier used to sign the process."},{"field":"process.code_signature.timestamp","type":"date","normalization":"","example":"2021-01-01T12:10:30Z","description":"When the signature was generated and signed."},{"field":"process.code_signature.trusted","type":"boolean","normalization":"","example":true,"description":"Stores the trust status of the certificate chain."},{"field":"process.code_signature.valid","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"process.command_line","type":"wildcard","normalization":"","example":"/usr/bin/ssh -l user 10.0.0.16","description":"Full command line that started the process."},{"field":"process.command_line.text","type":"match_only_text","normalization":"","example":"/usr/bin/ssh -l user 10.0.0.16","description":"Full command line that started the process."},{"field":"process.elf.architecture","type":"keyword","normalization":"","example":"x86-64","description":"Machine architecture of the ELF file."},{"field":"process.elf.byte_order","type":"keyword","normalization":"","example":"Little Endian","description":"Byte sequence of ELF file."},{"field":"process.elf.cpu_type","type":"keyword","normalization":"","example":"Intel","description":"CPU type of the ELF file."},{"field":"process.elf.creation_date","type":"date","normalization":"","example":"","description":"Build or compile date."},{"field":"process.elf.exports","type":"flattened","normalization":"array","example":"","description":"List of exported element names and types."},{"field":"process.elf.header.abi_version","type":"keyword","normalization":"","example":"","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"process.elf.header.class","type":"keyword","normalization":"","example":"","description":"Header class of the ELF file."},{"field":"process.elf.header.data","type":"keyword","normalization":"","example":"","description":"Data table of the ELF header."},{"field":"process.elf.header.entrypoint","type":"long","normalization":"","example":"","description":"Header entrypoint of the ELF file."},{"field":"process.elf.header.object_version","type":"keyword","normalization":"","example":"","description":"0x1\" for original ELF files."},{"field":"process.elf.header.os_abi","type":"keyword","normalization":"","example":"","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"process.elf.header.type","type":"keyword","normalization":"","example":"","description":"Header type of the ELF file."},{"field":"process.elf.header.version","type":"keyword","normalization":"","example":"","description":"Version of the ELF header."},{"field":"process.elf.imports","type":"flattened","normalization":"array","example":"","description":"List of imported element names and types."},{"field":"process.elf.sections","type":"nested","normalization":"array","example":"","description":"Section information of the ELF file."},{"field":"process.elf.sections.chi2","type":"long","normalization":"","example":"","description":"Chi-square probability distribution of the section."},{"field":"process.elf.sections.entropy","type":"long","normalization":"","example":"","description":"Shannon entropy calculation from the section."},{"field":"process.elf.sections.flags","type":"keyword","normalization":"","example":"","description":"ELF Section List flags."},{"field":"process.elf.sections.name","type":"keyword","normalization":"","example":"","description":"ELF Section List name."},{"field":"process.elf.sections.physical_offset","type":"keyword","normalization":"","example":"","description":"ELF Section List offset."},{"field":"process.elf.sections.physical_size","type":"long","normalization":"","example":"","description":"ELF Section List physical size."},{"field":"process.elf.sections.type","type":"keyword","normalization":"","example":"","description":"ELF Section List type."},{"field":"process.elf.sections.virtual_address","type":"long","normalization":"","example":"","description":"ELF Section List virtual address."},{"field":"process.elf.sections.virtual_size","type":"long","normalization":"","example":"","description":"ELF Section List virtual size."},{"field":"process.elf.segments","type":"nested","normalization":"array","example":"","description":"ELF object segment list."},{"field":"process.elf.segments.sections","type":"keyword","normalization":"","example":"","description":"ELF object segment sections."},{"field":"process.elf.segments.type","type":"keyword","normalization":"","example":"","description":"ELF object segment type."},{"field":"process.elf.shared_libraries","type":"keyword","normalization":"array","example":"","description":"List of shared libraries used by this ELF object."},{"field":"process.elf.telfhash","type":"keyword","normalization":"","example":"","description":"telfhash hash for ELF file."},{"field":"process.end","type":"date","normalization":"","example":"2016-05-23T08:05:34.853Z","description":"The time the process ended."},{"field":"process.entity_id","type":"keyword","normalization":"","example":"c2c455d9f99375d","description":"Unique identifier for the process."},{"field":"process.executable","type":"keyword","normalization":"","example":"/usr/bin/ssh","description":"Absolute path to the process executable."},{"field":"process.executable.text","type":"match_only_text","normalization":"","example":"/usr/bin/ssh","description":"Absolute path to the process executable."},{"field":"process.exit_code","type":"long","normalization":"","example":137,"description":"The exit code of the process."},{"field":"process.hash.md5","type":"keyword","normalization":"","example":"","description":"MD5 hash."},{"field":"process.hash.sha1","type":"keyword","normalization":"","example":"","description":"SHA1 hash."},{"field":"process.hash.sha256","type":"keyword","normalization":"","example":"","description":"SHA256 hash."},{"field":"process.hash.sha512","type":"keyword","normalization":"","example":"","description":"SHA512 hash."},{"field":"process.hash.ssdeep","type":"keyword","normalization":"","example":"","description":"SSDEEP hash."},{"field":"process.name","type":"keyword","normalization":"","example":"ssh","description":"Process name."},{"field":"process.name.text","type":"match_only_text","normalization":"","example":"ssh","description":"Process name."},{"field":"process.parent.args","type":"keyword","normalization":"array","example":["/usr/bin/ssh","-l","user","10.0.0.16"],"description":"Array of process arguments."},{"field":"process.parent.args_count","type":"long","normalization":"","example":4,"description":"Length of the process.args array."},{"field":"process.parent.code_signature.digest_algorithm","type":"keyword","normalization":"","example":"sha256","description":"Hashing algorithm used to sign the process."},{"field":"process.parent.code_signature.exists","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if a signature is present."},{"field":"process.parent.code_signature.signing_id","type":"keyword","normalization":"","example":"com.apple.xpc.proxy","description":"The identifier used to sign the process."},{"field":"process.parent.code_signature.status","type":"keyword","normalization":"","example":"ERROR_UNTRUSTED_ROOT","description":"Additional information about the certificate status."},{"field":"process.parent.code_signature.subject_name","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Subject name of the code signer"},{"field":"process.parent.code_signature.team_id","type":"keyword","normalization":"","example":"EQHXZ8M8AV","description":"The team identifier used to sign the process."},{"field":"process.parent.code_signature.timestamp","type":"date","normalization":"","example":"2021-01-01T12:10:30Z","description":"When the signature was generated and signed."},{"field":"process.parent.code_signature.trusted","type":"boolean","normalization":"","example":true,"description":"Stores the trust status of the certificate chain."},{"field":"process.parent.code_signature.valid","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"process.parent.command_line","type":"wildcard","normalization":"","example":"/usr/bin/ssh -l user 10.0.0.16","description":"Full command line that started the process."},{"field":"process.parent.command_line.text","type":"match_only_text","normalization":"","example":"/usr/bin/ssh -l user 10.0.0.16","description":"Full command line that started the process."},{"field":"process.parent.elf.architecture","type":"keyword","normalization":"","example":"x86-64","description":"Machine architecture of the ELF file."},{"field":"process.parent.elf.byte_order","type":"keyword","normalization":"","example":"Little Endian","description":"Byte sequence of ELF file."},{"field":"process.parent.elf.cpu_type","type":"keyword","normalization":"","example":"Intel","description":"CPU type of the ELF file."},{"field":"process.parent.elf.creation_date","type":"date","normalization":"","example":"","description":"Build or compile date."},{"field":"process.parent.elf.exports","type":"flattened","normalization":"array","example":"","description":"List of exported element names and types."},{"field":"process.parent.elf.header.abi_version","type":"keyword","normalization":"","example":"","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"process.parent.elf.header.class","type":"keyword","normalization":"","example":"","description":"Header class of the ELF file."},{"field":"process.parent.elf.header.data","type":"keyword","normalization":"","example":"","description":"Data table of the ELF header."},{"field":"process.parent.elf.header.entrypoint","type":"long","normalization":"","example":"","description":"Header entrypoint of the ELF file."},{"field":"process.parent.elf.header.object_version","type":"keyword","normalization":"","example":"","description":"0x1\" for original ELF files."},{"field":"process.parent.elf.header.os_abi","type":"keyword","normalization":"","example":"","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"process.parent.elf.header.type","type":"keyword","normalization":"","example":"","description":"Header type of the ELF file."},{"field":"process.parent.elf.header.version","type":"keyword","normalization":"","example":"","description":"Version of the ELF header."},{"field":"process.parent.elf.imports","type":"flattened","normalization":"array","example":"","description":"List of imported element names and types."},{"field":"process.parent.elf.sections","type":"nested","normalization":"array","example":"","description":"Section information of the ELF file."},{"field":"process.parent.elf.sections.chi2","type":"long","normalization":"","example":"","description":"Chi-square probability distribution of the section."},{"field":"process.parent.elf.sections.entropy","type":"long","normalization":"","example":"","description":"Shannon entropy calculation from the section."},{"field":"process.parent.elf.sections.flags","type":"keyword","normalization":"","example":"","description":"ELF Section List flags."},{"field":"process.parent.elf.sections.name","type":"keyword","normalization":"","example":"","description":"ELF Section List name."},{"field":"process.parent.elf.sections.physical_offset","type":"keyword","normalization":"","example":"","description":"ELF Section List offset."},{"field":"process.parent.elf.sections.physical_size","type":"long","normalization":"","example":"","description":"ELF Section List physical size."},{"field":"process.parent.elf.sections.type","type":"keyword","normalization":"","example":"","description":"ELF Section List type."},{"field":"process.parent.elf.sections.virtual_address","type":"long","normalization":"","example":"","description":"ELF Section List virtual address."},{"field":"process.parent.elf.sections.virtual_size","type":"long","normalization":"","example":"","description":"ELF Section List virtual size."},{"field":"process.parent.elf.segments","type":"nested","normalization":"array","example":"","description":"ELF object segment list."},{"field":"process.parent.elf.segments.sections","type":"keyword","normalization":"","example":"","description":"ELF object segment sections."},{"field":"process.parent.elf.segments.type","type":"keyword","normalization":"","example":"","description":"ELF object segment type."},{"field":"process.parent.elf.shared_libraries","type":"keyword","normalization":"array","example":"","description":"List of shared libraries used by this ELF object."},{"field":"process.parent.elf.telfhash","type":"keyword","normalization":"","example":"","description":"telfhash hash for ELF file."},{"field":"process.parent.end","type":"date","normalization":"","example":"2016-05-23T08:05:34.853Z","description":"The time the process ended."},{"field":"process.parent.entity_id","type":"keyword","normalization":"","example":"c2c455d9f99375d","description":"Unique identifier for the process."},{"field":"process.parent.executable","type":"keyword","normalization":"","example":"/usr/bin/ssh","description":"Absolute path to the process executable."},{"field":"process.parent.executable.text","type":"match_only_text","normalization":"","example":"/usr/bin/ssh","description":"Absolute path to the process executable."},{"field":"process.parent.exit_code","type":"long","normalization":"","example":137,"description":"The exit code of the process."},{"field":"process.parent.hash.md5","type":"keyword","normalization":"","example":"","description":"MD5 hash."},{"field":"process.parent.hash.sha1","type":"keyword","normalization":"","example":"","description":"SHA1 hash."},{"field":"process.parent.hash.sha256","type":"keyword","normalization":"","example":"","description":"SHA256 hash."},{"field":"process.parent.hash.sha512","type":"keyword","normalization":"","example":"","description":"SHA512 hash."},{"field":"process.parent.hash.ssdeep","type":"keyword","normalization":"","example":"","description":"SSDEEP hash."},{"field":"process.parent.name","type":"keyword","normalization":"","example":"ssh","description":"Process name."},{"field":"process.parent.name.text","type":"match_only_text","normalization":"","example":"ssh","description":"Process name."},{"field":"process.parent.pe.architecture","type":"keyword","normalization":"","example":"x64","description":"CPU architecture target for the file."},{"field":"process.parent.pe.company","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Internal company name of the file, provided at compile-time."},{"field":"process.parent.pe.description","type":"keyword","normalization":"","example":"Paint","description":"Internal description of the file, provided at compile-time."},{"field":"process.parent.pe.file_version","type":"keyword","normalization":"","example":"6.3.9600.17415","description":"Process name."},{"field":"process.parent.pe.imphash","type":"keyword","normalization":"","example":"0c6803c4e922103c4dca5963aad36ddf","description":"A hash of the imports in a PE file."},{"field":"process.parent.pe.original_file_name","type":"keyword","normalization":"","example":"MSPAINT.EXE","description":"Internal name of the file, provided at compile-time."},{"field":"process.parent.pe.product","type":"keyword","normalization":"","example":"Microsoft® Windows® Operating System","description":"Internal product name of the file, provided at compile-time."},{"field":"process.parent.pgid","type":"long","normalization":"","example":"","description":"Identifier of the group of processes the process belongs to."},{"field":"process.parent.pid","type":"long","normalization":"","example":4242,"description":"Process id."},{"field":"process.parent.ppid","type":"long","normalization":"","example":4241,"description":"Parent process' pid."},{"field":"process.parent.start","type":"date","normalization":"","example":"2016-05-23T08:05:34.853Z","description":"The time the process started."},{"field":"process.parent.thread.id","type":"long","normalization":"","example":4242,"description":"Thread ID."},{"field":"process.parent.thread.name","type":"keyword","normalization":"","example":"thread-0","description":"Thread name."},{"field":"process.parent.title","type":"keyword","normalization":"","example":"","description":"Process title."},{"field":"process.parent.title.text","type":"match_only_text","normalization":"","example":"","description":"Process title."},{"field":"process.parent.uptime","type":"long","normalization":"","example":1325,"description":"Seconds the process has been up."},{"field":"process.parent.working_directory","type":"keyword","normalization":"","example":"/home/alice","description":"The working directory of the process."},{"field":"process.parent.working_directory.text","type":"match_only_text","normalization":"","example":"/home/alice","description":"The working directory of the process."},{"field":"process.pe.architecture","type":"keyword","normalization":"","example":"x64","description":"CPU architecture target for the file."},{"field":"process.pe.company","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Internal company name of the file, provided at compile-time."},{"field":"process.pe.description","type":"keyword","normalization":"","example":"Paint","description":"Internal description of the file, provided at compile-time."},{"field":"process.pe.file_version","type":"keyword","normalization":"","example":"6.3.9600.17415","description":"Process name."},{"field":"process.pe.imphash","type":"keyword","normalization":"","example":"0c6803c4e922103c4dca5963aad36ddf","description":"A hash of the imports in a PE file."},{"field":"process.pe.original_file_name","type":"keyword","normalization":"","example":"MSPAINT.EXE","description":"Internal name of the file, provided at compile-time."},{"field":"process.pe.product","type":"keyword","normalization":"","example":"Microsoft® Windows® Operating System","description":"Internal product name of the file, provided at compile-time."},{"field":"process.pgid","type":"long","normalization":"","example":"","description":"Identifier of the group of processes the process belongs to."},{"field":"process.pid","type":"long","normalization":"","example":4242,"description":"Process id."},{"field":"process.ppid","type":"long","normalization":"","example":4241,"description":"Parent process' pid."},{"field":"process.start","type":"date","normalization":"","example":"2016-05-23T08:05:34.853Z","description":"The time the process started."},{"field":"process.thread.id","type":"long","normalization":"","example":4242,"description":"Thread ID."},{"field":"process.thread.name","type":"keyword","normalization":"","example":"thread-0","description":"Thread name."},{"field":"process.title","type":"keyword","normalization":"","example":"","description":"Process title."},{"field":"process.title.text","type":"match_only_text","normalization":"","example":"","description":"Process title."},{"field":"process.uptime","type":"long","normalization":"","example":1325,"description":"Seconds the process has been up."},{"field":"process.working_directory","type":"keyword","normalization":"","example":"/home/alice","description":"The working directory of the process."},{"field":"process.working_directory.text","type":"match_only_text","normalization":"","example":"/home/alice","description":"The working directory of the process."},{"field":"registry.data.bytes","type":"keyword","normalization":"","example":"ZQBuAC0AVQBTAAAAZQBuAAAAAAA=","description":"Original bytes written with base64 encoding."},{"field":"registry.data.strings","type":"wildcard","normalization":"array","example":"[\"C:\\rta\\red_ttp\\bin\\myapp.exe\"]","description":"List of strings representing what was written to the registry."},{"field":"registry.data.type","type":"keyword","normalization":"","example":"REG_SZ","description":"Standard registry type for encoding contents"},{"field":"registry.hive","type":"keyword","normalization":"","example":"HKLM","description":"Abbreviated name for the hive."},{"field":"registry.key","type":"keyword","normalization":"","example":"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe","description":"Hive-relative path of keys."},{"field":"registry.path","type":"keyword","normalization":"","example":"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe\\Debugger","description":"Full path, including hive, key and value"},{"field":"registry.value","type":"keyword","normalization":"","example":"Debugger","description":"Name of the value written."},{"field":"related.hash","type":"keyword","normalization":"array","example":"","description":"All the hashes seen on your event."},{"field":"related.hosts","type":"keyword","normalization":"array","example":"","description":"All the host identifiers seen on your event."},{"field":"related.ip","type":"ip","normalization":"array","example":"","description":"All of the IPs seen on your event."},{"field":"related.user","type":"keyword","normalization":"array","example":"","description":"All the user names or other user identifiers seen on the event."},{"field":"rule.author","type":"keyword","normalization":"array","example":["Star-Lord"],"description":"Rule author"},{"field":"rule.category","type":"keyword","normalization":"","example":"Attempted Information Leak","description":"Rule category"},{"field":"rule.description","type":"keyword","normalization":"","example":"Block requests to public DNS over HTTPS / TLS protocols","description":"Rule description"},{"field":"rule.id","type":"keyword","normalization":"","example":101,"description":"Rule ID"},{"field":"rule.license","type":"keyword","normalization":"","example":"Apache 2.0","description":"Rule license"},{"field":"rule.name","type":"keyword","normalization":"","example":"BLOCK_DNS_over_TLS","description":"Rule name"},{"field":"rule.reference","type":"keyword","normalization":"","example":"https://en.wikipedia.org/wiki/DNS_over_TLS","description":"Rule reference URL"},{"field":"rule.ruleset","type":"keyword","normalization":"","example":"Standard_Protocol_Filters","description":"Rule ruleset"},{"field":"rule.uuid","type":"keyword","normalization":"","example":1100110011,"description":"Rule UUID"},{"field":"rule.version","type":"keyword","normalization":"","example":1.1,"description":"Rule version"},{"field":"server.address","type":"keyword","normalization":"","example":"","description":"Server network address."},{"field":"server.as.number","type":"long","normalization":"","example":15169,"description":"Unique number allocated to the autonomous system."},{"field":"server.as.organization.name","type":"keyword","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"server.as.organization.name.text","type":"match_only_text","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"server.bytes","type":"long","normalization":"","example":184,"description":"Bytes sent from the server to the client."},{"field":"server.domain","type":"keyword","normalization":"","example":"","description":"Server domain."},{"field":"server.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"server.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"server.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"server.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"server.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"server.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"server.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"server.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"server.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"server.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"server.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"server.ip","type":"ip","normalization":"","example":"","description":"IP address of the server."},{"field":"server.mac","type":"keyword","normalization":"","example":"00-00-5E-00-53-23","description":"MAC address of the server."},{"field":"server.nat.ip","type":"ip","normalization":"","example":"","description":"Server NAT ip"},{"field":"server.nat.port","type":"long","normalization":"","example":"","description":"Server NAT port"},{"field":"server.packets","type":"long","normalization":"","example":12,"description":"Packets sent from the server to the client."},{"field":"server.port","type":"long","normalization":"","example":"","description":"Port of the server."},{"field":"server.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered server domain, stripped of the subdomain."},{"field":"server.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"server.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"server.user.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"server.user.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"server.user.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"server.user.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"server.user.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"server.user.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"server.user.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"server.user.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"server.user.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"server.user.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"server.user.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"server.user.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"service.address","type":"keyword","normalization":"","example":"172.26.0.2:5432","description":"Address of this service."},{"field":"service.environment","type":"keyword","normalization":"","example":"production","description":"Environment of the service."},{"field":"service.ephemeral_id","type":"keyword","normalization":"","example":"8a4f500f","description":"Ephemeral identifier of this service."},{"field":"service.id","type":"keyword","normalization":"","example":"d37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6","description":"Unique identifier of the running service."},{"field":"service.name","type":"keyword","normalization":"","example":"elasticsearch-metrics","description":"Name of the service."},{"field":"service.node.name","type":"keyword","normalization":"","example":"instance-0000000016","description":"Name of the service node."},{"field":"service.state","type":"keyword","normalization":"","example":"","description":"Current state of the service."},{"field":"service.type","type":"keyword","normalization":"","example":"elasticsearch","description":"The type of the service."},{"field":"service.version","type":"keyword","normalization":"","example":"3.2.4","description":"Version of the service."},{"field":"source.address","type":"keyword","normalization":"","example":"","description":"Source network address."},{"field":"source.as.number","type":"long","normalization":"","example":15169,"description":"Unique number allocated to the autonomous system."},{"field":"source.as.organization.name","type":"keyword","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"source.as.organization.name.text","type":"match_only_text","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"source.bytes","type":"long","normalization":"","example":184,"description":"Bytes sent from the source to the destination."},{"field":"source.domain","type":"keyword","normalization":"","example":"","description":"Source domain."},{"field":"source.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"source.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"source.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"source.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"source.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"source.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"source.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"source.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"source.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"source.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"source.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"source.ip","type":"ip","normalization":"","example":"","description":"IP address of the source."},{"field":"source.mac","type":"keyword","normalization":"","example":"00-00-5E-00-53-23","description":"MAC address of the source."},{"field":"source.nat.ip","type":"ip","normalization":"","example":"","description":"Source NAT ip"},{"field":"source.nat.port","type":"long","normalization":"","example":"","description":"Source NAT port"},{"field":"source.packets","type":"long","normalization":"","example":12,"description":"Packets sent from the source to the destination."},{"field":"source.port","type":"long","normalization":"","example":"","description":"Port of the source."},{"field":"source.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered source domain, stripped of the subdomain."},{"field":"source.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"source.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"source.user.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"source.user.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"source.user.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"source.user.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"source.user.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"source.user.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"source.user.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"source.user.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"source.user.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"source.user.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"source.user.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"source.user.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"span.id","type":"keyword","normalization":"","example":"3ff9a8981b7ccd5a","description":"Unique identifier of the span within the scope of its trace."},{"field":"threat.enrichments","type":"nested","normalization":"array","example":"","description":"List of objects containing indicators enriching the event."},{"field":"threat.enrichments.indicator","type":"object","normalization":"","example":"","description":"Object containing indicators enriching the event."},{"field":"threat.enrichments.indicator.as.number","type":"long","normalization":"","example":15169,"description":"Unique number allocated to the autonomous system."},{"field":"threat.enrichments.indicator.as.organization.name","type":"keyword","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"threat.enrichments.indicator.as.organization.name.text","type":"match_only_text","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"threat.enrichments.indicator.confidence","type":"keyword","normalization":"","example":"High","description":"Indicator confidence rating"},{"field":"threat.enrichments.indicator.description","type":"keyword","normalization":"","example":"IP x.x.x.x was observed delivering the Angler EK.","description":"Indicator description"},{"field":"threat.enrichments.indicator.email.address","type":"keyword","normalization":"","example":"phish@example.com","description":"Indicator email address"},{"field":"threat.enrichments.indicator.file.accessed","type":"date","normalization":"","example":"","description":"Last time the file was accessed."},{"field":"threat.enrichments.indicator.file.attributes","type":"keyword","normalization":"array","example":["readonly","system"],"description":"Array of file attributes."},{"field":"threat.enrichments.indicator.file.code_signature.digest_algorithm","type":"keyword","normalization":"","example":"sha256","description":"Hashing algorithm used to sign the process."},{"field":"threat.enrichments.indicator.file.code_signature.exists","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if a signature is present."},{"field":"threat.enrichments.indicator.file.code_signature.signing_id","type":"keyword","normalization":"","example":"com.apple.xpc.proxy","description":"The identifier used to sign the process."},{"field":"threat.enrichments.indicator.file.code_signature.status","type":"keyword","normalization":"","example":"ERROR_UNTRUSTED_ROOT","description":"Additional information about the certificate status."},{"field":"threat.enrichments.indicator.file.code_signature.subject_name","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Subject name of the code signer"},{"field":"threat.enrichments.indicator.file.code_signature.team_id","type":"keyword","normalization":"","example":"EQHXZ8M8AV","description":"The team identifier used to sign the process."},{"field":"threat.enrichments.indicator.file.code_signature.timestamp","type":"date","normalization":"","example":"2021-01-01T12:10:30Z","description":"When the signature was generated and signed."},{"field":"threat.enrichments.indicator.file.code_signature.trusted","type":"boolean","normalization":"","example":true,"description":"Stores the trust status of the certificate chain."},{"field":"threat.enrichments.indicator.file.code_signature.valid","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"threat.enrichments.indicator.file.created","type":"date","normalization":"","example":"","description":"File creation time."},{"field":"threat.enrichments.indicator.file.ctime","type":"date","normalization":"","example":"","description":"Last time the file attributes or metadata changed."},{"field":"threat.enrichments.indicator.file.device","type":"keyword","normalization":"","example":"sda","description":"Device that is the source of the file."},{"field":"threat.enrichments.indicator.file.directory","type":"keyword","normalization":"","example":"/home/alice","description":"Directory where the file is located."},{"field":"threat.enrichments.indicator.file.drive_letter","type":"keyword","normalization":"","example":"C","description":"Drive letter where the file is located."},{"field":"threat.enrichments.indicator.file.elf.architecture","type":"keyword","normalization":"","example":"x86-64","description":"Machine architecture of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.byte_order","type":"keyword","normalization":"","example":"Little Endian","description":"Byte sequence of ELF file."},{"field":"threat.enrichments.indicator.file.elf.cpu_type","type":"keyword","normalization":"","example":"Intel","description":"CPU type of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.creation_date","type":"date","normalization":"","example":"","description":"Build or compile date."},{"field":"threat.enrichments.indicator.file.elf.exports","type":"flattened","normalization":"array","example":"","description":"List of exported element names and types."},{"field":"threat.enrichments.indicator.file.elf.header.abi_version","type":"keyword","normalization":"","example":"","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"threat.enrichments.indicator.file.elf.header.class","type":"keyword","normalization":"","example":"","description":"Header class of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.header.data","type":"keyword","normalization":"","example":"","description":"Data table of the ELF header."},{"field":"threat.enrichments.indicator.file.elf.header.entrypoint","type":"long","normalization":"","example":"","description":"Header entrypoint of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.header.object_version","type":"keyword","normalization":"","example":"","description":"0x1\" for original ELF files."},{"field":"threat.enrichments.indicator.file.elf.header.os_abi","type":"keyword","normalization":"","example":"","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"threat.enrichments.indicator.file.elf.header.type","type":"keyword","normalization":"","example":"","description":"Header type of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.header.version","type":"keyword","normalization":"","example":"","description":"Version of the ELF header."},{"field":"threat.enrichments.indicator.file.elf.imports","type":"flattened","normalization":"array","example":"","description":"List of imported element names and types."},{"field":"threat.enrichments.indicator.file.elf.sections","type":"nested","normalization":"array","example":"","description":"Section information of the ELF file."},{"field":"threat.enrichments.indicator.file.elf.sections.chi2","type":"long","normalization":"","example":"","description":"Chi-square probability distribution of the section."},{"field":"threat.enrichments.indicator.file.elf.sections.entropy","type":"long","normalization":"","example":"","description":"Shannon entropy calculation from the section."},{"field":"threat.enrichments.indicator.file.elf.sections.flags","type":"keyword","normalization":"","example":"","description":"ELF Section List flags."},{"field":"threat.enrichments.indicator.file.elf.sections.name","type":"keyword","normalization":"","example":"","description":"ELF Section List name."},{"field":"threat.enrichments.indicator.file.elf.sections.physical_offset","type":"keyword","normalization":"","example":"","description":"ELF Section List offset."},{"field":"threat.enrichments.indicator.file.elf.sections.physical_size","type":"long","normalization":"","example":"","description":"ELF Section List physical size."},{"field":"threat.enrichments.indicator.file.elf.sections.type","type":"keyword","normalization":"","example":"","description":"ELF Section List type."},{"field":"threat.enrichments.indicator.file.elf.sections.virtual_address","type":"long","normalization":"","example":"","description":"ELF Section List virtual address."},{"field":"threat.enrichments.indicator.file.elf.sections.virtual_size","type":"long","normalization":"","example":"","description":"ELF Section List virtual size."},{"field":"threat.enrichments.indicator.file.elf.segments","type":"nested","normalization":"array","example":"","description":"ELF object segment list."},{"field":"threat.enrichments.indicator.file.elf.segments.sections","type":"keyword","normalization":"","example":"","description":"ELF object segment sections."},{"field":"threat.enrichments.indicator.file.elf.segments.type","type":"keyword","normalization":"","example":"","description":"ELF object segment type."},{"field":"threat.enrichments.indicator.file.elf.shared_libraries","type":"keyword","normalization":"array","example":"","description":"List of shared libraries used by this ELF object."},{"field":"threat.enrichments.indicator.file.elf.telfhash","type":"keyword","normalization":"","example":"","description":"telfhash hash for ELF file."},{"field":"threat.enrichments.indicator.file.extension","type":"keyword","normalization":"","example":"png","description":"File extension, excluding the leading dot."},{"field":"threat.enrichments.indicator.file.fork_name","type":"keyword","normalization":"","example":"Zone.Identifer","description":"A fork is additional data associated with a filesystem object."},{"field":"threat.enrichments.indicator.file.gid","type":"keyword","normalization":"","example":1001,"description":"Primary group ID (GID) of the file."},{"field":"threat.enrichments.indicator.file.group","type":"keyword","normalization":"","example":"alice","description":"Primary group name of the file."},{"field":"threat.enrichments.indicator.file.hash.md5","type":"keyword","normalization":"","example":"","description":"MD5 hash."},{"field":"threat.enrichments.indicator.file.hash.sha1","type":"keyword","normalization":"","example":"","description":"SHA1 hash."},{"field":"threat.enrichments.indicator.file.hash.sha256","type":"keyword","normalization":"","example":"","description":"SHA256 hash."},{"field":"threat.enrichments.indicator.file.hash.sha512","type":"keyword","normalization":"","example":"","description":"SHA512 hash."},{"field":"threat.enrichments.indicator.file.hash.ssdeep","type":"keyword","normalization":"","example":"","description":"SSDEEP hash."},{"field":"threat.enrichments.indicator.file.inode","type":"keyword","normalization":"","example":256383,"description":"Inode representing the file in the filesystem."},{"field":"threat.enrichments.indicator.file.mime_type","type":"keyword","normalization":"","example":"","description":"Media type of file, document, or arrangement of bytes."},{"field":"threat.enrichments.indicator.file.mode","type":"keyword","normalization":"","example":"0640","description":"Mode of the file in octal representation."},{"field":"threat.enrichments.indicator.file.mtime","type":"date","normalization":"","example":"","description":"Last time the file content was modified."},{"field":"threat.enrichments.indicator.file.name","type":"keyword","normalization":"","example":"example.png","description":"Name of the file including the extension, without the directory."},{"field":"threat.enrichments.indicator.file.owner","type":"keyword","normalization":"","example":"alice","description":"File owner's username."},{"field":"threat.enrichments.indicator.file.path","type":"keyword","normalization":"","example":"/home/alice/example.png","description":"Full path to the file, including the file name."},{"field":"threat.enrichments.indicator.file.path.text","type":"match_only_text","normalization":"","example":"/home/alice/example.png","description":"Full path to the file, including the file name."},{"field":"threat.enrichments.indicator.file.pe.architecture","type":"keyword","normalization":"","example":"x64","description":"CPU architecture target for the file."},{"field":"threat.enrichments.indicator.file.pe.company","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Internal company name of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.pe.description","type":"keyword","normalization":"","example":"Paint","description":"Internal description of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.pe.file_version","type":"keyword","normalization":"","example":"6.3.9600.17415","description":"Process name."},{"field":"threat.enrichments.indicator.file.pe.imphash","type":"keyword","normalization":"","example":"0c6803c4e922103c4dca5963aad36ddf","description":"A hash of the imports in a PE file."},{"field":"threat.enrichments.indicator.file.pe.original_file_name","type":"keyword","normalization":"","example":"MSPAINT.EXE","description":"Internal name of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.pe.product","type":"keyword","normalization":"","example":"Microsoft® Windows® Operating System","description":"Internal product name of the file, provided at compile-time."},{"field":"threat.enrichments.indicator.file.size","type":"long","normalization":"","example":16384,"description":"File size in bytes."},{"field":"threat.enrichments.indicator.file.target_path","type":"keyword","normalization":"","example":"","description":"Target path for symlinks."},{"field":"threat.enrichments.indicator.file.target_path.text","type":"match_only_text","normalization":"","example":"","description":"Target path for symlinks."},{"field":"threat.enrichments.indicator.file.type","type":"keyword","normalization":"","example":"file","description":"File type (file, dir, or symlink)."},{"field":"threat.enrichments.indicator.file.uid","type":"keyword","normalization":"","example":1001,"description":"The user ID (UID) or security identifier (SID) of the file owner."},{"field":"threat.enrichments.indicator.file.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"threat.enrichments.indicator.file.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"threat.enrichments.indicator.file.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.file.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.enrichments.indicator.file.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.file.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.enrichments.indicator.file.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"threat.enrichments.indicator.file.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"threat.enrichments.indicator.file.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.enrichments.indicator.file.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.enrichments.indicator.file.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"threat.enrichments.indicator.file.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"threat.enrichments.indicator.file.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"threat.enrichments.indicator.file.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"threat.enrichments.indicator.file.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"threat.enrichments.indicator.file.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.enrichments.indicator.file.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.file.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"threat.enrichments.indicator.file.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"threat.enrichments.indicator.file.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.file.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"threat.enrichments.indicator.first_seen","type":"date","normalization":"","example":"2020-11-05T17:25:47.000Z","description":"Date/time indicator was first reported."},{"field":"threat.enrichments.indicator.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"threat.enrichments.indicator.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"threat.enrichments.indicator.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"threat.enrichments.indicator.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"threat.enrichments.indicator.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"threat.enrichments.indicator.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"threat.enrichments.indicator.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"threat.enrichments.indicator.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"threat.enrichments.indicator.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"threat.enrichments.indicator.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"threat.enrichments.indicator.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"threat.enrichments.indicator.ip","type":"ip","normalization":"","example":"1.2.3.4","description":"Indicator IP address"},{"field":"threat.enrichments.indicator.last_seen","type":"date","normalization":"","example":"2020-11-05T17:25:47.000Z","description":"Date/time indicator was last reported."},{"field":"threat.enrichments.indicator.marking.tlp","type":"keyword","normalization":"","example":"White","description":"Indicator TLP marking"},{"field":"threat.enrichments.indicator.modified_at","type":"date","normalization":"","example":"2020-11-05T17:25:47.000Z","description":"Date/time indicator was last updated."},{"field":"threat.enrichments.indicator.port","type":"long","normalization":"","example":443,"description":"Indicator port"},{"field":"threat.enrichments.indicator.provider","type":"keyword","normalization":"","example":"lrz_urlhaus","description":"Indicator provider"},{"field":"threat.enrichments.indicator.reference","type":"keyword","normalization":"","example":"https://system.example.com/indicator/0001234","description":"Indicator reference URL"},{"field":"threat.enrichments.indicator.registry.data.bytes","type":"keyword","normalization":"","example":"ZQBuAC0AVQBTAAAAZQBuAAAAAAA=","description":"Original bytes written with base64 encoding."},{"field":"threat.enrichments.indicator.registry.data.strings","type":"wildcard","normalization":"array","example":"[\"C:\\rta\\red_ttp\\bin\\myapp.exe\"]","description":"List of strings representing what was written to the registry."},{"field":"threat.enrichments.indicator.registry.data.type","type":"keyword","normalization":"","example":"REG_SZ","description":"Standard registry type for encoding contents"},{"field":"threat.enrichments.indicator.registry.hive","type":"keyword","normalization":"","example":"HKLM","description":"Abbreviated name for the hive."},{"field":"threat.enrichments.indicator.registry.key","type":"keyword","normalization":"","example":"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe","description":"Hive-relative path of keys."},{"field":"threat.enrichments.indicator.registry.path","type":"keyword","normalization":"","example":"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe\\Debugger","description":"Full path, including hive, key and value"},{"field":"threat.enrichments.indicator.registry.value","type":"keyword","normalization":"","example":"Debugger","description":"Name of the value written."},{"field":"threat.enrichments.indicator.scanner_stats","type":"long","normalization":"","example":4,"description":"Scanner statistics"},{"field":"threat.enrichments.indicator.sightings","type":"long","normalization":"","example":20,"description":"Number of times indicator observed"},{"field":"threat.enrichments.indicator.type","type":"keyword","normalization":"","example":"ipv4-addr","description":"Type of indicator"},{"field":"threat.enrichments.indicator.url.domain","type":"keyword","normalization":"","example":"www.elastic.co","description":"Domain of the url."},{"field":"threat.enrichments.indicator.url.extension","type":"keyword","normalization":"","example":"png","description":"File extension from the request url, excluding the leading dot."},{"field":"threat.enrichments.indicator.url.fragment","type":"keyword","normalization":"","example":"","description":"Portion of the url after the `#`."},{"field":"threat.enrichments.indicator.url.full","type":"wildcard","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top","description":"Full unparsed URL."},{"field":"threat.enrichments.indicator.url.full.text","type":"match_only_text","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top","description":"Full unparsed URL."},{"field":"threat.enrichments.indicator.url.original","type":"wildcard","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch","description":"Unmodified original url as seen in the event source."},{"field":"threat.enrichments.indicator.url.original.text","type":"match_only_text","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch","description":"Unmodified original url as seen in the event source."},{"field":"threat.enrichments.indicator.url.password","type":"keyword","normalization":"","example":"","description":"Password of the request."},{"field":"threat.enrichments.indicator.url.path","type":"wildcard","normalization":"","example":"","description":"Path of the request, such as \"/search\"."},{"field":"threat.enrichments.indicator.url.port","type":"long","normalization":"","example":443,"description":"Port of the request, such as 443."},{"field":"threat.enrichments.indicator.url.query","type":"keyword","normalization":"","example":"","description":"Query string of the request."},{"field":"threat.enrichments.indicator.url.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered url domain, stripped of the subdomain."},{"field":"threat.enrichments.indicator.url.scheme","type":"keyword","normalization":"","example":"https","description":"Scheme of the url."},{"field":"threat.enrichments.indicator.url.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"threat.enrichments.indicator.url.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"threat.enrichments.indicator.url.username","type":"keyword","normalization":"","example":"","description":"Username of the request."},{"field":"threat.enrichments.indicator.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"threat.enrichments.indicator.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"threat.enrichments.indicator.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.enrichments.indicator.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.enrichments.indicator.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"threat.enrichments.indicator.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"threat.enrichments.indicator.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.enrichments.indicator.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.enrichments.indicator.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"threat.enrichments.indicator.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"threat.enrichments.indicator.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"threat.enrichments.indicator.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"threat.enrichments.indicator.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"threat.enrichments.indicator.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.enrichments.indicator.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"threat.enrichments.indicator.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"threat.enrichments.indicator.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"threat.enrichments.indicator.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.enrichments.indicator.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"threat.enrichments.matched.atomic","type":"keyword","normalization":"","example":"bad-domain.com","description":"Matched indicator value"},{"field":"threat.enrichments.matched.field","type":"keyword","normalization":"","example":"file.hash.sha256","description":"Matched indicator field"},{"field":"threat.enrichments.matched.id","type":"keyword","normalization":"","example":"ff93aee5-86a1-4a61-b0e6-0cdc313d01b5","description":"Matched indicator identifier"},{"field":"threat.enrichments.matched.index","type":"keyword","normalization":"","example":"filebeat-8.0.0-2021.05.23-000011","description":"Matched indicator index"},{"field":"threat.enrichments.matched.type","type":"keyword","normalization":"","example":"indicator_match_rule","description":"Type of indicator match"},{"field":"threat.framework","type":"keyword","normalization":"","example":"MITRE ATT&CK","description":"Threat classification framework."},{"field":"threat.group.alias","type":"keyword","normalization":"array","example":["Magecart Group 6"],"description":"Alias of the group."},{"field":"threat.group.id","type":"keyword","normalization":"","example":"G0037","description":"ID of the group."},{"field":"threat.group.name","type":"keyword","normalization":"","example":"FIN6","description":"Name of the group."},{"field":"threat.group.reference","type":"keyword","normalization":"","example":"https://attack.mitre.org/groups/G0037/","description":"Reference URL of the group."},{"field":"threat.indicator.as.number","type":"long","normalization":"","example":15169,"description":"Unique number allocated to the autonomous system."},{"field":"threat.indicator.as.organization.name","type":"keyword","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"threat.indicator.as.organization.name.text","type":"match_only_text","normalization":"","example":"Google LLC","description":"Organization name."},{"field":"threat.indicator.confidence","type":"keyword","normalization":"","example":"High","description":"Indicator confidence rating"},{"field":"threat.indicator.description","type":"keyword","normalization":"","example":"IP x.x.x.x was observed delivering the Angler EK.","description":"Indicator description"},{"field":"threat.indicator.email.address","type":"keyword","normalization":"","example":"phish@example.com","description":"Indicator email address"},{"field":"threat.indicator.file.accessed","type":"date","normalization":"","example":"","description":"Last time the file was accessed."},{"field":"threat.indicator.file.attributes","type":"keyword","normalization":"array","example":["readonly","system"],"description":"Array of file attributes."},{"field":"threat.indicator.file.code_signature.digest_algorithm","type":"keyword","normalization":"","example":"sha256","description":"Hashing algorithm used to sign the process."},{"field":"threat.indicator.file.code_signature.exists","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if a signature is present."},{"field":"threat.indicator.file.code_signature.signing_id","type":"keyword","normalization":"","example":"com.apple.xpc.proxy","description":"The identifier used to sign the process."},{"field":"threat.indicator.file.code_signature.status","type":"keyword","normalization":"","example":"ERROR_UNTRUSTED_ROOT","description":"Additional information about the certificate status."},{"field":"threat.indicator.file.code_signature.subject_name","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Subject name of the code signer"},{"field":"threat.indicator.file.code_signature.team_id","type":"keyword","normalization":"","example":"EQHXZ8M8AV","description":"The team identifier used to sign the process."},{"field":"threat.indicator.file.code_signature.timestamp","type":"date","normalization":"","example":"2021-01-01T12:10:30Z","description":"When the signature was generated and signed."},{"field":"threat.indicator.file.code_signature.trusted","type":"boolean","normalization":"","example":true,"description":"Stores the trust status of the certificate chain."},{"field":"threat.indicator.file.code_signature.valid","type":"boolean","normalization":"","example":true,"description":"Boolean to capture if the digital signature is verified against the binary content."},{"field":"threat.indicator.file.created","type":"date","normalization":"","example":"","description":"File creation time."},{"field":"threat.indicator.file.ctime","type":"date","normalization":"","example":"","description":"Last time the file attributes or metadata changed."},{"field":"threat.indicator.file.device","type":"keyword","normalization":"","example":"sda","description":"Device that is the source of the file."},{"field":"threat.indicator.file.directory","type":"keyword","normalization":"","example":"/home/alice","description":"Directory where the file is located."},{"field":"threat.indicator.file.drive_letter","type":"keyword","normalization":"","example":"C","description":"Drive letter where the file is located."},{"field":"threat.indicator.file.elf.architecture","type":"keyword","normalization":"","example":"x86-64","description":"Machine architecture of the ELF file."},{"field":"threat.indicator.file.elf.byte_order","type":"keyword","normalization":"","example":"Little Endian","description":"Byte sequence of ELF file."},{"field":"threat.indicator.file.elf.cpu_type","type":"keyword","normalization":"","example":"Intel","description":"CPU type of the ELF file."},{"field":"threat.indicator.file.elf.creation_date","type":"date","normalization":"","example":"","description":"Build or compile date."},{"field":"threat.indicator.file.elf.exports","type":"flattened","normalization":"array","example":"","description":"List of exported element names and types."},{"field":"threat.indicator.file.elf.header.abi_version","type":"keyword","normalization":"","example":"","description":"Version of the ELF Application Binary Interface (ABI)."},{"field":"threat.indicator.file.elf.header.class","type":"keyword","normalization":"","example":"","description":"Header class of the ELF file."},{"field":"threat.indicator.file.elf.header.data","type":"keyword","normalization":"","example":"","description":"Data table of the ELF header."},{"field":"threat.indicator.file.elf.header.entrypoint","type":"long","normalization":"","example":"","description":"Header entrypoint of the ELF file."},{"field":"threat.indicator.file.elf.header.object_version","type":"keyword","normalization":"","example":"","description":"0x1\" for original ELF files."},{"field":"threat.indicator.file.elf.header.os_abi","type":"keyword","normalization":"","example":"","description":"Application Binary Interface (ABI) of the Linux OS."},{"field":"threat.indicator.file.elf.header.type","type":"keyword","normalization":"","example":"","description":"Header type of the ELF file."},{"field":"threat.indicator.file.elf.header.version","type":"keyword","normalization":"","example":"","description":"Version of the ELF header."},{"field":"threat.indicator.file.elf.imports","type":"flattened","normalization":"array","example":"","description":"List of imported element names and types."},{"field":"threat.indicator.file.elf.sections","type":"nested","normalization":"array","example":"","description":"Section information of the ELF file."},{"field":"threat.indicator.file.elf.sections.chi2","type":"long","normalization":"","example":"","description":"Chi-square probability distribution of the section."},{"field":"threat.indicator.file.elf.sections.entropy","type":"long","normalization":"","example":"","description":"Shannon entropy calculation from the section."},{"field":"threat.indicator.file.elf.sections.flags","type":"keyword","normalization":"","example":"","description":"ELF Section List flags."},{"field":"threat.indicator.file.elf.sections.name","type":"keyword","normalization":"","example":"","description":"ELF Section List name."},{"field":"threat.indicator.file.elf.sections.physical_offset","type":"keyword","normalization":"","example":"","description":"ELF Section List offset."},{"field":"threat.indicator.file.elf.sections.physical_size","type":"long","normalization":"","example":"","description":"ELF Section List physical size."},{"field":"threat.indicator.file.elf.sections.type","type":"keyword","normalization":"","example":"","description":"ELF Section List type."},{"field":"threat.indicator.file.elf.sections.virtual_address","type":"long","normalization":"","example":"","description":"ELF Section List virtual address."},{"field":"threat.indicator.file.elf.sections.virtual_size","type":"long","normalization":"","example":"","description":"ELF Section List virtual size."},{"field":"threat.indicator.file.elf.segments","type":"nested","normalization":"array","example":"","description":"ELF object segment list."},{"field":"threat.indicator.file.elf.segments.sections","type":"keyword","normalization":"","example":"","description":"ELF object segment sections."},{"field":"threat.indicator.file.elf.segments.type","type":"keyword","normalization":"","example":"","description":"ELF object segment type."},{"field":"threat.indicator.file.elf.shared_libraries","type":"keyword","normalization":"array","example":"","description":"List of shared libraries used by this ELF object."},{"field":"threat.indicator.file.elf.telfhash","type":"keyword","normalization":"","example":"","description":"telfhash hash for ELF file."},{"field":"threat.indicator.file.extension","type":"keyword","normalization":"","example":"png","description":"File extension, excluding the leading dot."},{"field":"threat.indicator.file.fork_name","type":"keyword","normalization":"","example":"Zone.Identifer","description":"A fork is additional data associated with a filesystem object."},{"field":"threat.indicator.file.gid","type":"keyword","normalization":"","example":1001,"description":"Primary group ID (GID) of the file."},{"field":"threat.indicator.file.group","type":"keyword","normalization":"","example":"alice","description":"Primary group name of the file."},{"field":"threat.indicator.file.hash.md5","type":"keyword","normalization":"","example":"","description":"MD5 hash."},{"field":"threat.indicator.file.hash.sha1","type":"keyword","normalization":"","example":"","description":"SHA1 hash."},{"field":"threat.indicator.file.hash.sha256","type":"keyword","normalization":"","example":"","description":"SHA256 hash."},{"field":"threat.indicator.file.hash.sha512","type":"keyword","normalization":"","example":"","description":"SHA512 hash."},{"field":"threat.indicator.file.hash.ssdeep","type":"keyword","normalization":"","example":"","description":"SSDEEP hash."},{"field":"threat.indicator.file.inode","type":"keyword","normalization":"","example":256383,"description":"Inode representing the file in the filesystem."},{"field":"threat.indicator.file.mime_type","type":"keyword","normalization":"","example":"","description":"Media type of file, document, or arrangement of bytes."},{"field":"threat.indicator.file.mode","type":"keyword","normalization":"","example":"0640","description":"Mode of the file in octal representation."},{"field":"threat.indicator.file.mtime","type":"date","normalization":"","example":"","description":"Last time the file content was modified."},{"field":"threat.indicator.file.name","type":"keyword","normalization":"","example":"example.png","description":"Name of the file including the extension, without the directory."},{"field":"threat.indicator.file.owner","type":"keyword","normalization":"","example":"alice","description":"File owner's username."},{"field":"threat.indicator.file.path","type":"keyword","normalization":"","example":"/home/alice/example.png","description":"Full path to the file, including the file name."},{"field":"threat.indicator.file.path.text","type":"match_only_text","normalization":"","example":"/home/alice/example.png","description":"Full path to the file, including the file name."},{"field":"threat.indicator.file.pe.architecture","type":"keyword","normalization":"","example":"x64","description":"CPU architecture target for the file."},{"field":"threat.indicator.file.pe.company","type":"keyword","normalization":"","example":"Microsoft Corporation","description":"Internal company name of the file, provided at compile-time."},{"field":"threat.indicator.file.pe.description","type":"keyword","normalization":"","example":"Paint","description":"Internal description of the file, provided at compile-time."},{"field":"threat.indicator.file.pe.file_version","type":"keyword","normalization":"","example":"6.3.9600.17415","description":"Process name."},{"field":"threat.indicator.file.pe.imphash","type":"keyword","normalization":"","example":"0c6803c4e922103c4dca5963aad36ddf","description":"A hash of the imports in a PE file."},{"field":"threat.indicator.file.pe.original_file_name","type":"keyword","normalization":"","example":"MSPAINT.EXE","description":"Internal name of the file, provided at compile-time."},{"field":"threat.indicator.file.pe.product","type":"keyword","normalization":"","example":"Microsoft® Windows® Operating System","description":"Internal product name of the file, provided at compile-time."},{"field":"threat.indicator.file.size","type":"long","normalization":"","example":16384,"description":"File size in bytes."},{"field":"threat.indicator.file.target_path","type":"keyword","normalization":"","example":"","description":"Target path for symlinks."},{"field":"threat.indicator.file.target_path.text","type":"match_only_text","normalization":"","example":"","description":"Target path for symlinks."},{"field":"threat.indicator.file.type","type":"keyword","normalization":"","example":"file","description":"File type (file, dir, or symlink)."},{"field":"threat.indicator.file.uid","type":"keyword","normalization":"","example":1001,"description":"The user ID (UID) or security identifier (SID) of the file owner."},{"field":"threat.indicator.file.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"threat.indicator.file.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"threat.indicator.file.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"threat.indicator.file.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.indicator.file.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.file.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.indicator.file.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"threat.indicator.file.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"threat.indicator.file.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.indicator.file.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.indicator.file.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"threat.indicator.file.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"threat.indicator.file.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"threat.indicator.file.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"threat.indicator.file.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"threat.indicator.file.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.indicator.file.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"threat.indicator.file.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"threat.indicator.file.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"threat.indicator.file.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.file.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"threat.indicator.first_seen","type":"date","normalization":"","example":"2020-11-05T17:25:47.000Z","description":"Date/time indicator was first reported."},{"field":"threat.indicator.geo.city_name","type":"keyword","normalization":"","example":"Montreal","description":"City name."},{"field":"threat.indicator.geo.continent_code","type":"keyword","normalization":"","example":"NA","description":"Continent code."},{"field":"threat.indicator.geo.continent_name","type":"keyword","normalization":"","example":"North America","description":"Name of the continent."},{"field":"threat.indicator.geo.country_iso_code","type":"keyword","normalization":"","example":"CA","description":"Country ISO code."},{"field":"threat.indicator.geo.country_name","type":"keyword","normalization":"","example":"Canada","description":"Country name."},{"field":"threat.indicator.geo.location","type":"geo_point","normalization":"","example":{"lon":-73.61483,"lat":45.505918},"description":"Longitude and latitude."},{"field":"threat.indicator.geo.name","type":"keyword","normalization":"","example":"boston-dc","description":"User-defined description of a location."},{"field":"threat.indicator.geo.postal_code","type":"keyword","normalization":"","example":94040,"description":"Postal code."},{"field":"threat.indicator.geo.region_iso_code","type":"keyword","normalization":"","example":"CA-QC","description":"Region ISO code."},{"field":"threat.indicator.geo.region_name","type":"keyword","normalization":"","example":"Quebec","description":"Region name."},{"field":"threat.indicator.geo.timezone","type":"keyword","normalization":"","example":"America/Argentina/Buenos_Aires","description":"Time zone."},{"field":"threat.indicator.ip","type":"ip","normalization":"","example":"1.2.3.4","description":"Indicator IP address"},{"field":"threat.indicator.last_seen","type":"date","normalization":"","example":"2020-11-05T17:25:47.000Z","description":"Date/time indicator was last reported."},{"field":"threat.indicator.marking.tlp","type":"keyword","normalization":"","example":"WHITE","description":"Indicator TLP marking"},{"field":"threat.indicator.modified_at","type":"date","normalization":"","example":"2020-11-05T17:25:47.000Z","description":"Date/time indicator was last updated."},{"field":"threat.indicator.port","type":"long","normalization":"","example":443,"description":"Indicator port"},{"field":"threat.indicator.provider","type":"keyword","normalization":"","example":"lrz_urlhaus","description":"Indicator provider"},{"field":"threat.indicator.reference","type":"keyword","normalization":"","example":"https://system.example.com/indicator/0001234","description":"Indicator reference URL"},{"field":"threat.indicator.registry.data.bytes","type":"keyword","normalization":"","example":"ZQBuAC0AVQBTAAAAZQBuAAAAAAA=","description":"Original bytes written with base64 encoding."},{"field":"threat.indicator.registry.data.strings","type":"wildcard","normalization":"array","example":"[\"C:\\rta\\red_ttp\\bin\\myapp.exe\"]","description":"List of strings representing what was written to the registry."},{"field":"threat.indicator.registry.data.type","type":"keyword","normalization":"","example":"REG_SZ","description":"Standard registry type for encoding contents"},{"field":"threat.indicator.registry.hive","type":"keyword","normalization":"","example":"HKLM","description":"Abbreviated name for the hive."},{"field":"threat.indicator.registry.key","type":"keyword","normalization":"","example":"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe","description":"Hive-relative path of keys."},{"field":"threat.indicator.registry.path","type":"keyword","normalization":"","example":"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\winword.exe\\Debugger","description":"Full path, including hive, key and value"},{"field":"threat.indicator.registry.value","type":"keyword","normalization":"","example":"Debugger","description":"Name of the value written."},{"field":"threat.indicator.scanner_stats","type":"long","normalization":"","example":4,"description":"Scanner statistics"},{"field":"threat.indicator.sightings","type":"long","normalization":"","example":20,"description":"Number of times indicator observed"},{"field":"threat.indicator.type","type":"keyword","normalization":"","example":"ipv4-addr","description":"Type of indicator"},{"field":"threat.indicator.url.domain","type":"keyword","normalization":"","example":"www.elastic.co","description":"Domain of the url."},{"field":"threat.indicator.url.extension","type":"keyword","normalization":"","example":"png","description":"File extension from the request url, excluding the leading dot."},{"field":"threat.indicator.url.fragment","type":"keyword","normalization":"","example":"","description":"Portion of the url after the `#`."},{"field":"threat.indicator.url.full","type":"wildcard","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top","description":"Full unparsed URL."},{"field":"threat.indicator.url.full.text","type":"match_only_text","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top","description":"Full unparsed URL."},{"field":"threat.indicator.url.original","type":"wildcard","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch","description":"Unmodified original url as seen in the event source."},{"field":"threat.indicator.url.original.text","type":"match_only_text","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch","description":"Unmodified original url as seen in the event source."},{"field":"threat.indicator.url.password","type":"keyword","normalization":"","example":"","description":"Password of the request."},{"field":"threat.indicator.url.path","type":"wildcard","normalization":"","example":"","description":"Path of the request, such as \"/search\"."},{"field":"threat.indicator.url.port","type":"long","normalization":"","example":443,"description":"Port of the request, such as 443."},{"field":"threat.indicator.url.query","type":"keyword","normalization":"","example":"","description":"Query string of the request."},{"field":"threat.indicator.url.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered url domain, stripped of the subdomain."},{"field":"threat.indicator.url.scheme","type":"keyword","normalization":"","example":"https","description":"Scheme of the url."},{"field":"threat.indicator.url.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"threat.indicator.url.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"threat.indicator.url.username","type":"keyword","normalization":"","example":"","description":"Username of the request."},{"field":"threat.indicator.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"threat.indicator.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"threat.indicator.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"threat.indicator.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"threat.indicator.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"threat.indicator.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"threat.indicator.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"threat.indicator.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"threat.indicator.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"threat.indicator.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"threat.indicator.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"threat.indicator.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"threat.indicator.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"threat.indicator.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"threat.indicator.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"threat.indicator.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"threat.indicator.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"threat.indicator.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"threat.indicator.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"threat.indicator.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"threat.software.alias","type":"keyword","normalization":"array","example":["X-Agent"],"description":"Alias of the software"},{"field":"threat.software.id","type":"keyword","normalization":"","example":"S0552","description":"ID of the software"},{"field":"threat.software.name","type":"keyword","normalization":"","example":"AdFind","description":"Name of the software."},{"field":"threat.software.platforms","type":"keyword","normalization":"array","example":["Windows"],"description":"Platforms of the software."},{"field":"threat.software.reference","type":"keyword","normalization":"","example":"https://attack.mitre.org/software/S0552/","description":"Software reference URL."},{"field":"threat.software.type","type":"keyword","normalization":"","example":"Tool","description":"Software type."},{"field":"threat.tactic.id","type":"keyword","normalization":"array","example":"TA0002","description":"Threat tactic id."},{"field":"threat.tactic.name","type":"keyword","normalization":"array","example":"Execution","description":"Threat tactic."},{"field":"threat.tactic.reference","type":"keyword","normalization":"array","example":"https://attack.mitre.org/tactics/TA0002/","description":"Threat tactic URL reference."},{"field":"threat.technique.id","type":"keyword","normalization":"array","example":"T1059","description":"Threat technique id."},{"field":"threat.technique.name","type":"keyword","normalization":"array","example":"Command and Scripting Interpreter","description":"Threat technique name."},{"field":"threat.technique.name.text","type":"match_only_text","normalization":"","example":"Command and Scripting Interpreter","description":"Threat technique name."},{"field":"threat.technique.reference","type":"keyword","normalization":"array","example":"https://attack.mitre.org/techniques/T1059/","description":"Threat technique URL reference."},{"field":"threat.technique.subtechnique.id","type":"keyword","normalization":"array","example":"T1059.001","description":"Threat subtechnique id."},{"field":"threat.technique.subtechnique.name","type":"keyword","normalization":"array","example":"PowerShell","description":"Threat subtechnique name."},{"field":"threat.technique.subtechnique.name.text","type":"match_only_text","normalization":"","example":"PowerShell","description":"Threat subtechnique name."},{"field":"threat.technique.subtechnique.reference","type":"keyword","normalization":"array","example":"https://attack.mitre.org/techniques/T1059/001/","description":"Threat subtechnique URL reference."},{"field":"tls.cipher","type":"keyword","normalization":"","example":"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256","description":"String indicating the cipher used during the current connection."},{"field":"tls.client.certificate","type":"keyword","normalization":"","example":"MII...","description":"PEM-encoded stand-alone certificate offered by the client."},{"field":"tls.client.certificate_chain","type":"keyword","normalization":"array","example":["MII...","MII..."],"description":"Array of PEM-encoded certificates that make up the certificate chain offered by the client."},{"field":"tls.client.hash.md5","type":"keyword","normalization":"","example":"0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC","description":"Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the client."},{"field":"tls.client.hash.sha1","type":"keyword","normalization":"","example":"9E393D93138888D288266C2D915214D1D1CCEB2A","description":"Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the client."},{"field":"tls.client.hash.sha256","type":"keyword","normalization":"","example":"0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0","description":"Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the client."},{"field":"tls.client.issuer","type":"keyword","normalization":"","example":"CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com","description":"Distinguished name of subject of the issuer of the x.509 certificate presented by the client."},{"field":"tls.client.ja3","type":"keyword","normalization":"","example":"d4e5b18d6b55c71272893221c96ba240","description":"A hash that identifies clients based on how they perform an SSL/TLS handshake."},{"field":"tls.client.not_after","type":"date","normalization":"","example":"2021-01-01T00:00:00.000Z","description":"Date/Time indicating when client certificate is no longer considered valid."},{"field":"tls.client.not_before","type":"date","normalization":"","example":"1970-01-01T00:00:00.000Z","description":"Date/Time indicating when client certificate is first considered valid."},{"field":"tls.client.server_name","type":"keyword","normalization":"","example":"www.elastic.co","description":"Hostname the client is trying to connect to. Also called the SNI."},{"field":"tls.client.subject","type":"keyword","normalization":"","example":"CN=myclient, OU=Documentation Team, DC=example, DC=com","description":"Distinguished name of subject of the x.509 certificate presented by the client."},{"field":"tls.client.supported_ciphers","type":"keyword","normalization":"array","example":["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","..."],"description":"Array of ciphers offered by the client during the client hello."},{"field":"tls.client.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"tls.client.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"tls.client.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"tls.client.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"tls.client.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"tls.client.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"tls.client.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"tls.client.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"tls.client.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"tls.client.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"tls.client.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"tls.client.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"tls.client.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"tls.client.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"tls.client.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"tls.client.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"tls.client.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"tls.client.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"tls.client.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"tls.client.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"tls.client.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"tls.client.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"tls.client.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"tls.client.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"tls.curve","type":"keyword","normalization":"","example":"secp256r1","description":"String indicating the curve used for the given cipher, when applicable."},{"field":"tls.established","type":"boolean","normalization":"","example":"","description":"Boolean flag indicating if the TLS negotiation was successful and transitioned to an encrypted tunnel."},{"field":"tls.next_protocol","type":"keyword","normalization":"","example":"http/1.1","description":"String indicating the protocol being tunneled."},{"field":"tls.resumed","type":"boolean","normalization":"","example":"","description":"Boolean flag indicating if this TLS connection was resumed from an existing TLS negotiation."},{"field":"tls.server.certificate","type":"keyword","normalization":"","example":"MII...","description":"PEM-encoded stand-alone certificate offered by the server."},{"field":"tls.server.certificate_chain","type":"keyword","normalization":"array","example":["MII...","MII..."],"description":"Array of PEM-encoded certificates that make up the certificate chain offered by the server."},{"field":"tls.server.hash.md5","type":"keyword","normalization":"","example":"0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC","description":"Certificate fingerprint using the MD5 digest of DER-encoded version of certificate offered by the server."},{"field":"tls.server.hash.sha1","type":"keyword","normalization":"","example":"9E393D93138888D288266C2D915214D1D1CCEB2A","description":"Certificate fingerprint using the SHA1 digest of DER-encoded version of certificate offered by the server."},{"field":"tls.server.hash.sha256","type":"keyword","normalization":"","example":"0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0","description":"Certificate fingerprint using the SHA256 digest of DER-encoded version of certificate offered by the server."},{"field":"tls.server.issuer","type":"keyword","normalization":"","example":"CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com","description":"Subject of the issuer of the x.509 certificate presented by the server."},{"field":"tls.server.ja3s","type":"keyword","normalization":"","example":"394441ab65754e2207b1e1b457b3641d","description":"A hash that identifies servers based on how they perform an SSL/TLS handshake."},{"field":"tls.server.not_after","type":"date","normalization":"","example":"2021-01-01T00:00:00.000Z","description":"Timestamp indicating when server certificate is no longer considered valid."},{"field":"tls.server.not_before","type":"date","normalization":"","example":"1970-01-01T00:00:00.000Z","description":"Timestamp indicating when server certificate is first considered valid."},{"field":"tls.server.subject","type":"keyword","normalization":"","example":"CN=www.example.com, OU=Infrastructure Team, DC=example, DC=com","description":"Subject of the x.509 certificate presented by the server."},{"field":"tls.server.x509.alternative_names","type":"keyword","normalization":"array","example":"*.elastic.co","description":"List of subject alternative names (SAN)."},{"field":"tls.server.x509.issuer.common_name","type":"keyword","normalization":"array","example":"Example SHA2 High Assurance Server CA","description":"List of common name (CN) of issuing certificate authority."},{"field":"tls.server.x509.issuer.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) codes"},{"field":"tls.server.x509.issuer.distinguished_name","type":"keyword","normalization":"","example":"C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance Server CA","description":"Distinguished name (DN) of issuing certificate authority."},{"field":"tls.server.x509.issuer.locality","type":"keyword","normalization":"array","example":"Mountain View","description":"List of locality names (L)"},{"field":"tls.server.x509.issuer.organization","type":"keyword","normalization":"array","example":"Example Inc","description":"List of organizations (O) of issuing certificate authority."},{"field":"tls.server.x509.issuer.organizational_unit","type":"keyword","normalization":"array","example":"www.example.com","description":"List of organizational units (OU) of issuing certificate authority."},{"field":"tls.server.x509.issuer.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"tls.server.x509.not_after","type":"date","normalization":"","example":"2020-07-16 03:15:39+00:00","description":"Time at which the certificate is no longer considered valid."},{"field":"tls.server.x509.not_before","type":"date","normalization":"","example":"2019-08-16 01:40:25+00:00","description":"Time at which the certificate is first considered valid."},{"field":"tls.server.x509.public_key_algorithm","type":"keyword","normalization":"","example":"RSA","description":"Algorithm used to generate the public key."},{"field":"tls.server.x509.public_key_curve","type":"keyword","normalization":"","example":"nistp521","description":"The curve used by the elliptic curve public key algorithm. This is algorithm specific."},{"field":"tls.server.x509.public_key_exponent","type":"long","normalization":"","example":65537,"description":"Exponent used to derive the public key. This is algorithm specific."},{"field":"tls.server.x509.public_key_size","type":"long","normalization":"","example":2048,"description":"The size of the public key space in bits."},{"field":"tls.server.x509.serial_number","type":"keyword","normalization":"","example":"55FBB9C7DEBF09809D12CCAA","description":"Unique serial number issued by the certificate authority."},{"field":"tls.server.x509.signature_algorithm","type":"keyword","normalization":"","example":"SHA256-RSA","description":"Identifier for certificate signature algorithm."},{"field":"tls.server.x509.subject.common_name","type":"keyword","normalization":"array","example":"shared.global.example.net","description":"List of common names (CN) of subject."},{"field":"tls.server.x509.subject.country","type":"keyword","normalization":"array","example":"US","description":"List of country (C) code"},{"field":"tls.server.x509.subject.distinguished_name","type":"keyword","normalization":"","example":"C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net","description":"Distinguished name (DN) of the certificate subject entity."},{"field":"tls.server.x509.subject.locality","type":"keyword","normalization":"array","example":"San Francisco","description":"List of locality names (L)"},{"field":"tls.server.x509.subject.organization","type":"keyword","normalization":"array","example":"Example, Inc.","description":"List of organizations (O) of subject."},{"field":"tls.server.x509.subject.organizational_unit","type":"keyword","normalization":"array","example":"","description":"List of organizational units (OU) of subject."},{"field":"tls.server.x509.subject.state_or_province","type":"keyword","normalization":"array","example":"California","description":"List of state or province names (ST, S, or P)"},{"field":"tls.server.x509.version_number","type":"keyword","normalization":"","example":3,"description":"Version of x509 format."},{"field":"tls.version","type":"keyword","normalization":"","example":1.2,"description":"Numeric part of the version parsed from the original string."},{"field":"tls.version_protocol","type":"keyword","normalization":"","example":"tls","description":"Normalized lowercase protocol name parsed from original string."},{"field":"trace.id","type":"keyword","normalization":"","example":"4bf92f3577b34da6a3ce929d0e0e4736","description":"Unique identifier of the trace."},{"field":"transaction.id","type":"keyword","normalization":"","example":"00f067aa0ba902b7","description":"Unique identifier of the transaction within the scope of its trace."},{"field":"url.domain","type":"keyword","normalization":"","example":"www.elastic.co","description":"Domain of the url."},{"field":"url.extension","type":"keyword","normalization":"","example":"png","description":"File extension from the request url, excluding the leading dot."},{"field":"url.fragment","type":"keyword","normalization":"","example":"","description":"Portion of the url after the `#`."},{"field":"url.full","type":"wildcard","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top","description":"Full unparsed URL."},{"field":"url.full.text","type":"match_only_text","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top","description":"Full unparsed URL."},{"field":"url.original","type":"wildcard","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch","description":"Unmodified original url as seen in the event source."},{"field":"url.original.text","type":"match_only_text","normalization":"","example":"https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch","description":"Unmodified original url as seen in the event source."},{"field":"url.password","type":"keyword","normalization":"","example":"","description":"Password of the request."},{"field":"url.path","type":"wildcard","normalization":"","example":"","description":"Path of the request, such as \"/search\"."},{"field":"url.port","type":"long","normalization":"","example":443,"description":"Port of the request, such as 443."},{"field":"url.query","type":"keyword","normalization":"","example":"","description":"Query string of the request."},{"field":"url.registered_domain","type":"keyword","normalization":"","example":"example.com","description":"The highest registered url domain, stripped of the subdomain."},{"field":"url.scheme","type":"keyword","normalization":"","example":"https","description":"Scheme of the url."},{"field":"url.subdomain","type":"keyword","normalization":"","example":"east","description":"The subdomain of the domain."},{"field":"url.top_level_domain","type":"keyword","normalization":"","example":"co.uk","description":"The effective top level domain (com, org, net, co.uk)."},{"field":"url.username","type":"keyword","normalization":"","example":"","description":"Username of the request."},{"field":"user.changes.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"user.changes.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"user.changes.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.changes.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.changes.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"user.changes.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"user.changes.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"user.changes.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.changes.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"user.changes.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.changes.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.changes.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"user.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"user.effective.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"user.effective.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"user.effective.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.effective.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.effective.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"user.effective.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"user.effective.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"user.effective.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.effective.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"user.effective.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.effective.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.effective.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"user.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"user.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"user.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"user.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"user.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"user.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"user.target.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the user is a member of."},{"field":"user.target.email","type":"keyword","normalization":"","example":"","description":"User email address."},{"field":"user.target.full_name","type":"keyword","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.target.full_name.text","type":"match_only_text","normalization":"","example":"Albert Einstein","description":"User's full name, if available."},{"field":"user.target.group.domain","type":"keyword","normalization":"","example":"","description":"Name of the directory the group is a member of."},{"field":"user.target.group.id","type":"keyword","normalization":"","example":"","description":"Unique identifier for the group on the system/platform."},{"field":"user.target.group.name","type":"keyword","normalization":"","example":"","description":"Name of the group."},{"field":"user.target.hash","type":"keyword","normalization":"","example":"","description":"Unique user hash to correlate information for a user in anonymized form."},{"field":"user.target.id","type":"keyword","normalization":"","example":"S-1-5-21-202424912787-2692429404-2351956786-1000","description":"Unique identifier of the user."},{"field":"user.target.name","type":"keyword","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.target.name.text","type":"match_only_text","normalization":"","example":"a.einstein","description":"Short name or login of the user."},{"field":"user.target.roles","type":"keyword","normalization":"array","example":["kibana_admin","reporting_user"],"description":"Array of user roles at the time of the event."},{"field":"user_agent.device.name","type":"keyword","normalization":"","example":"iPhone","description":"Name of the device."},{"field":"user_agent.name","type":"keyword","normalization":"","example":"Safari","description":"Name of the user agent."},{"field":"user_agent.original","type":"keyword","normalization":"","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","description":"Unparsed user_agent string."},{"field":"user_agent.original.text","type":"match_only_text","normalization":"","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","description":"Unparsed user_agent string."},{"field":"user_agent.os.family","type":"keyword","normalization":"","example":"debian","description":"OS family (such as redhat, debian, freebsd, windows)."},{"field":"user_agent.os.full","type":"keyword","normalization":"","example":"Mac OS Mojave","description":"Operating system name, including the version or code name."},{"field":"user_agent.os.full.text","type":"match_only_text","normalization":"","example":"Mac OS Mojave","description":"Operating system name, including the version or code name."},{"field":"user_agent.os.kernel","type":"keyword","normalization":"","example":"4.4.0-112-generic","description":"Operating system kernel version as a raw string."},{"field":"user_agent.os.name","type":"keyword","normalization":"","example":"Mac OS X","description":"Operating system name, without the version."},{"field":"user_agent.os.name.text","type":"match_only_text","normalization":"","example":"Mac OS X","description":"Operating system name, without the version."},{"field":"user_agent.os.platform","type":"keyword","normalization":"","example":"darwin","description":"Operating system platform (such centos, ubuntu, windows)."},{"field":"user_agent.os.type","type":"keyword","normalization":"","example":"macos","description":"Which commercial OS family (one of: linux, macos, unix or windows)."},{"field":"user_agent.os.version","type":"keyword","normalization":"","example":"10.14.1","description":"Operating system version as a raw string."},{"field":"user_agent.version","type":"keyword","normalization":"","example":12,"description":"Version of the user agent."},{"field":"vulnerability.category","type":"keyword","normalization":"array","example":["Firewall"],"description":"Category of a vulnerability."},{"field":"vulnerability.classification","type":"keyword","normalization":"","example":"CVSS","description":"Classification of the vulnerability."},{"field":"vulnerability.description","type":"keyword","normalization":"","example":"In macOS before 2.12.6, there is a vulnerability in the RPC...","description":"Description of the vulnerability."},{"field":"vulnerability.description.text","type":"match_only_text","normalization":"","example":"In macOS before 2.12.6, there is a vulnerability in the RPC...","description":"Description of the vulnerability."},{"field":"vulnerability.enumeration","type":"keyword","normalization":"","example":"CVE","description":"Identifier of the vulnerability."},{"field":"vulnerability.id","type":"keyword","normalization":"","example":"CVE-2019-00001","description":"ID of the vulnerability."},{"field":"vulnerability.reference","type":"keyword","normalization":"","example":"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111","description":"Reference of the vulnerability."},{"field":"vulnerability.report_id","type":"keyword","normalization":"","example":20191018.0001,"description":"Scan identification number."},{"field":"vulnerability.scanner.vendor","type":"keyword","normalization":"","example":"Tenable","description":"Name of the scanner vendor."},{"field":"vulnerability.score.base","type":"float","normalization":"","example":5.5,"description":"Vulnerability Base score."},{"field":"vulnerability.score.environmental","type":"float","normalization":"","example":5.5,"description":"Vulnerability Environmental score."},{"field":"vulnerability.score.temporal","type":"float","normalization":"","example":"","description":"Vulnerability Temporal score."},{"field":"vulnerability.score.version","type":"keyword","normalization":"","example":2,"description":"CVSS version."},{"field":"vulnerability.severity","type":"keyword","normalization":"","example":"Critical","description":"Severity of the vulnerability."}] \ No newline at end of file diff --git a/x-pack/plugins/osquery/public/components/app.tsx b/x-pack/plugins/osquery/public/components/app.tsx index ea1f9698795aa..f4c805d375351 100644 --- a/x-pack/plugins/osquery/public/components/app.tsx +++ b/x-pack/plugins/osquery/public/components/app.tsx @@ -24,7 +24,7 @@ const OsqueryAppComponent = () => { const section = useMemo(() => location.pathname.split('/')[1] ?? 'overview', [location.pathname]); const { data: osqueryIntegration, isFetched } = useOsqueryIntegrationStatus(); - if (isFetched && osqueryIntegration.install_status !== 'installed') { + if (isFetched && osqueryIntegration?.install_status !== 'installed') { return ; } diff --git a/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_custom_button_extension.tsx b/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_custom_button_extension.tsx index 67791cb34e683..c3770f202c087 100644 --- a/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_custom_button_extension.tsx +++ b/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_custom_button_extension.tsx @@ -24,8 +24,8 @@ export const OsqueryManagedCustomButtonExtension = React.memo { const fetchStatus = () => { - http.get('/internal/osquery/status').then((response) => { - setDisabled(response.install_status !== 'installed'); + http.get<{ install_status: string }>('/internal/osquery/status').then((response) => { + setDisabled(response?.install_status !== 'installed'); }); }; fetchStatus(); diff --git a/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx b/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx index 4ac20e6144c08..c2ac84ce191da 100644 --- a/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx +++ b/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx @@ -165,16 +165,6 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo< defaultValue: { config: JSON.stringify(get(newPolicy, 'inputs[0].config.osquery.value', {}), null, 2), }, - serializer: (formData) => { - let config; - try { - // @ts-expect-error update types - config = JSON.parse(formData.config); - } catch (e) { - config = {}; - } - return { config }; - }, schema: { config: { label: i18n.translate('xpack.osquery.fleetIntegration.osqueryConfig.configFieldLabel', { @@ -243,10 +233,16 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo< if (isValid === undefined) return; const updatedPolicy = produce(newPolicy, (draft) => { - if (isEmpty(config)) { + let parsedConfig; + try { + parsedConfig = JSON.parse(config); + // eslint-disable-next-line no-empty + } catch (e) {} + + if (isEmpty(parsedConfig)) { unset(draft, 'inputs[0].config'); } else { - set(draft, 'inputs[0].config.osquery.value', config); + set(draft, 'inputs[0].config.osquery.value', parsedConfig); } return draft; }); @@ -261,11 +257,14 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo< if (editMode && policyAgentsCount === null) { const fetchAgentsCount = async () => { try { - const response = await http.fetch(agentRouteService.getStatusPath(), { - query: { - policyId: policy?.policy_id, - }, - }); + const response = await http.fetch<{ results: { total: number } }>( + agentRouteService.getStatusPath(), + { + query: { + policyId: policy?.policy_id, + }, + } + ); if (response.results) { setPolicyAgentsCount(response.results.total); } @@ -276,7 +275,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo< const fetchAgentPolicyDetails = async () => { if (policy?.policy_id) { try { - const response = await http.fetch( + const response = await http.fetch<{ item: AgentPolicy }>( agentPolicyRouteService.getInfoPath(policy?.policy_id) ); if (response.item) { diff --git a/x-pack/plugins/osquery/public/live_queries/form/index.tsx b/x-pack/plugins/osquery/public/live_queries/form/index.tsx index 6d13c76d9d592..0c0151b36203c 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/index.tsx @@ -86,7 +86,7 @@ const LiveQueryFormComponent: React.FC = ({ const { data, isLoading, mutateAsync, isError, isSuccess } = useMutation( (payload: Record) => - http.post('/internal/osquery/action', { + http.post('/internal/osquery/action', { body: JSON.stringify(payload), }), { diff --git a/x-pack/plugins/osquery/public/packs/form/index.tsx b/x-pack/plugins/osquery/public/packs/form/index.tsx index f20a26f2791dd..1930227c2dc9e 100644 --- a/x-pack/plugins/osquery/public/packs/form/index.tsx +++ b/x-pack/plugins/osquery/public/packs/form/index.tsx @@ -98,14 +98,17 @@ const PackFormComponent: React.FC = ({ defaultValue, editMode = f description: { type: FIELD_TYPES.TEXT, label: i18n.translate('xpack.osquery.pack.form.descriptionFieldLabel', { - defaultMessage: 'Description', + defaultMessage: 'Description (optional)', }), }, policy_ids: { defaultValue: [], type: FIELD_TYPES.COMBO_BOX, label: i18n.translate('xpack.osquery.pack.form.agentPoliciesFieldLabel', { - defaultMessage: 'Agent policies', + defaultMessage: 'Agent policies (optional)', + }), + helpText: i18n.translate('xpack.osquery.pack.form.agentPoliciesFieldHelpText', { + defaultMessage: 'Queries in this pack are scheduled for agents in the selected policies.', }), }, enabled: { diff --git a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx index a32f369922958..0b661c61a9057 100644 --- a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx @@ -22,6 +22,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, FormattedDate, FormattedTime, FormattedRelative } from '@kbn/i18n/react'; +import moment from 'moment-timezone'; import { TypedLensByValueInput, @@ -29,7 +30,7 @@ import { PieVisualizationState, } from '../../../lens/public'; import { FilterStateStore, IndexPattern } from '../../../../../src/plugins/data/common'; -import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kibana'; +import { useKibana } from '../common/lib/kibana'; import { OsqueryManagerPackagePolicyInputStream } from '../../common/types'; import { ScheduledQueryErrorsTable } from './scheduled_query_errors_table'; import { usePackQueryLastResults } from './use_pack_query_last_results'; @@ -207,8 +208,6 @@ const ViewResultsInLensActionComponent: React.FC { - const openInNewTab = !(!isModifiedEvent(event) && isLeftClickEvent(event)); - event.preventDefault(); lensService?.navigateToPrefilledEditor( @@ -222,7 +221,7 @@ const ViewResultsInLensActionComponent: React.FC + {VIEW_IN_DISCOVER} ); @@ -378,6 +377,7 @@ interface ScheduledQueryLastResultsProps { actionId: string; queryId: string; interval: number; + logsIndexPattern: IndexPattern | undefined; toggleErrors: (payload: { queryId: string; interval: number }) => void; expanded: boolean; } @@ -386,12 +386,10 @@ const ScheduledQueryLastResults: React.FC = ({ actionId, queryId, interval, + logsIndexPattern, toggleErrors, expanded, }) => { - const data = useKibana().services.data; - const [logsIndexPattern, setLogsIndexPattern] = useState(undefined); - const { data: lastResultsData, isFetched } = usePackQueryLastResults({ actionId, interval, @@ -409,15 +407,6 @@ const ScheduledQueryLastResults: React.FC = ({ [queryId, interval, toggleErrors] ); - useEffect(() => { - const fetchLogsIndexPattern = async () => { - const indexPattern = await data.indexPatterns.find('logs-*'); - - setLogsIndexPattern(indexPattern[0]); - }; - fetchLogsIndexPattern(); - }, [data.indexPatterns]); - if (!isFetched || !errorsFetched) { return ; } @@ -518,6 +507,86 @@ const ScheduledQueryLastResults: React.FC = ({ const getPackActionId = (actionId: string, packName: string) => `pack_${packName}_${actionId}`; +interface PackViewInActionProps { + item: { + id: string; + interval: number; + }; + logsIndexPattern: IndexPattern | undefined; + packName: string; + agentIds?: string[]; +} + +const PackViewInDiscoverActionComponent: React.FC = ({ + item, + logsIndexPattern, + packName, + agentIds, +}) => { + const { id, interval } = item; + const actionId = getPackActionId(id, packName); + const { data: lastResultsData } = usePackQueryLastResults({ + actionId, + interval, + logsIndexPattern, + }); + + const startDate = lastResultsData?.['@timestamp'] + ? moment(lastResultsData?.['@timestamp'][0]).subtract(interval, 'seconds').toISOString() + : `now-${interval}s`; + const endDate = lastResultsData?.['@timestamp'] + ? moment(lastResultsData?.['@timestamp'][0]).toISOString() + : 'now'; + + return ( + + ); +}; + +const PackViewInDiscoverAction = React.memo(PackViewInDiscoverActionComponent); + +const PackViewInLensActionComponent: React.FC = ({ + item, + logsIndexPattern, + packName, + agentIds, +}) => { + const { id, interval } = item; + const actionId = getPackActionId(id, packName); + const { data: lastResultsData } = usePackQueryLastResults({ + actionId, + interval, + logsIndexPattern, + }); + + const startDate = lastResultsData?.['@timestamp'] + ? moment(lastResultsData?.['@timestamp'][0]).subtract(interval, 'seconds').toISOString() + : `now-${interval}s`; + const endDate = lastResultsData?.['@timestamp'] + ? moment(lastResultsData?.['@timestamp'][0]).toISOString() + : 'now'; + + return ( + + ); +}; + +const PackViewInLensAction = React.memo(PackViewInLensActionComponent); + interface PackQueriesStatusTableProps { agentIds?: string[]; data: OsqueryManagerPackagePolicyInputStream[]; @@ -533,6 +602,18 @@ const PackQueriesStatusTableComponent: React.FC = ( Record> >({}); + const indexPatterns = useKibana().services.data.indexPatterns; + const [logsIndexPattern, setLogsIndexPattern] = useState(undefined); + + useEffect(() => { + const fetchLogsIndexPattern = async () => { + const indexPattern = await indexPatterns.find('logs-*'); + + setLogsIndexPattern(indexPattern[0]); + }; + fetchLogsIndexPattern(); + }, [indexPatterns]); + const renderQueryColumn = useCallback( (query: string) => ( @@ -564,6 +645,7 @@ const PackQueriesStatusTableComponent: React.FC = ( const renderLastResultsColumn = useCallback( (item) => ( = ( expanded={!!itemIdToExpandedRowMap[item.id]} /> ), - [itemIdToExpandedRowMap, packName, toggleErrors] + [itemIdToExpandedRowMap, packName, toggleErrors, logsIndexPattern] ); const renderDiscoverResultsAction = useCallback( (item) => ( - ), - [agentIds, packName] + [agentIds, logsIndexPattern, packName] ); const renderLensResultsAction = useCallback( (item) => ( - ), - [agentIds, packName] + [agentIds, logsIndexPattern, packName] ); const getItemId = useCallback( diff --git a/x-pack/plugins/osquery/public/packs/packs_table.tsx b/x-pack/plugins/osquery/public/packs/packs_table.tsx index 3d4efd88b789f..dcca0e2f56596 100644 --- a/x-pack/plugins/osquery/public/packs/packs_table.tsx +++ b/x-pack/plugins/osquery/public/packs/packs_table.tsx @@ -126,7 +126,7 @@ const PacksTableComponent = () => { { field: 'policy_ids', name: i18n.translate('xpack.osquery.packs.table.policyColumnTitle', { - defaultMessage: 'Policies', + defaultMessage: 'Scheduled policies', }), truncateText: true, render: renderAgentPolicy, diff --git a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx index f6967f26cfbc2..85f4b3b3f0fad 100644 --- a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx @@ -30,6 +30,7 @@ import { EuiTitle, EuiText, EuiIcon, + EuiSuperSelect, } from '@elastic/eui'; import sqlParser from 'js-sql-parser'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -54,7 +55,9 @@ import { getUseField, fieldValidators, ValidationFuncArg, + UseMultiFields, } from '../../shared_imports'; +import { OsqueryIcon } from '../../components/osquery_icon'; export const CommonUseField = getUseField({ component: Field }); @@ -77,6 +80,35 @@ const typeMap = { constant_keyword: 'string', }; +const StyledEuiSuperSelect = styled(EuiSuperSelect)` + &.euiFormControlLayout__prepend { + padding-left: 8px; + padding-right: 24px; + box-shadow: none; + + .euiIcon { + padding: 0; + width: 18px; + background: none; + } + } +`; + +// @ts-expect-error update types +const ResultComboBox = styled(EuiComboBox)` + &.euiComboBox--prepended .euiSuperSelect { + border-right: 1px solid ${(props) => props.theme.eui.euiBorderColor}; + + .euiFormControlLayout__childrenWrapper { + border-radius: 6px 0 0 6px; + + .euiFormControlLayoutIcons--right { + right: 6px; + } + } + } +`; + const StyledFieldIcon = styled(FieldIcon)` width: 32px; @@ -90,6 +122,11 @@ const StyledFieldSpan = styled.span` padding-bottom: 0 !important; `; +// align the icon to the inputs +const StyledSemicolonWrapper = styled.div` + margin-top: 8px; +`; + // align the icon to the inputs const StyledButtonWrapper = styled.div` margin-top: 11px; @@ -115,11 +152,10 @@ interface ECSComboboxFieldProps { idAria?: string; } -export const ECSComboboxField: React.FC = ({ +const ECSComboboxFieldComponent: React.FC = ({ field, euiFieldProps = {}, idAria, - ...rest }) => { const { setValue } = field; const [selectedOptions, setSelected] = useState>>( @@ -179,6 +215,21 @@ export const ECSComboboxField: React.FC = ({ [selectedOptions] ); + const helpText = useMemo(() => { + // @ts-expect-error update types + let text = selectedOptions[0]?.value?.description; + + if (!text) return; + + // @ts-expect-error update types + const example = selectedOptions[0]?.value?.example; + if (example) { + text += ` e.g. ${JSON.stringify(example)}`; + } + + return text; + }, [selectedOptions]); + useEffect(() => { // @ts-expect-error update types setSelected(() => { @@ -193,14 +244,12 @@ export const ECSComboboxField: React.FC = ({ return ( = ({ ); }; +export const ECSComboboxField = React.memo(ECSComboboxFieldComponent); + +const OSQUERY_COLUMN_VALUE_TYPE_OPTIONS = [ + { + value: 'field', + inputDisplay: , + dropdownDisplay: ( + + + + + + + + + + + ), + }, + { + value: 'value', + inputDisplay: , + dropdownDisplay: ( + + + + + + + + + + + ), + }, +]; + interface OsqueryColumnFieldProps { - field: FieldHook; + resultType: FieldHook; + resultValue: FieldHook; euiFieldProps: EuiComboBoxProps; idAria?: string; } -export const OsqueryColumnField: React.FC = ({ - field, +const OsqueryColumnFieldComponent: React.FC = ({ + resultType, + resultValue, euiFieldProps = {}, idAria, - ...rest }) => { - const { setValue } = field; - const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); + const { setValue } = resultValue; + const { setValue: setType } = resultType; + const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(resultValue); const describedByIds = useMemo(() => (idAria ? [idAria] : []), [idAria]); const [selectedOptions, setSelected] = useState< Array> @@ -269,19 +363,51 @@ export const OsqueryColumnField: React.FC = ({ [setValue, setSelected] ); + const onTypeChange = useCallback( + (newType) => { + if (newType !== resultType.value) { + setType(newType); + } + }, + [setType, resultType.value] + ); + + const handleCreateOption = useCallback( + (newOption) => { + setValue(newOption); + }, + [setValue] + ); + + const Prepend = useMemo( + () => ( + + ), + [onTypeChange, resultType.value] + ); + useEffect(() => { setSelected(() => { - if (!field.value.length) return []; + if (!resultValue.value.length) return []; - const selectedOption = find(euiFieldProps?.options, ['label', field.value]); + const selectedOption = find(euiFieldProps?.options, ['label', resultValue.value]); - return selectedOption ? [selectedOption] : [{ label: field.value }]; + return selectedOption ? [selectedOption] : [{ label: resultValue.value }]; }); - }, [euiFieldProps?.options, setSelected, field.value]); + }, [euiFieldProps?.options, setSelected, resultValue.value]); return ( = ({ fullWidth describedByIds={describedByIds} isDisabled={euiFieldProps.isDisabled} - {...rest} > - = ({ ); }; +export const OsqueryColumnField = React.memo( + OsqueryColumnFieldComponent, + (prevProps, nextProps) => + prevProps.resultType.value === nextProps.resultType.value && + prevProps.resultType.isChangingValue === nextProps.resultType.isChangingValue && + prevProps.resultType.errors === nextProps.resultType.errors && + prevProps.resultValue.value === nextProps.resultValue.value && + prevProps.resultValue.isChangingValue === nextProps.resultValue.isChangingValue && + prevProps.resultValue.errors === nextProps.resultValue.errors && + deepEqual(prevProps.euiFieldProps, nextProps.euiFieldProps) +); + export interface ECSMappingEditorFieldRef { validate: () => Promise< | Record< @@ -344,7 +483,7 @@ const getEcsFieldValidator = )(args); // @ts-expect-error update types - if (fieldRequiredError && ((!editForm && args.formData['value.field'].length) || editForm)) { + if (fieldRequiredError && ((!editForm && args.formData['result.value'].length) || editForm)) { return fieldRequiredError; } @@ -354,7 +493,7 @@ const getEcsFieldValidator = const getOsqueryResultFieldValidator = (osquerySchemaOptions: OsquerySchemaOption[], editForm: boolean) => ( - args: ValidationFuncArg + args: ValidationFuncArg ) => { const fieldRequiredError = fieldValidators.emptyField( i18n.translate('xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldRequiredErrorMessage', { @@ -366,7 +505,8 @@ const getOsqueryResultFieldValidator = return fieldRequiredError; } - if (!args.value.length) return; + // @ts-expect-error update types + if (!args.value?.length || args.formData['result.type'] !== 'field') return; const osqueryColumnExists = find(osquerySchemaOptions, ['label', args.value]); @@ -383,6 +523,7 @@ const getOsqueryResultFieldValidator = }, } ), + __isBlocking__: false, } : undefined; }; @@ -395,7 +536,8 @@ const FORM_DEFAULT_VALUE = { interface ECSMappingEditorFormData { key: string; value: { - field: string; + field?: string; + value?: string; }; } @@ -413,27 +555,44 @@ export const ECSMappingEditorForm = forwardRef ({ + key: data.key ?? '', + result: { + type: data.value + ? Object.keys(data.value)[0] + : OSQUERY_COLUMN_VALUE_TYPE_OPTIONS[0].value, + value: data.value ? Object.values(data.value)[0] : '', + }, + }), }); const { submit, reset, validate, __validateFields } = form; @@ -442,17 +601,25 @@ export const ECSMappingEditorForm = forwardRef { validate(); - __validateFields(['value.field']); + __validateFields(['result.value']); const { data, isValid } = await submit(); if (isValid) { + const serializedData = { + key: data.key, + value: { + [data.result.type]: data.result.value, + }, + }; if (onAdd) { - onAdd(data); + onAdd(serializedData); + } + if (onChange) { + onChange(serializedData); } reset(); } - return { data, isValid }; - }, [validate, __validateFields, submit, onAdd, reset]); + }, [validate, __validateFields, submit, onAdd, onChange, reset]); const handleDeleteClick = useCallback(() => { if (defaultValue?.key && onDelete) { @@ -460,6 +627,37 @@ export const ECSMappingEditorForm = forwardRef ( + + {(fields) => ( + + )} + + ), + [osquerySchemaOptions, isDisabled] + ); + + const ecsComboBoxEuiFieldProps = useMemo(() => ({ isDisabled }), [isDisabled]); + useImperativeHandle( ref, () => ({ @@ -468,35 +666,37 @@ export const ECSMappingEditorForm = forwardRef { - if (onAdd && !deepEqual(formData, currentFormData.current)) { + if (!deepEqual(formData, currentFormData.current)) { currentFormData.current = formData; handleSubmit(); } }, [handleSubmit, formData, onAdd]); - useEffect(() => { - if (onChange && !deepEqual(formData, currentFormData.current)) { - currentFormData.current = formData; - onChange(formData); - } - }, [defaultValue, formData, handleDeleteClick, onChange]); - - useEffect(() => { - if (defaultValue) { - validate(); - __validateFields(['value.field']); - } - }, [defaultValue, osquerySchemaOptions, validate, __validateFields]); + // useEffect(() => { + // if (defaultValue) { + // validate(); + // __validateFields(['result.value']); + // } + // }, [defaultValue, osquerySchemaOptions, validate, __validateFields]); return (
@@ -507,30 +707,19 @@ export const ECSMappingEditorForm = forwardRef - - - + + : + - - - + {MultiFields} {!isDisabled && ( @@ -578,179 +767,175 @@ interface OsqueryColumn { index: boolean; } -export const ECSMappingEditorField = ({ - field, - query, - fieldRef, - euiFieldProps, -}: ECSMappingEditorFieldProps) => { - const { setValue, value = {} } = field; - const [osquerySchemaOptions, setOsquerySchemaOptions] = useState([]); - const formRefs = useRef>({}); - - useImperativeHandle( - fieldRef, - () => ({ - validate: async () => { - const validations = await Promise.all( - Object.values(formRefs.current).map(async (formRef) => { - const { data, isValid } = await formRef.validate(); - return [data, isValid]; - }) - ); +export const ECSMappingEditorField = React.memo( + ({ field, query, fieldRef, euiFieldProps }: ECSMappingEditorFieldProps) => { + const { setValue, value = {} } = field; + const [osquerySchemaOptions, setOsquerySchemaOptions] = useState([]); + const formRefs = useRef>({}); - if (find(validations, (result) => result[1] === false)) { - return false; - } - - return deepmerge.all(map(validations, '[0]')); - }, - }), - [] - ); + useImperativeHandle( + fieldRef, + () => ({ + validate: async () => { + const validations = await Promise.all( + Object.values(formRefs.current).map(async (formRef) => { + const { data, isValid } = await formRef.validate(); + return [data, isValid]; + }) + ); + + if (find(validations, (result) => result[1] === false)) { + return false; + } - useEffect(() => { - setOsquerySchemaOptions((currentValue) => { - if (!query?.length) { - return currentValue; - } + return deepmerge.all(map(validations, '[0]')); + }, + }), + [] + ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let ast: Record | undefined; + useEffect(() => { + setOsquerySchemaOptions((currentValue) => { + if (!query?.length) { + return currentValue; + } - try { - ast = sqlParser.parse(query)?.value; - } catch (e) { - return currentValue; - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let ast: Record | undefined; - const astOsqueryTables: Record< - string, - { - columns: OsqueryColumn[]; - order: number; + try { + ast = sqlParser.parse(query)?.value; + } catch (e) { + return currentValue; } - > = - ast?.from?.value?.reduce( - ( - acc: { - [x: string]: { - columns: OsqueryColumn[]; - order: number; - }; - }, - table: { - value: { - left?: { value: { value: string }; alias?: { value: string } }; - right?: { value: { value: string }; alias?: { value: string } }; - value?: { value: string }; - alias?: { value: string }; - }; - } - ) => { - each(['value.left', 'value.right', 'value'], (valueKey) => { - if (valueKey) { - const osqueryTable = find(osquerySchema, [ - 'name', - get(table, `${valueKey}.value.value`), - ]); - - if (osqueryTable) { - acc[ - get(table, `${valueKey}.alias.value`) ?? get(table, `${valueKey}.value.value`) - ] = { - columns: osqueryTable.columns, - order: Object.keys(acc).length, - }; - } + + const astOsqueryTables: Record< + string, + { + columns: OsqueryColumn[]; + order: number; + } + > = + ast?.from?.value?.reduce( + ( + acc: { + [x: string]: { + columns: OsqueryColumn[]; + order: number; + }; + }, + table: { + value: { + left?: { value: { value: string }; alias?: { value: string } }; + right?: { value: { value: string }; alias?: { value: string } }; + value?: { value: string }; + alias?: { value: string }; + }; } - }); + ) => { + each(['value.left', 'value.right', 'value'], (valueKey) => { + if (valueKey) { + const osqueryTable = find(osquerySchema, [ + 'name', + get(table, `${valueKey}.value.value`), + ]); + + if (osqueryTable) { + acc[ + get(table, `${valueKey}.alias.value`) ?? get(table, `${valueKey}.value.value`) + ] = { + columns: osqueryTable.columns, + order: Object.keys(acc).length, + }; + } + } + }); - return acc; - }, - {} - ) ?? {}; + return acc; + }, + {} + ) ?? {}; - // Table doesn't exist in osquery schema - if (isEmpty(astOsqueryTables)) { - return currentValue; - } + // Table doesn't exist in osquery schema + if (isEmpty(astOsqueryTables)) { + return currentValue; + } - const suggestions = - isArray(ast?.selectItems?.value) && - ast?.selectItems?.value - ?.map((selectItem: { type: string; value: string; hasAs: boolean; alias?: string }) => { - if (selectItem.type === 'Identifier') { - /* + const suggestions = + isArray(ast?.selectItems?.value) && + ast?.selectItems?.value + ?.map((selectItem: { type: string; value: string; hasAs: boolean; alias?: string }) => { + if (selectItem.type === 'Identifier') { + /* select * from routes, uptime; */ - if (ast?.selectItems?.value.length === 1 && selectItem.value === '*') { - return reduce( - astOsqueryTables, - (acc, { columns: osqueryColumns, order: tableOrder }, table) => { - acc.push( - ...osqueryColumns.map((osqueryColumn) => ({ - label: osqueryColumn.name, - value: { - name: osqueryColumn.name, - description: osqueryColumn.description, - table, - tableOrder, - suggestion_label: osqueryColumn.name, - }, - })) - ); - return acc; - }, - [] as OsquerySchemaOption[] - ); - } + if (ast?.selectItems?.value.length === 1 && selectItem.value === '*') { + return reduce( + astOsqueryTables, + (acc, { columns: osqueryColumns, order: tableOrder }, table) => { + acc.push( + ...osqueryColumns.map((osqueryColumn) => ({ + label: osqueryColumn.name, + value: { + name: osqueryColumn.name, + description: osqueryColumn.description, + table, + tableOrder, + suggestion_label: osqueryColumn.name, + }, + })) + ); + return acc; + }, + [] as OsquerySchemaOption[] + ); + } - /* + /* select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid; */ - const [table, column] = selectItem.value.includes('.') - ? selectItem.value?.split('.') - : [Object.keys(astOsqueryTables)[0], selectItem.value]; - - if (column === '*' && astOsqueryTables[table]) { - const { columns: osqueryColumns, order: tableOrder } = astOsqueryTables[table]; - return osqueryColumns.map((osqueryColumn) => ({ - label: osqueryColumn.name, - value: { - name: osqueryColumn.name, - description: osqueryColumn.description, - table, - tableOrder, - suggestion_label: `${osqueryColumn.name}`, - }, - })); - } + const [table, column] = selectItem.value.includes('.') + ? selectItem.value?.split('.') + : [Object.keys(astOsqueryTables)[0], selectItem.value]; + + if (column === '*' && astOsqueryTables[table]) { + const { columns: osqueryColumns, order: tableOrder } = astOsqueryTables[table]; + return osqueryColumns.map((osqueryColumn) => ({ + label: osqueryColumn.name, + value: { + name: osqueryColumn.name, + description: osqueryColumn.description, + table, + tableOrder, + suggestion_label: `${osqueryColumn.name}`, + }, + })); + } + + if (astOsqueryTables[table]) { + const osqueryColumn = find(astOsqueryTables[table].columns, ['name', column]); + + if (osqueryColumn) { + const label = selectItem.hasAs ? selectItem.alias : column; - if (astOsqueryTables[table]) { - const osqueryColumn = find(astOsqueryTables[table].columns, ['name', column]); - - if (osqueryColumn) { - const label = selectItem.hasAs ? selectItem.alias : column; - - return [ - { - label, - value: { - name: osqueryColumn.name, - description: osqueryColumn.description, - table, - tableOrder: astOsqueryTables[table].order, - suggestion_label: `${label}`, + return [ + { + label, + value: { + name: osqueryColumn.name, + description: osqueryColumn.description, + table, + tableOrder: astOsqueryTables[table].order, + suggestion_label: `${label}`, + }, }, - }, - ]; + ]; + } } } - } - /* + /* SELECT pid, uid, name, ROUND(( (user_time + system_time) / (cpu_time.tsb - cpu_time.itsb) ) * 100, 2) AS percentage @@ -764,161 +949,166 @@ export const ECSMappingEditorField = ({ LIMIT 5; */ - if (selectItem.hasAs && selectItem.alias) { - return [ - { - label: selectItem.alias, - value: { - name: selectItem.alias, - description: '', - table: '', - tableOrder: -1, - suggestion_label: selectItem.alias, + if (selectItem.hasAs && selectItem.alias) { + return [ + { + label: selectItem.alias, + value: { + name: selectItem.alias, + description: '', + table: '', + tableOrder: -1, + suggestion_label: selectItem.alias, + }, }, - }, - ]; - } + ]; + } - return []; - }) - .flat(); + return []; + }) + .flat(); - // Remove column duplicates by keeping the column from the table that appears last in the query - return sortedUniqBy( - orderBy(suggestions, ['value.suggestion_label', 'value.tableOrder'], ['asc', 'desc']), - 'label' - ); - }); - }, [query]); - - const handleAddRow = useCallback( - (newRow) => { - if (newRow?.key && newRow?.value) { - setValue( - produce((draft) => { - draft[newRow.key] = newRow.value; - return draft; - }) + // Remove column duplicates by keeping the column from the table that appears last in the query + return sortedUniqBy( + orderBy(suggestions, ['value.suggestion_label', 'value.tableOrder'], ['asc', 'desc']), + 'label' ); - } - }, - [setValue] - ); + }); + }, [query]); + + const handleAddRow = useCallback( + (newRow) => { + if (newRow?.key && newRow?.value) { + setValue( + produce((draft) => { + draft[newRow.key] = newRow.value; + return draft; + }) + ); + } + }, + [setValue] + ); - const handleUpdateRow = useCallback( - (currentKey: string) => (updatedRow: FormData) => { - if (updatedRow?.key && updatedRow?.value) { - setValue( - produce((draft) => { - if (currentKey !== updatedRow.key) { - delete draft[currentKey]; - } + const handleUpdateRow = useCallback( + (currentKey: string) => (updatedRow: FormData) => { + if (updatedRow?.key && updatedRow?.value) { + setValue( + produce((draft) => { + if (currentKey !== updatedRow.key) { + delete draft[currentKey]; + } - draft[updatedRow.key] = updatedRow.value; + draft[updatedRow.key] = updatedRow.value; - return draft; - }) - ); - } - }, - [setValue] - ); + return draft; + }) + ); + } + }, + [setValue] + ); - const handleDeleteRow = useCallback( - (key) => { - if (key) { - setValue( - produce((draft) => { - if (draft[key]) { - delete draft[key]; - } - return draft; - }) - ); + const handleDeleteRow = useCallback( + (key) => { + if (key) { + setValue( + produce((draft) => { + if (draft[key]) { + delete draft[key]; + } + return draft; + }) + ); - if (formRefs.current[key]) { - delete formRefs.current[key]; + if (formRefs.current[key]) { + delete formRefs.current[key]; + } } - } - }, - [setValue] - ); + }, + [setValue] + ); - return ( - <> - - - -
+ return ( + <> + + + +
+ +
+
+ -
-
- - - -
-
- - - - - - - - - - - - - - - {Object.entries(value).map(([ecsKey, ecsValue]) => ( - +
+
+ + + + + + + + + + + + + + + {Object.entries(value).map(([ecsKey, ecsValue]) => ( + { - if (formRef) { - formRefs.current[ecsKey] = formRef; - } - }} - key={ecsKey} - osquerySchemaOptions={osquerySchemaOptions} - // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - defaultValue={{ - key: ecsKey, - value: ecsValue, - }} - onChange={handleUpdateRow(ecsKey)} - onDelete={handleDeleteRow} - isDisabled={!!euiFieldProps?.isDisabled} - /> - ))} - {!euiFieldProps?.isDisabled && ( - + ))} + {!euiFieldProps?.isDisabled && ( + { - if (formRef) { - formRefs.current.new = formRef; - } - }} - osquerySchemaOptions={osquerySchemaOptions} - onAdd={handleAddRow} - /> - )} - - ); -}; + if (formRef) { + formRefs.current.new = formRef; + } + }} + osquerySchemaOptions={osquerySchemaOptions} + onAdd={handleAddRow} + /> + )} + + ); + }, + (prevProps, nextProps) => + prevProps.field.value === nextProps.field.value && + prevProps.query === nextProps.query && + deepEqual(prevProps.euiFieldProps, nextProps.euiFieldProps) +); // eslint-disable-next-line import/no-default-export export default ECSMappingEditorField; diff --git a/x-pack/plugins/osquery/public/packs/use_create_pack.ts b/x-pack/plugins/osquery/public/packs/use_create_pack.ts index 05756afde40d8..41104361cc4a3 100644 --- a/x-pack/plugins/osquery/public/packs/use_create_pack.ts +++ b/x-pack/plugins/osquery/public/packs/use_create_pack.ts @@ -29,7 +29,7 @@ export const useCreatePack = ({ withRedirect }: UseCreatePackProps) => { return useMutation( (payload) => - http.post('/internal/osquery/packs', { + http.post('/internal/osquery/packs', { body: JSON.stringify(payload), }), { diff --git a/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts b/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts index af3e5b23e80f8..cb84386dbe3ea 100644 --- a/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts +++ b/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts @@ -6,6 +6,7 @@ */ import { useQuery } from 'react-query'; +import moment from 'moment-timezone'; import { IndexPattern } from '../../../../../src/plugins/data/common'; import { useKibana } from '../common/lib/kibana'; @@ -46,13 +47,12 @@ export const usePackQueryLastResults = ({ }); const lastResultsResponse = await lastResultsSearchSource.fetch$().toPromise(); + const timestamp = lastResultsResponse.rawResponse?.hits?.hits[0]?.fields?.['@timestamp'][0]; - const responseId = lastResultsResponse.rawResponse?.hits?.hits[0]?._source?.response_id; - - if (responseId) { + if (timestamp) { const aggsSearchSource = await data.search.searchSource.create({ index: logsIndexPattern, - size: 0, + size: 1, aggs: { unique_agents: { cardinality: { field: 'agent.id' } }, }, @@ -61,13 +61,16 @@ export const usePackQueryLastResults = ({ bool: { filter: [ { - match_phrase: { - action_id: actionId, + range: { + '@timestamp': { + gte: moment(timestamp).subtract(interval, 'seconds').format(), + lte: moment(timestamp).format(), + }, }, }, { match_phrase: { - response_id: responseId, + action_id: actionId, }, }, ], @@ -81,7 +84,7 @@ export const usePackQueryLastResults = ({ '@timestamp': lastResultsResponse.rawResponse?.hits?.hits[0]?.fields?.['@timestamp'], // @ts-expect-error update types uniqueAgentsCount: aggsResponse.rawResponse.aggregations?.unique_agents?.value, - docCount: aggsResponse.rawResponse?.hits?.total, + docCount: aggsResponse?.rawResponse?.hits?.total, }; } diff --git a/x-pack/plugins/osquery/public/packs/use_packs.ts b/x-pack/plugins/osquery/public/packs/use_packs.ts index 9870cb481450f..72dbf4115247d 100644 --- a/x-pack/plugins/osquery/public/packs/use_packs.ts +++ b/x-pack/plugins/osquery/public/packs/use_packs.ts @@ -22,7 +22,7 @@ export const usePacks = ({ return useQuery( [PACKS_ID, { pageIndex, pageSize, sortField, sortDirection }], async () => - http.get('/internal/osquery/packs', { + http.get('/internal/osquery/packs', { query: { pageIndex, pageSize, sortField, sortDirection }, }), { diff --git a/x-pack/plugins/osquery/public/packs/use_update_pack.ts b/x-pack/plugins/osquery/public/packs/use_update_pack.ts index d9aecbe9ac598..d7a0ccf7269ea 100644 --- a/x-pack/plugins/osquery/public/packs/use_update_pack.ts +++ b/x-pack/plugins/osquery/public/packs/use_update_pack.ts @@ -32,7 +32,7 @@ export const useUpdatePack = ({ withRedirect, options }: UseUpdatePackProps) => return useMutation( // @ts-expect-error update types ({ id, ...payload }) => - http.put(`/internal/osquery/packs/${id}`, { + http.put(`/internal/osquery/packs/${id}`, { body: JSON.stringify(payload), }), { diff --git a/x-pack/plugins/osquery/public/results/results_table.tsx b/x-pack/plugins/osquery/public/results/results_table.tsx index 5b8143c874e2b..d1d16730e7982 100644 --- a/x-pack/plugins/osquery/public/results/results_table.tsx +++ b/x-pack/plugins/osquery/public/results/results_table.tsx @@ -291,19 +291,9 @@ const ResultsTableComponent: React.FC = ({ setIsLive(() => { if (!agentIds?.length || expired) return false; - const uniqueAgentsRepliedCount = - // @ts-expect-error-type - allResultsData?.rawResponse.aggregations?.unique_agents.value ?? 0; - - return !!(uniqueAgentsRepliedCount !== agentIds?.length - aggregations.failed); + return !!(aggregations.totalResponded !== agentIds?.length); }), - [ - agentIds?.length, - aggregations.failed, - // @ts-expect-error-type - allResultsData?.rawResponse.aggregations?.unique_agents.value, - expired, - ] + [agentIds?.length, aggregations.failed, aggregations.totalResponded, expired] ); if (!hasActionResultsPrivileges) { @@ -328,7 +318,7 @@ const ResultsTableComponent: React.FC = ({ <> {isLive && } - {isFetched && !allResultsData?.edges.length ? ( + {isFetched && !allResultsData?.edges.length && !aggregations?.totalRowCount ? ( <> diff --git a/x-pack/plugins/osquery/public/routes/packs/list/index.tsx b/x-pack/plugins/osquery/public/routes/packs/list/index.tsx index 945677cade577..6f084e9e6bf25 100644 --- a/x-pack/plugins/osquery/public/routes/packs/list/index.tsx +++ b/x-pack/plugins/osquery/public/routes/packs/list/index.tsx @@ -27,6 +27,16 @@ const PacksPageComponent = () => {
+ + +

+ +

+
+
), [] diff --git a/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts b/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts index c736cdf9c3545..a8061fd9a5cce 100644 --- a/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts +++ b/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts @@ -29,7 +29,7 @@ export const useCreateSavedQuery = ({ withRedirect }: UseCreateSavedQueryProps) return useMutation( (payload) => - http.post('/internal/osquery/saved_query', { + http.post('/internal/osquery/saved_query', { body: JSON.stringify(payload), }), { diff --git a/x-pack/plugins/osquery/public/saved_queries/use_saved_queries.ts b/x-pack/plugins/osquery/public/saved_queries/use_saved_queries.ts index 22ed81a62a5b3..9de40c759c2cf 100644 --- a/x-pack/plugins/osquery/public/saved_queries/use_saved_queries.ts +++ b/x-pack/plugins/osquery/public/saved_queries/use_saved_queries.ts @@ -24,7 +24,8 @@ export const useSavedQueries = ({ return useQuery( [SAVED_QUERIES_ID, { pageIndex, pageSize, sortField, sortDirection }], () => - http.get('/internal/osquery/saved_query', { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + http.get('/internal/osquery/saved_query', { query: { pageIndex, pageSize, sortField, sortDirection }, }), { @@ -36,6 +37,7 @@ export const useSavedQueries = ({ toastMessage: error.body.message, }); }, + refetchOnWindowFocus: !!isLive, } ); }; diff --git a/x-pack/plugins/osquery/public/saved_queries/use_saved_query.ts b/x-pack/plugins/osquery/public/saved_queries/use_saved_query.ts index 04d7a9b505372..f05f38b8259ce 100644 --- a/x-pack/plugins/osquery/public/saved_queries/use_saved_query.ts +++ b/x-pack/plugins/osquery/public/saved_queries/use_saved_query.ts @@ -26,9 +26,11 @@ export const useSavedQuery = ({ savedQueryId }: UseSavedQueryProps) => { return useQuery( [SAVED_QUERY_ID, { savedQueryId }], - () => http.get(`/internal/osquery/saved_query/${savedQueryId}`), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + () => http.get(`/internal/osquery/saved_query/${savedQueryId}`), { keepPreviousData: true, + refetchOnWindowFocus: false, onSuccess: (data) => { if (data.error) { setErrorToast(data.error, { diff --git a/x-pack/plugins/osquery/public/saved_queries/use_update_saved_query.ts b/x-pack/plugins/osquery/public/saved_queries/use_update_saved_query.ts index b2e23163a74c8..cc35654d50d54 100644 --- a/x-pack/plugins/osquery/public/saved_queries/use_update_saved_query.ts +++ b/x-pack/plugins/osquery/public/saved_queries/use_update_saved_query.ts @@ -29,7 +29,7 @@ export const useUpdateSavedQuery = ({ savedQueryId }: UseUpdateSavedQueryProps) return useMutation( (payload) => - http.put(`/internal/osquery/saved_query/${savedQueryId}`, { + http.put(`/internal/osquery/saved_query/${savedQueryId}`, { body: JSON.stringify(payload), }), { diff --git a/x-pack/plugins/osquery/scripts/schema_formatter/ecs_formatter.ts b/x-pack/plugins/osquery/scripts/schema_formatter/ecs_formatter.ts index e53750080ef76..07f02a892999c 100644 --- a/x-pack/plugins/osquery/scripts/schema_formatter/ecs_formatter.ts +++ b/x-pack/plugins/osquery/scripts/schema_formatter/ecs_formatter.ts @@ -11,7 +11,7 @@ import path from 'path'; import { run } from '@kbn/dev-utils'; -const ECS_COLUMN_SCHEMA_FIELDS = ['field', 'type', 'description']; +const ECS_COLUMN_SCHEMA_FIELDS = ['field', 'type', 'normalization', 'example', 'description']; const RESTRICTED_FIELDS = [ 'agent.name', diff --git a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts index a633fe4923aeb..fb2c834f3c74d 100644 --- a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts +++ b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts @@ -53,6 +53,11 @@ export const savedQueryType: SavedObjectsType = { hidden: false, namespaceType: 'multiple-isolated', mappings: savedQuerySavedObjectMappings, + management: { + defaultSearchField: 'id', + importableAndExportable: true, + getTitle: (savedObject) => savedObject.attributes.id, + }, }; export const packSavedObjectMappings: SavedObjectsType['mappings'] = { @@ -109,4 +114,9 @@ export const packType: SavedObjectsType = { hidden: false, namespaceType: 'multiple-isolated', mappings: packSavedObjectMappings, + management: { + defaultSearchField: 'name', + importableAndExportable: true, + getTitle: (savedObject) => savedObject.attributes.name, + }, }; diff --git a/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts index 3308a8023dd9e..a84ec5a262a64 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts @@ -26,7 +26,7 @@ export const readSavedQueryRoute = (router: IRouter) => { const savedObjectsClient = context.core.savedObjects.client; const savedQuery = await savedObjectsClient.get<{ - ecs_mapping: Array<{ field: string; value: string }>; + ecs_mapping: Array<{ key: string; value: Record }>; }>(savedQuerySavedObjectType, request.params.id); if (savedQuery.attributes.ecs_mapping) { diff --git a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts index c0148087ee8c9..b34999204b8a3 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts @@ -34,7 +34,8 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp schema.recordOf( schema.string(), schema.object({ - field: schema.string(), + field: schema.maybe(schema.string()), + value: schema.maybe(schema.string()), }) ) ), diff --git a/x-pack/plugins/osquery/server/routes/utils.ts b/x-pack/plugins/osquery/server/routes/utils.ts index 136cbc190e46c..62464ec5d6336 100644 --- a/x-pack/plugins/osquery/server/routes/utils.ts +++ b/x-pack/plugins/osquery/server/routes/utils.ts @@ -5,22 +5,24 @@ * 2.0. */ -import { pick, reduce } from 'lodash'; +import { reduce } from 'lodash'; export const convertECSMappingToArray = (ecsMapping: Record | undefined) => ecsMapping ? Object.entries(ecsMapping).map((item) => ({ - value: item[0], - ...item[1], + key: item[0], + value: item[1], })) : undefined; -export const convertECSMappingToObject = (ecsMapping: Array<{ field: string; value: string }>) => +export const convertECSMappingToObject = ( + ecsMapping: Array<{ key: string; value: Record }> +) => reduce( ecsMapping, (acc, value) => { - acc[value.value] = pick(value, 'field'); + acc[value.key] = value.value; return acc; }, - {} as Record + {} as Record ); diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts index 109e260911933..96d5ad60cd54c 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts @@ -46,6 +46,11 @@ export const buildActionResultsQuery = ({ }, }, aggs: { + rows_count: { + sum: { + field: 'action_response.osquery.count', + }, + }, responses: { terms: { script: { diff --git a/x-pack/plugins/painless_lab/public/application/hooks/use_submit_code.ts b/x-pack/plugins/painless_lab/public/application/hooks/use_submit_code.ts index f182ff2f3302b..11cde8ad03d57 100644 --- a/x-pack/plugins/painless_lab/public/application/hooks/use_submit_code.ts +++ b/x-pack/plugins/painless_lab/public/application/hooks/use_submit_code.ts @@ -31,7 +31,7 @@ export const useSubmitCode = (http: HttpSetup) => { const requestId = ++currentRequestIdRef.current; try { - const result = await http.post(`${API_BASE_PATH}/execute`, { + const result = await http.post(`${API_BASE_PATH}/execute`, { // Stringify the string, because http runs it through JSON.parse, and we want to actually // send a JSON string. body: JSON.stringify(formatRequestPayload(config, PayloadFormat.UGLY)), diff --git a/x-pack/plugins/remote_clusters/public/application/services/api_errors.ts b/x-pack/plugins/remote_clusters/public/application/services/api_errors.ts index 190c6c16e1477..1f10478bf3543 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/api_errors.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/api_errors.ts @@ -8,7 +8,13 @@ import { IHttpFetchError } from 'kibana/public'; import { toasts, fatalError } from './notification'; -function createToastConfig(error: IHttpFetchError, errorTitle: string) { +interface CommonErrorBody { + statusCode: number; + message: string; + error: string; +} + +function createToastConfig(error: IHttpFetchError, errorTitle: string) { // Expect an error in the shape provided by http service. if (error && error.body) { const { error: errorString, statusCode, message } = error.body; @@ -19,7 +25,7 @@ function createToastConfig(error: IHttpFetchError, errorTitle: string) { } } -export function showApiWarning(error: IHttpFetchError, errorTitle: string) { +export function showApiWarning(error: IHttpFetchError, errorTitle: string) { const toastConfig = createToastConfig(error, errorTitle); if (toastConfig) { @@ -31,7 +37,7 @@ export function showApiWarning(error: IHttpFetchError, errorTitle: string) { return fatalError.add(error, errorTitle); } -export function showApiError(error: IHttpFetchError, errorTitle: string) { +export function showApiError(error: IHttpFetchError, errorTitle: string) { const toastConfig = createToastConfig(error, errorTitle); if (toastConfig) { diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts index 7a391368f65b3..b27c2a65be963 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts @@ -87,7 +87,7 @@ export class ReportingAPIClient implements IReportingAPI { } public async deleteReport(jobId: string) { - return await this.http.delete(`${API_LIST_URL}/delete/${jobId}`, { + return await this.http.delete(`${API_LIST_URL}/delete/${jobId}`, { asSystemRequest: true, }); } @@ -108,7 +108,7 @@ export class ReportingAPIClient implements IReportingAPI { } public async total() { - return await this.http.get(`${API_LIST_URL}/count`, { + return await this.http.get(`${API_LIST_URL}/count`, { asSystemRequest: true, }); } @@ -196,13 +196,13 @@ export class ReportingAPIClient implements IReportingAPI { public getServerBasePath = () => this.http.basePath.serverBasePath; public verifyBrowser() { - return this.http.post(`${API_BASE_URL}/diagnose/browser`, { + return this.http.post(`${API_BASE_URL}/diagnose/browser`, { asSystemRequest: true, }); } public verifyScreenCapture() { - return this.http.post(`${API_BASE_URL}/diagnose/screenshot`, { + return this.http.post(`${API_BASE_URL}/diagnose/screenshot`, { asSystemRequest: true, }); } diff --git a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx index fbfaeab9bc4f2..b55b7e636472c 100644 --- a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx +++ b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx @@ -144,7 +144,7 @@ export class ReportingCsvPanelAction implements ActionDefinition this.isDownloading = false; const download = `${savedSearch.title}.csv`; - const blob = new Blob([rawResponse], { type: 'text/csv;charset=utf-8;' }); + const blob = new Blob([rawResponse as BlobPart], { type: 'text/csv;charset=utf-8;' }); // Hack for IE11 Support if (window.navigator.msSaveOrOpenBlob) { diff --git a/x-pack/plugins/rollup/public/crud_app/services/api_errors.ts b/x-pack/plugins/rollup/public/crud_app/services/api_errors.ts index 2749e165e1568..a2adfd7a38529 100644 --- a/x-pack/plugins/rollup/public/crud_app/services/api_errors.ts +++ b/x-pack/plugins/rollup/public/crud_app/services/api_errors.ts @@ -8,7 +8,14 @@ import { IHttpFetchError } from 'src/core/public'; import { getNotifications, getFatalErrors } from '../../kibana_services'; -function createToastConfig(error: IHttpFetchError, errorTitle: string) { +function createToastConfig( + error: IHttpFetchError<{ + statusCode: number; + message: string; + error: string; + }>, + errorTitle: string +) { if (error && error.body) { // Error body shape is defined by the API. const { error: errorString, statusCode, message } = error.body; @@ -20,7 +27,14 @@ function createToastConfig(error: IHttpFetchError, errorTitle: string) { } } -export function showApiWarning(error: IHttpFetchError, errorTitle: string) { +export function showApiWarning( + error: IHttpFetchError<{ + statusCode: number; + message: string; + error: string; + }>, + errorTitle: string +) { const toastConfig = createToastConfig(error, errorTitle); if (toastConfig) { @@ -32,7 +46,14 @@ export function showApiWarning(error: IHttpFetchError, errorTitle: string) { return getFatalErrors().add(error, errorTitle); } -export function showApiError(error: IHttpFetchError, errorTitle: string) { +export function showApiError( + error: IHttpFetchError<{ + statusCode: number; + message: string; + error: string; + }>, + errorTitle: string +) { const toastConfig = createToastConfig(error, errorTitle); if (toastConfig) { diff --git a/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts b/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts index aba51c5aedecc..c27ca90e6e2f2 100644 --- a/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts +++ b/x-pack/plugins/searchprofiler/public/application/hooks/use_request_profile.ts @@ -66,7 +66,10 @@ export const useRequestProfile = () => { } try { - const resp = await http.post('../api/searchprofiler/profile', { + const resp = await http.post< + | { ok: true; resp: { profile: { shards: ShardSerialized[] } } } + | { ok: false; err: { msg: string } } + >('../api/searchprofiler/profile', { body: JSON.stringify(payload), headers: { 'Content-Type': 'application/json' }, }); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 4c71dcd935ff9..10e1729dbd34b 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -224,7 +224,7 @@ function useRole( function useSpaces(http: HttpStart, fatalErrors: FatalErrorsSetup) { const [spaces, setSpaces] = useState<{ enabled: boolean; list: Space[] } | null>(null); useEffect(() => { - http.get('/api/spaces/space').then( + http.get('/api/spaces/space').then( (fetchedSpaces) => setSpaces({ enabled: true, list: fetchedSpaces }), (err: IHttpFetchError) => { // Spaces plugin can be disabled and hence this endpoint can be unavailable. diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts index 0f05dffe65156..3506d2c22ce3f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts @@ -11,6 +11,7 @@ import semverGte from 'semver/functions/gte'; import { CoreStart, HttpStart } from 'kibana/public'; import { ActivityLog, + GetHostPolicyResponse, HostInfo, HostIsolationRequestBody, HostIsolationResponse, @@ -577,9 +578,10 @@ async function loadEndpointDetails({ // call the policy response api try { - const policyResponse = await coreStart.http.get(BASE_POLICY_RESPONSE_ROUTE, { - query: { agentId: selectedEndpoint }, - }); + const policyResponse = await coreStart.http.get( + BASE_POLICY_RESPONSE_ROUTE, + { query: { agentId: selectedEndpoint } } + ); dispatch({ type: 'serverReturnedEndpointPolicyResponse', payload: policyResponse, @@ -610,7 +612,7 @@ async function endpointDetailsMiddleware({ if (listData(getState()).length === 0) { const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(getState()); try { - const response = await coreStart.http.post(HOST_METADATA_LIST_ROUTE, { + const response = await coreStart.http.post(HOST_METADATA_LIST_ROUTE, { body: JSON.stringify({ paging_properties: [{ page_index: pageIndex }, { page_size: pageSize }], }), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts index 744742f64eb4a..2362a6a392a56 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts @@ -34,7 +34,7 @@ const convertToLegacyAlert = (alert: RACAlert) => * Formats alerts before sending to `scheduleActions`. We augment the context with * the equivalent "legacy" alert context so that pre-8.0 actions will continue to work. */ -const formatAlertsForNotificationActions = (alerts: unknown[]) => { +const formatAlertsForNotificationActions = (alerts: unknown[]): unknown[] => { return alerts.map((alert) => isRACAlert(alert) ? { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts index efdaf2377872c..018220e400937 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts @@ -69,4 +69,21 @@ describe('Expand Dotted', () => { flat: 'yep', }); }); + + it('expands non dotted field without changing it other than reference', () => { + const simpleDottedObj = { + test: { value: '123' }, + }; + expect(expandDottedObject(simpleDottedObj)).toEqual(simpleDottedObj); + }); + + it('expands empty object without changing it other than reference', () => { + const simpleDottedObj = {}; + expect(expandDottedObject(simpleDottedObj)).toEqual(simpleDottedObj); + }); + + it('if we allow arrays as a type, it should not touch them', () => { + const simpleDottedObj: string[] = ['hello']; + expect(expandDottedObject(simpleDottedObj)).toEqual(simpleDottedObj); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts index 69a9cb8236cbc..f90f589486ff5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts @@ -45,6 +45,9 @@ const expandDottedField = (dottedFieldName: string, val: unknown): object => { * } */ export const expandDottedObject = (dottedObj: object) => { + if (Array.isArray(dottedObj)) { + return dottedObj; + } return Object.entries(dottedObj).reduce( (acc, [key, val]) => merge(acc, expandDottedField(key, val)), {} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 48def86203e95..8da9267daabac 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -8,6 +8,7 @@ import moment from 'moment'; import sinon from 'sinon'; import { TransportResult } from '@elastic/elasticsearch'; +import { ALERT_UUID } from '@kbn/rule-data-utils'; import { alertsMock, AlertServicesMock } from '../../../../../alerting/server/mocks'; import { listMock } from '../../../../../lists/server/mocks'; @@ -41,6 +42,7 @@ import { getValidDateFromDoc, calculateTotal, getTotalHitsValue, + isRACAlert, } from './utils'; import { BulkResponseErrorAggregation, SearchAfterAndBulkCreateReturnType } from './types'; import { @@ -1519,4 +1521,52 @@ describe('utils', () => { expect(calculateTotal(undefined, 2)).toBe(-1); }); }); + + describe('isRACAlert', () => { + test('alert with dotted fields returns true', () => { + expect( + isRACAlert({ + [ALERT_UUID]: '123', + }) + ).toEqual(true); + }); + + test('alert with nested fields returns true', () => { + expect( + isRACAlert({ + kibana: { + alert: { uuid: '123' }, + }, + }) + ).toEqual(true); + }); + + test('undefined returns false', () => { + expect(isRACAlert(undefined)).toEqual(false); + }); + + test('null returns false', () => { + expect(isRACAlert(null)).toEqual(false); + }); + + test('number returns false', () => { + expect(isRACAlert(5)).toEqual(false); + }); + + test('string returns false', () => { + expect(isRACAlert('a')).toEqual(false); + }); + + test('array returns false', () => { + expect(isRACAlert([])).toEqual(false); + }); + + test('empty object returns false', () => { + expect(isRACAlert({})).toEqual(false); + }); + + test('alert with null value returns false', () => { + expect(isRACAlert({ 'kibana.alert.uuid': null })).toEqual(false); + }); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index 7cdcae96490a9..8a59d71fe74ec 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -986,7 +986,7 @@ export const isWrappedRACAlert = (event: SimpleHit): event is WrappedRACAlert => }; export const isRACAlert = (event: unknown): event is RACAlert => { - return (event as RACAlert)?.[ALERT_UUID] != null; + return get(event, ALERT_UUID) != null; }; export const racFieldMappings: Record = { diff --git a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts index d0406d744b72a..62f3a39a6b48b 100644 --- a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts +++ b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts @@ -140,7 +140,9 @@ export class SpacesManager { type: string ): Promise<{ shareToAllSpaces: boolean }> { return this.http - .get('/internal/security/_share_saved_object_permissions', { query: { type } }) + .get<{ shareToAllSpaces: boolean }>('/internal/security/_share_saved_object_permissions', { + query: { type }, + }) .catch((err) => { const isNotFound = err?.body?.statusCode === 404; if (isNotFound) { @@ -190,7 +192,7 @@ export class SpacesManager { if (this.isAnonymousPath()) { return; } - const activeSpace = await this.http.get('/internal/spaces/_active_space'); + const activeSpace = await this.http.get('/internal/spaces/_active_space'); this.activeSpace$.next(activeSpace); } diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 2786cab4fe963..8ac619d479bef 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -100,6 +100,49 @@ } } }, + "count_actions_executions_per_day": { + "type": "long" + }, + "count_actions_executions_by_type_per_day": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__email": { + "type": "long" + }, + "__index": { + "type": "long" + }, + "__pagerduty": { + "type": "long" + }, + "__swimlane": { + "type": "long" + }, + "__server-log": { + "type": "long" + }, + "__slack": { + "type": "long" + }, + "__webhook": { + "type": "long" + }, + "__servicenow": { + "type": "long" + }, + "__jira": { + "type": "long" + }, + "__resilient": { + "type": "long" + }, + "__teams": { + "type": "long" + } + } + }, "count_active_email_connectors_by_service_type": { "properties": { "DYNAMIC_KEY": { @@ -127,6 +170,92 @@ }, "count_actions_namespaces": { "type": "long" + }, + "count_actions_executions_failed_per_day": { + "type": "long" + }, + "count_actions_executions_failed_by_type_per_day": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__email": { + "type": "long" + }, + "__index": { + "type": "long" + }, + "__pagerduty": { + "type": "long" + }, + "__swimlane": { + "type": "long" + }, + "__server-log": { + "type": "long" + }, + "__slack": { + "type": "long" + }, + "__webhook": { + "type": "long" + }, + "__servicenow": { + "type": "long" + }, + "__jira": { + "type": "long" + }, + "__resilient": { + "type": "long" + }, + "__teams": { + "type": "long" + } + } + }, + "avg_execution_time_per_day": { + "type": "long" + }, + "avg_execution_time_by_type_per_day": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__email": { + "type": "long" + }, + "__index": { + "type": "long" + }, + "__pagerduty": { + "type": "long" + }, + "__swimlane": { + "type": "long" + }, + "__server-log": { + "type": "long" + }, + "__slack": { + "type": "long" + }, + "__webhook": { + "type": "long" + }, + "__servicenow": { + "type": "long" + }, + "__jira": { + "type": "long" + }, + "__resilient": { + "type": "long" + }, + "__teams": { + "type": "long" + } + } } } }, @@ -352,6 +481,633 @@ }, "count_rules_namespaces": { "type": "long" + }, + "count_rules_executions_per_day": { + "type": "long" + }, + "count_rules_executions_by_type_per_day": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } + }, + "count_rules_executions_failured_per_day": { + "type": "long" + }, + "count_rules_executions_failured_by_reason_per_day": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "read": { + "type": "long" + }, + "decrypt": { + "type": "long" + }, + "license": { + "type": "long" + }, + "unknown": { + "type": "long" + } + } + }, + "count_rules_executions_failured_by_reason_by_type_per_day": { + "properties": { + "DYNAMIC_KEY": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } + }, + "read": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } + }, + "decrypt": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } + }, + "license": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } + }, + "unknown": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } + } + } + }, + "avg_execution_time_per_day": { + "type": "long" + }, + "avg_execution_time_by_type_per_day": { + "properties": { + "DYNAMIC_KEY": { + "type": "long" + }, + "__index-threshold": { + "type": "long" + }, + "__es-query": { + "type": "long" + }, + "transform_health": { + "type": "long" + }, + "apm__error_rate": { + "type": "long" + }, + "apm__transaction_error_rate": { + "type": "long" + }, + "apm__transaction_duration": { + "type": "long" + }, + "apm__transaction_duration_anomaly": { + "type": "long" + }, + "metrics__alert__threshold": { + "type": "long" + }, + "metrics__alert__inventory__threshold": { + "type": "long" + }, + "logs__alert__document__count": { + "type": "long" + }, + "monitoring_alert_cluster_health": { + "type": "long" + }, + "monitoring_alert_cpu_usage": { + "type": "long" + }, + "monitoring_alert_disk_usage": { + "type": "long" + }, + "monitoring_alert_elasticsearch_version_mismatch": { + "type": "long" + }, + "monitoring_alert_kibana_version_mismatch": { + "type": "long" + }, + "monitoring_alert_license_expiration": { + "type": "long" + }, + "monitoring_alert_logstash_version_mismatch": { + "type": "long" + }, + "monitoring_alert_nodes_changed": { + "type": "long" + }, + "siem__signals": { + "type": "long" + }, + "siem__notifications": { + "type": "long" + }, + "xpack__uptime__alerts__monitorStatus": { + "type": "long" + }, + "xpack__uptime__alerts__tls": { + "type": "long" + }, + "xpack__uptime__alerts__durationAnomaly": { + "type": "long" + }, + "__geo-containment": { + "type": "long" + }, + "xpack__ml__anomaly_detection_alert": { + "type": "long" + }, + "xpack__ml__anomaly_detection_jobs_health": { + "type": "long" + } + } } } }, diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx index 9e43c16fd5e6f..29766a5b8a1f5 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx @@ -146,7 +146,14 @@ const EuiDataGridContainer = styled.div<{ hideLastPage: boolean }>` } `; -const FIELDS_WITHOUT_CELL_ACTIONS = ['@timestamp', 'signal.rule.risk_score', 'signal.reason']; +// TODO: accept extra list of column ids without actions from callsites +const FIELDS_WITHOUT_CELL_ACTIONS = [ + '@timestamp', + 'signal.rule.risk_score', + 'signal.reason', + 'kibana.alert.duration.us', + 'kibana.alert.reason', +]; const hasCellActions = (columnId?: string) => columnId && FIELDS_WITHOUT_CELL_ACTIONS.indexOf(columnId) < 0; const transformControlColumns = ({ diff --git a/x-pack/plugins/timelines/public/container/use_update_alerts.ts b/x-pack/plugins/timelines/public/container/use_update_alerts.ts index 37a1fe1671fbd..b5d76f2fe324a 100644 --- a/x-pack/plugins/timelines/public/container/use_update_alerts.ts +++ b/x-pack/plugins/timelines/public/container/use_update_alerts.ts @@ -40,14 +40,15 @@ export const useUpdateAlertsStatus = ( return { updateAlertStatus: async ({ status, index, query }) => { if (useDetectionEngine) { - return http.fetch(DETECTION_ENGINE_SIGNALS_STATUS_URL, { + return http.fetch(DETECTION_ENGINE_SIGNALS_STATUS_URL, { method: 'POST', body: JSON.stringify({ status, query }), }); } else { - const { body } = await http.post(RAC_ALERTS_BULK_UPDATE_URL, { - body: JSON.stringify({ index, status, query }), - }); + const { body } = await http.post<{ body: estypes.UpdateByQueryResponse }>( + RAC_ALERTS_BULK_UPDATE_URL, + { body: JSON.stringify({ index, status, query }) } + ); return body; } }, diff --git a/x-pack/plugins/transform/public/app/services/es_index_service.ts b/x-pack/plugins/transform/public/app/services/es_index_service.ts index d9014602cc393..c8d3f625a9281 100644 --- a/x-pack/plugins/transform/public/app/services/es_index_service.ts +++ b/x-pack/plugins/transform/public/app/services/es_index_service.ts @@ -11,7 +11,7 @@ import { IIndexPattern } from '../../../../../../src/plugins/data/common'; export class IndexService { async canDeleteIndex(http: HttpSetup) { - const privilege = await http.get(`${API_BASE_PATH}privileges`); + const privilege = await http.get<{ hasAllPrivileges: boolean }>(`${API_BASE_PATH}privileges`); if (!privilege) { return false; } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7ab4c7d31d745..857e97daa3515 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1359,11 +1359,7 @@ "core.ui.primaryNav.pinnedLinksAriaLabel": "ピン留めされたリンク", "core.ui.primaryNav.screenReaderLabel": "プライマリ", "core.ui.primaryNav.toggleNavAriaLabel": "プライマリナビゲーションを切り替える", - "core.ui.primaryNavSection.dockAriaLabel": "プライマリナビゲーションリンクを固定する", - "core.ui.primaryNavSection.dockLabel": "ナビゲーションを固定する", "core.ui.primaryNavSection.screenReaderLabel": "プライマリナビゲーションリンク、{category}", - "core.ui.primaryNavSection.undockAriaLabel": "プライマリナビゲーションリンクの固定を解除する", - "core.ui.primaryNavSection.undockLabel": "ナビゲーションの固定を解除する", "core.ui.publicBaseUrlWarning.configMissingDescription": "{configKey}が見つかりません。本番環境を実行するときに構成してください。一部の機能が正常に動作しない場合があります。", "core.ui.publicBaseUrlWarning.configMissingTitle": "構成がありません", "core.ui.publicBaseUrlWarning.muteWarningButtonLabel": "ミュート警告", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1208277001cb9..6c860a5b2cc4d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1375,11 +1375,7 @@ "core.ui.primaryNav.pinnedLinksAriaLabel": "置顶链接", "core.ui.primaryNav.screenReaderLabel": "主分片", "core.ui.primaryNav.toggleNavAriaLabel": "切换主导航", - "core.ui.primaryNavSection.dockAriaLabel": "停靠主导航", - "core.ui.primaryNavSection.dockLabel": "停靠导航", "core.ui.primaryNavSection.screenReaderLabel": "主导航链接, {category}", - "core.ui.primaryNavSection.undockAriaLabel": "取消停靠主导航", - "core.ui.primaryNavSection.undockLabel": "取消停靠导航", "core.ui.publicBaseUrlWarning.configMissingDescription": "{configKey} 缺失,在生产环境中运行时应配置。某些功能可能运行不正常。", "core.ui.publicBaseUrlWarning.configMissingTitle": "配置缺失", "core.ui.publicBaseUrlWarning.muteWarningButtonLabel": "静音警告", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/api.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/api.ts index e3a46c5a875c7..daca46247ae3e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/api.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/api.ts @@ -7,7 +7,7 @@ import { HttpSetup } from 'kibana/public'; import { BASE_ACTION_API_PATH } from '../../../constants'; -import { rewriteResponseToCamelCase } from '../rewrite_response_body'; +import { ConnectorExecutorResult, rewriteResponseToCamelCase } from '../rewrite_response_body'; export async function getIncidentTypes({ http, @@ -18,7 +18,7 @@ export async function getIncidentTypes({ signal: AbortSignal; connectorId: string; }): Promise> { - const res = await http.post( + const res = await http.post>( `${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(connectorId)}/_execute`, { body: JSON.stringify({ @@ -39,7 +39,7 @@ export async function getSeverity({ signal: AbortSignal; connectorId: string; }): Promise> { - const res = await http.post( + const res = await http.post>( `${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(connectorId)}/_execute`, { body: JSON.stringify({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connector_types.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connector_types.ts index 6f7e8b03658e0..e1b63280cc915 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connector_types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connector_types.ts @@ -27,6 +27,8 @@ const rewriteBodyReq: RewriteRequestCase = ({ }); export async function loadActionTypes({ http }: { http: HttpSetup }): Promise { - const res = await http.get(`${BASE_ACTION_API_PATH}/connector_types`); + const res = await http.get[0]>( + `${BASE_ACTION_API_PATH}/connector_types` + ); return rewriteResponseRes(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts index 7011ec016c089..70997ca52dab1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts @@ -34,6 +34,8 @@ const transformConnector: RewriteRequestCase< }); export async function loadAllActions({ http }: { http: HttpSetup }): Promise { - const res = await http.get(`${BASE_ACTION_API_PATH}/connectors`); + const res = await http.get[0]>( + `${BASE_ACTION_API_PATH}/connectors` + ); return rewriteResponseRes(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/create.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/create.ts index 7a63f6a19f583..624aff1cd7773 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/create.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/create.ts @@ -42,8 +42,9 @@ export async function createActionConnector({ http: HttpSetup; connector: Omit; }): Promise { - const res = await http.post(`${BASE_ACTION_API_PATH}/connector`, { - body: JSON.stringify(rewriteBodyRequest(connector)), - }); + const res = await http.post[0]>( + `${BASE_ACTION_API_PATH}/connector`, + { body: JSON.stringify(rewriteBodyRequest(connector)) } + ); return rewriteBodyRes(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/delete.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/delete.ts index 868e5390045cc..8c9495158cc57 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/delete.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/delete.ts @@ -17,7 +17,9 @@ export async function deleteActions({ const successes: string[] = []; const errors: string[] = []; await Promise.all( - ids.map((id) => http.delete(`${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(id)}`)) + ids.map((id) => + http.delete(`${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(id)}`) + ) ).then( function (fulfilled) { successes.push(...fulfilled); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/execute.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/execute.ts index d97ad7d5962b7..0a305413f61f7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/execute.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/execute.ts @@ -31,7 +31,7 @@ export async function executeAction({ http: HttpSetup; params: Record; }): Promise> { - const res = await http.post( + const res = await http.post[0]>( `${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(id)}/_execute`, { body: JSON.stringify({ params }), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/update.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/update.ts index f2319ace29d68..a45dc8cfca2f9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/update.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/update.ts @@ -36,13 +36,16 @@ export async function updateActionConnector({ connector: Pick; id: string; }): Promise { - const res = await http.put(`${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(id)}`, { - body: JSON.stringify({ - name: connector.name, - config: connector.config, - secrets: connector.secrets, - }), - }); + const res = await http.put[0]>( + `${BASE_ACTION_API_PATH}/connector/${encodeURIComponent(id)}`, + { + body: JSON.stringify({ + name: connector.name, + config: connector.config, + secrets: connector.secrets, + }), + } + ); return rewriteBodyRes(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/aggregate.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/aggregate.ts index 589677ec2322d..917a491586b36 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/aggregate.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/aggregate.ts @@ -8,7 +8,7 @@ import { HttpSetup } from 'kibana/public'; import { AlertAggregations } from '../../../types'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { mapFiltersToKql } from './map_filters_to_kql'; -import { RewriteRequestCase } from '../../../../../actions/common'; +import { AsApiContract, RewriteRequestCase } from '../../../../../actions/common'; const rewriteBodyRes: RewriteRequestCase = ({ rule_execution_status: alertExecutionStatus, @@ -32,13 +32,16 @@ export async function loadAlertAggregations({ alertStatusesFilter?: string[]; }): Promise { const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, alertStatusesFilter }); - const res = await http.get(`${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`, { - query: { - search_fields: searchText ? JSON.stringify(['name', 'tags']) : undefined, - search: searchText, - filter: filters.length ? filters.join(' and ') : undefined, - default_search_operator: 'AND', - }, - }); + const res = await http.get>( + `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`, + { + query: { + search_fields: searchText ? JSON.stringify(['name', 'tags']) : undefined, + search: searchText, + filter: filters.length ? filters.join(' and ') : undefined, + default_search_operator: 'AND', + }, + } + ); return rewriteBodyRes(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts index 701c8f3a7beec..35a757f4b6afe 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts @@ -7,7 +7,7 @@ import { HttpSetup } from 'kibana/public'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { AlertInstanceSummary } from '../../../types'; -import { RewriteRequestCase } from '../../../../../actions/common'; +import { RewriteRequestCase, AsApiContract } from '../../../../../actions/common'; const rewriteBodyRes: RewriteRequestCase = ({ alerts, @@ -38,7 +38,7 @@ export async function loadAlertInstanceSummary({ http: HttpSetup; alertId: string; }): Promise { - const res = await http.get( + const res = await http.get>( `${INTERNAL_BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(alertId)}/_alert_summary` ); return rewriteBodyRes(res); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/create.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/create.ts index bd92769b4bbf3..36d2a17bcd4d5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/create.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/create.ts @@ -5,7 +5,7 @@ * 2.0. */ import { HttpSetup } from 'kibana/public'; -import { RewriteResponseCase } from '../../../../../actions/common'; +import { AsApiContract, RewriteResponseCase } from '../../../../../actions/common'; import { Alert, AlertUpdates } from '../../../types'; import { BASE_ALERTING_API_PATH } from '../../constants'; import { transformAlert } from './common_transformations'; @@ -37,7 +37,7 @@ export async function createAlert({ http: HttpSetup; alert: AlertCreateBody; }): Promise { - const res = await http.post(`${BASE_ALERTING_API_PATH}/rule`, { + const res = await http.post>(`${BASE_ALERTING_API_PATH}/rule`, { body: JSON.stringify(rewriteBodyRequest(alert)), }); return transformAlert(res); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/delete.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/delete.ts index b853e722e6fc3..d223dd08ca29a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/delete.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/delete.ts @@ -17,7 +17,7 @@ export async function deleteAlerts({ const successes: string[] = []; const errors: string[] = []; await Promise.all( - ids.map((id) => http.delete(`${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(id)}`)) + ids.map((id) => http.delete(`${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(id)}`)) ).then( function (fulfilled) { successes.push(...fulfilled); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/get_rule.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/get_rule.ts index 9fa882c02fa22..fd4de0c3dae68 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/get_rule.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/get_rule.ts @@ -5,6 +5,7 @@ * 2.0. */ import { HttpSetup } from 'kibana/public'; +import { AsApiContract } from '../../../../../actions/common'; import { Alert } from '../../../types'; import { BASE_ALERTING_API_PATH } from '../../constants'; import { transformAlert } from './common_transformations'; @@ -16,6 +17,8 @@ export async function loadAlert({ http: HttpSetup; alertId: string; }): Promise { - const res = await http.get(`${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(alertId)}`); + const res = await http.get>( + `${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(alertId)}` + ); return transformAlert(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/health.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/health.ts index 9468f4b3c03e0..b9df3938fafaa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/health.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/health.ts @@ -38,7 +38,14 @@ export async function alertingFrameworkHealth({ }: { http: HttpSetup; }): Promise { - const res = await http.get(`${BASE_ALERTING_API_PATH}/_health`); - const alertingFrameworkHeath = rewriteAlertingFrameworkHeath(res.alerting_framework_heath); - return { ...rewriteBodyRes(res), alertingFrameworkHeath }; + const res = await http.get>( + `${BASE_ALERTING_API_PATH}/_health` + ); + const alertingFrameworkHeath = rewriteAlertingFrameworkHeath( + res.alerting_framework_heath as unknown as AsApiContract + ); + return { + ...rewriteBodyRes(res), + alertingFrameworkHeath, + }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/resolve_rule.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/resolve_rule.ts index bc2a19d298f8a..fa2867ffd85e7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/resolve_rule.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/resolve_rule.ts @@ -5,6 +5,7 @@ * 2.0. */ import { HttpSetup } from 'kibana/public'; +import { AsApiContract } from '../../../../../actions/common'; import { ResolvedRule } from '../../../types'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { transformResolvedRule } from './common_transformations'; @@ -16,7 +17,7 @@ export async function resolveRule({ http: HttpSetup; ruleId: string; }): Promise { - const res = await http.get( + const res = await http.get>( `${INTERNAL_BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(ruleId)}/_resolve` ); return transformResolvedRule(res); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rule_types.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rule_types.ts index 67d317643ec06..530c158838c2b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rule_types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rule_types.ts @@ -36,6 +36,8 @@ const rewriteBodyReq: RewriteRequestCase = ({ }); export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise { - const res = await http.get(`${BASE_ALERTING_API_PATH}/rule_types`); + const res = await http.get>>>( + `${BASE_ALERTING_API_PATH}/rule_types` + ); return rewriteResponseRes(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rules.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rules.ts index f0bbb57180bb4..3475cbb04408e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rules.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/rules.ts @@ -38,7 +38,14 @@ export async function loadAlerts({ data: Alert[]; }> { const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, alertStatusesFilter }); - const res = await http.get(`${BASE_ALERTING_API_PATH}/rules/_find`, { + const res = await http.get< + AsApiContract<{ + page: number; + perPage: number; + total: number; + data: Array>; + }> + >(`${BASE_ALERTING_API_PATH}/rules/_find`, { query: { page: page.index + 1, per_page: page.size, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/state.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/state.ts index 428bc5b99a70b..f5529c5d7d5b5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/state.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/state.ts @@ -34,10 +34,10 @@ export async function loadAlertState({ alertId: string; }): Promise { return await http - .get(`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${alertId}/state`) - .then((state: AsApiContract | EmptyHttpResponse) => - state ? rewriteBodyRes(state) : {} + .get | EmptyHttpResponse>( + `${INTERNAL_BASE_ALERTING_API_PATH}/rule/${alertId}/state` ) + .then((state) => (state ? rewriteBodyRes(state) : {})) .then((state: AlertTaskState) => { return pipe( alertStateSchema.decode(state), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/update.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/update.ts index 930c0c2fb21a0..8b9365b0a4667 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/update.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/update.ts @@ -8,7 +8,7 @@ import { HttpSetup } from 'kibana/public'; import { pick } from 'lodash'; import { BASE_ALERTING_API_PATH } from '../../constants'; import { Alert, AlertUpdates } from '../../../types'; -import { RewriteResponseCase } from '../../../../../actions/common'; +import { RewriteResponseCase, AsApiContract } from '../../../../../actions/common'; import { transformAlert } from './common_transformations'; type AlertUpdatesBody = Pick< @@ -41,12 +41,15 @@ export async function updateAlert({ >; id: string; }): Promise { - const res = await http.put(`${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(id)}`, { - body: JSON.stringify( - rewriteBodyRequest( - pick(alert, ['throttle', 'name', 'tags', 'schedule', 'params', 'actions', 'notifyWhen']) - ) - ), - }); + const res = await http.put>( + `${BASE_ALERTING_API_PATH}/rule/${encodeURIComponent(id)}`, + { + body: JSON.stringify( + rewriteBodyRequest( + pick(alert, ['throttle', 'name', 'tags', 'schedule', 'params', 'actions', 'notifyWhen']) + ) + ), + } + ); return transformAlert(res); } diff --git a/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts b/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts index 7b97c8bdfaa69..d8a1ecabcd500 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts +++ b/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts @@ -22,9 +22,10 @@ export async function getMatchingIndices({ if (!pattern.endsWith('*')) { pattern = `${pattern}*`; } - const { indices } = await http.post(`${DATA_API_ROOT}/_indices`, { - body: JSON.stringify({ pattern }), - }); + const { indices } = await http.post>( + `${DATA_API_ROOT}/_indices`, + { body: JSON.stringify({ pattern }) } + ); return indices; } @@ -43,9 +44,10 @@ export async function getESIndexFields({ aggregatable: boolean; }> > { - const { fields } = await http.post(`${DATA_API_ROOT}/_fields`, { - body: JSON.stringify({ indexPatterns: indexes }), - }); + const { fields } = await http.post<{ fields: ReturnType }>( + `${DATA_API_ROOT}/_fields`, + { body: JSON.stringify({ indexPatterns: indexes }) } + ); return fields; } diff --git a/x-pack/plugins/uptime/common/runtime_types/ping/synthetics.ts b/x-pack/plugins/uptime/common/runtime_types/ping/synthetics.ts index 7b181ac2cf50c..040f0a83e84ab 100644 --- a/x-pack/plugins/uptime/common/runtime_types/ping/synthetics.ts +++ b/x-pack/plugins/uptime/common/runtime_types/ping/synthetics.ts @@ -27,6 +27,11 @@ export const JourneyStepType = t.intersection([ lt: t.string, }), }), + observer: t.type({ + geo: t.type({ + name: t.string, + }), + }), synthetics: t.partial({ error: t.partial({ message: t.string, diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx b/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx index 3bf6c4f4bcb14..9848ea77d4673 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx @@ -8,15 +8,15 @@ import { EuiEmptyPrompt, EuiPanel, EuiTitle, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { Fragment } from 'react'; -import { IHttpFetchError } from 'src/core/public'; +import { IHttpFetchError, ResponseErrorBody } from 'src/core/public'; interface EmptyStateErrorProps { - errors: IHttpFetchError[]; + errors: Array>; } export const EmptyStateError = ({ errors }: EmptyStateErrorProps) => { const unauthorized = errors.find( - (error: IHttpFetchError) => error.message && error.message.includes('unauthorized') + (error) => error.message && error.message.includes('unauthorized') ); return ( @@ -47,9 +47,9 @@ export const EmptyStateError = ({ errors }: EmptyStateErrorProps) => { body={ {!unauthorized && - errors.map((error: IHttpFetchError) => ( -

- {error.body.message || error.message} + errors.map((error) => ( +

+ {error.body?.message || error.message}

))}
diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx index 80b1463ac2f43..de077931167c1 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx @@ -18,7 +18,7 @@ import { import { MonitorListComponent, noItemsMessage } from './monitor_list'; import * as redux from 'react-redux'; import moment from 'moment'; -import { IHttpFetchError } from '../../../../../../../src/core/public'; +import { IHttpFetchError, ResponseErrorBody } from '../../../../../../../src/core/public'; import { mockMoment } from '../../../lib/helper/test_helpers'; import { render } from '../../../lib/helper/rtl_helpers'; import { NO_DATA_MESSAGE } from './translations'; @@ -185,7 +185,7 @@ describe('MonitorList component', () => { , loading: false, }} pageSize={10} diff --git a/x-pack/plugins/uptime/public/components/synthetics/check_steps/step_expanded_row/step_screenshots.tsx b/x-pack/plugins/uptime/public/components/synthetics/check_steps/step_expanded_row/step_screenshots.tsx index 54f73fb39a52a..f8776f74b780e 100644 --- a/x-pack/plugins/uptime/public/components/synthetics/check_steps/step_expanded_row/step_screenshots.tsx +++ b/x-pack/plugins/uptime/public/components/synthetics/check_steps/step_expanded_row/step_screenshots.tsx @@ -36,6 +36,7 @@ export const StepScreenshots = ({ step }: Props) => { timestamp: step['@timestamp'], monitorId: step.monitor.id, stepIndex: step.synthetics?.step?.index!, + location: step.observer?.geo?.name, }); } }, [step._id, step['@timestamp']]); diff --git a/x-pack/plugins/uptime/public/components/synthetics/check_steps/use_expanded_row.test.tsx b/x-pack/plugins/uptime/public/components/synthetics/check_steps/use_expanded_row.test.tsx index 7aa763c15ca1f..e1f43cfebdbb2 100644 --- a/x-pack/plugins/uptime/public/components/synthetics/check_steps/use_expanded_row.test.tsx +++ b/x-pack/plugins/uptime/public/components/synthetics/check_steps/use_expanded_row.test.tsx @@ -228,6 +228,9 @@ const browserConsoleStep = { _id: 'IvT1oXwB5ds00bB_FVXP', observer: { hostname: '16Elastic', + geo: { + name: 'au-heartbeat', + }, }, agent: { name: '16Elastic', diff --git a/x-pack/plugins/uptime/public/state/api/alerts.ts b/x-pack/plugins/uptime/public/state/api/alerts.ts index d74a73befb5d0..e175f7ac61bd3 100644 --- a/x-pack/plugins/uptime/public/state/api/alerts.ts +++ b/x-pack/plugins/uptime/public/state/api/alerts.ts @@ -127,8 +127,11 @@ export const fetchAlertRecords = async ({ sort_field: 'name.keyword', sort_order: 'asc', }; - const alerts = await apiService.get(API_URLS.RULES_FIND, data); - return alerts.data.find((alert: Alert) => alert.params.monitorId === monitorId); + const alerts = await apiService.get<{ data: Array> }>( + API_URLS.RULES_FIND, + data + ); + return alerts.data.find((alert) => alert.params.monitorId === monitorId) as Alert; }; export const disableAlertById = async ({ alertId }: { alertId: string }) => { diff --git a/x-pack/plugins/uptime/public/state/api/journey.ts b/x-pack/plugins/uptime/public/state/api/journey.ts index 8ed3fadf5c346..05d4a9e356919 100644 --- a/x-pack/plugins/uptime/public/state/api/journey.ts +++ b/x-pack/plugins/uptime/public/state/api/journey.ts @@ -20,7 +20,9 @@ import { } from '../../../common/runtime_types/ping/synthetics'; export async function fetchScreenshotBlockSet(params: string[]): Promise { - return apiService.post('/api/uptime/journey/screenshot/block', { hashes: params }); + return apiService.post('/api/uptime/journey/screenshot/block', { + hashes: params, + }); } export async function fetchJourneySteps( @@ -49,10 +51,12 @@ export async function fetchLastSuccessfulStep({ monitorId, timestamp, stepIndex, + location, }: { monitorId: string; timestamp: string; stepIndex: number; + location?: string; }): Promise { return await apiService.get( `/api/uptime/synthetics/step/success/`, @@ -60,6 +64,7 @@ export async function fetchLastSuccessfulStep({ monitorId, timestamp, stepIndex, + location, }, JourneyStepType ); diff --git a/x-pack/plugins/uptime/public/state/api/monitor.ts b/x-pack/plugins/uptime/public/state/api/monitor.ts index 4991727a3dcdd..ef04b38f37469 100644 --- a/x-pack/plugins/uptime/public/state/api/monitor.ts +++ b/x-pack/plugins/uptime/public/state/api/monitor.ts @@ -27,7 +27,7 @@ export const fetchMonitorDetails = async ({ dateStart, dateEnd, }; - return await apiService.get(API_URLS.MONITOR_DETAILS, params, MonitorDetailsType); + return await apiService.get(API_URLS.MONITOR_DETAILS, params, MonitorDetailsType); }; type ApiParams = QueryParams & ApiRequest; @@ -38,5 +38,5 @@ export const fetchMonitorLocations = async ({ monitorId, dateStart, dateEnd }: A dateEnd, monitorId, }; - return await apiService.get(API_URLS.MONITOR_LOCATIONS, params, MonitorLocationsType); + return await apiService.get(API_URLS.MONITOR_LOCATIONS, params, MonitorLocationsType); }; diff --git a/x-pack/plugins/uptime/public/state/api/monitor_duration.ts b/x-pack/plugins/uptime/public/state/api/monitor_duration.ts index 56838d06bf94f..c8010e18d0868 100644 --- a/x-pack/plugins/uptime/public/state/api/monitor_duration.ts +++ b/x-pack/plugins/uptime/public/state/api/monitor_duration.ts @@ -16,5 +16,5 @@ export const fetchMonitorDuration = async ({ monitorId, dateStart, dateEnd }: Ba dateEnd, }; - return await apiService.get(API_URLS.MONITOR_DURATION, queryParams); + return await apiService.get(API_URLS.MONITOR_DURATION, queryParams); }; diff --git a/x-pack/plugins/uptime/public/state/api/utils.ts b/x-pack/plugins/uptime/public/state/api/utils.ts index d10064f1ff7a1..0399129a80466 100644 --- a/x-pack/plugins/uptime/public/state/api/utils.ts +++ b/x-pack/plugins/uptime/public/state/api/utils.ts @@ -71,8 +71,13 @@ class ApiService { return ApiService.instance; } - public async get(apiUrl: string, params?: HttpFetchQuery, decodeType?: any, asResponse = false) { - const response = await this._http!.fetch({ + public async get( + apiUrl: string, + params?: HttpFetchQuery, + decodeType?: any, + asResponse = false + ) { + const response = await this._http!.fetch({ path: apiUrl, query: params, asResponse, @@ -83,7 +88,7 @@ class ApiService { if (decodeType) { const decoded = decodeType.decode(response); if (isRight(decoded)) { - return decoded.right; + return decoded.right as T; } else { // eslint-disable-next-line no-console console.error( @@ -98,8 +103,8 @@ class ApiService { return response; } - public async post(apiUrl: string, data?: any, decodeType?: any) { - const response = await this._http!.post(apiUrl, { + public async post(apiUrl: string, data?: any, decodeType?: any) { + const response = await this._http!.post(apiUrl, { method: 'POST', body: JSON.stringify(data), }); @@ -107,7 +112,7 @@ class ApiService { if (decodeType) { const decoded = decodeType.decode(response); if (isRight(decoded)) { - return decoded.right; + return decoded.right as T; } else { // eslint-disable-next-line no-console console.warn( @@ -118,8 +123,8 @@ class ApiService { return response; } - public async delete(apiUrl: string) { - const response = await this._http!.delete(apiUrl); + public async delete(apiUrl: string) { + const response = await this._http!.delete(apiUrl); if (response instanceof Error) { throw response; } diff --git a/x-pack/plugins/uptime/public/state/reducers/monitor_list.ts b/x-pack/plugins/uptime/public/state/reducers/monitor_list.ts index 8a2c7df05018e..2e833bd033c46 100644 --- a/x-pack/plugins/uptime/public/state/reducers/monitor_list.ts +++ b/x-pack/plugins/uptime/public/state/reducers/monitor_list.ts @@ -6,12 +6,12 @@ */ import { handleActions, Action } from 'redux-actions'; -import { IHttpFetchError } from 'src/core/public'; +import { IHttpFetchError, ResponseErrorBody } from 'src/core/public'; import { getMonitorList, getMonitorListSuccess, getMonitorListFailure } from '../actions'; import { MonitorSummariesResult } from '../../../common/runtime_types'; export interface MonitorList { - error?: IHttpFetchError; + error?: IHttpFetchError; loading: boolean; list: MonitorSummariesResult; } @@ -25,7 +25,7 @@ export const initialState: MonitorList = { loading: false, }; -type Payload = MonitorSummariesResult & IHttpFetchError; +type Payload = MonitorSummariesResult & IHttpFetchError; export const monitorListReducer = handleActions( { @@ -42,7 +42,10 @@ export const monitorListReducer = handleActions( error: undefined, list: { ...action.payload }, }), - [String(getMonitorListFailure)]: (state: MonitorList, action: Action) => ({ + [String(getMonitorListFailure)]: ( + state: MonitorList, + action: Action> + ) => ({ ...state, error: action.payload, loading: false, diff --git a/x-pack/plugins/uptime/public/state/reducers/types.ts b/x-pack/plugins/uptime/public/state/reducers/types.ts index c9dc30ed3dde3..71cf9a59f6478 100644 --- a/x-pack/plugins/uptime/public/state/reducers/types.ts +++ b/x-pack/plugins/uptime/public/state/reducers/types.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { IHttpFetchError } from 'src/core/public'; +import { IHttpFetchError, ResponseErrorBody } from 'src/core/public'; export interface AsyncInitState { data: ReduceStateType | null; loading: boolean; - error?: IHttpFetchError | null; + error?: IHttpFetchError | null; } diff --git a/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.test.ts new file mode 100644 index 0000000000000..63274bf64536c --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.test.ts @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getLastSuccessfulStepParams } from './get_last_successful_step'; + +describe('getLastSuccessfulStep', () => { + describe('getLastSuccessfulStepParams', () => { + it('formats ES params with location', () => { + const monitorId = 'my-monitor'; + const stepIndex = 1; + const location = 'au-heartbeat'; + const timestamp = '2021-10-31T19:47:52.392Z'; + const params = getLastSuccessfulStepParams({ + monitorId, + stepIndex, + location, + timestamp, + }); + + expect(params).toEqual({ + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + lte: '2021-10-31T19:47:52.392Z', + }, + }, + }, + { + term: { + 'monitor.id': monitorId, + }, + }, + { + term: { + 'synthetics.type': 'step/end', + }, + }, + { + term: { + 'synthetics.step.status': 'succeeded', + }, + }, + { + term: { + 'synthetics.step.index': stepIndex, + }, + }, + { + term: { + 'observer.geo.name': location, + }, + }, + ], + }, + }, + size: 1, + sort: [ + { + '@timestamp': { + order: 'desc', + }, + }, + ], + }); + }); + + it('formats ES params without location', () => { + const params = getLastSuccessfulStepParams({ + monitorId: 'my-monitor', + stepIndex: 1, + location: undefined, + timestamp: '2021-10-31T19:47:52.392Z', + }); + + expect(params).toEqual({ + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + lte: '2021-10-31T19:47:52.392Z', + }, + }, + }, + { + term: { + 'monitor.id': 'my-monitor', + }, + }, + { + term: { + 'synthetics.type': 'step/end', + }, + }, + { + term: { + 'synthetics.step.status': 'succeeded', + }, + }, + { + term: { + 'synthetics.step.index': 1, + }, + }, + ], + must_not: { + exists: { + field: 'observer.geo.name', + }, + }, + }, + }, + size: 1, + sort: [ + { + '@timestamp': { + order: 'desc', + }, + }, + ], + }); + }); + }); +}); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts b/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts index e096cdaa65b86..d6862b93c8cd4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts @@ -13,13 +13,16 @@ export interface GetStepScreenshotParams { monitorId: string; timestamp: string; stepIndex: number; + location?: string; } -export const getStepLastSuccessfulStep: UMElasticsearchQueryFn< - GetStepScreenshotParams, - JourneyStep | null -> = async ({ uptimeEsClient, monitorId, stepIndex, timestamp }) => { - const lastSuccessCheckParams: estypes.SearchRequest['body'] = { +export const getLastSuccessfulStepParams = ({ + monitorId, + stepIndex, + timestamp, + location, +}: GetStepScreenshotParams): estypes.SearchRequest['body'] => { + return { size: 1, sort: [ { @@ -58,10 +61,40 @@ export const getStepLastSuccessfulStep: UMElasticsearchQueryFn< 'synthetics.step.index': stepIndex, }, }, + ...(location + ? [ + { + term: { + 'observer.geo.name': location, + }, + }, + ] + : []), ], + ...(!location + ? { + must_not: { + exists: { + field: 'observer.geo.name', + }, + }, + } + : {}), }, }, }; +}; + +export const getStepLastSuccessfulStep: UMElasticsearchQueryFn< + GetStepScreenshotParams, + JourneyStep | null +> = async ({ uptimeEsClient, monitorId, stepIndex, timestamp, location }) => { + const lastSuccessCheckParams = getLastSuccessfulStepParams({ + monitorId, + stepIndex, + timestamp, + location, + }); const { body: result } = await uptimeEsClient.search({ body: lastSuccessCheckParams }); diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics/last_successful_step.ts b/x-pack/plugins/uptime/server/rest_api/synthetics/last_successful_step.ts index 5d1407a8679c8..81539459172cc 100644 --- a/x-pack/plugins/uptime/server/rest_api/synthetics/last_successful_step.ts +++ b/x-pack/plugins/uptime/server/rest_api/synthetics/last_successful_step.ts @@ -22,16 +22,18 @@ export const createLastSuccessfulStepRoute: UMRestApiRouteFactory = (libs: UMSer monitorId: schema.string(), stepIndex: schema.number(), timestamp: schema.string(), + location: schema.maybe(schema.string()), }), }, handler: async ({ uptimeEsClient, request, response }) => { - const { timestamp, monitorId, stepIndex } = request.query; + const { timestamp, monitorId, stepIndex, location } = request.query; const step: JourneyStep | null = await libs.requests.getStepLastSuccessfulStep({ uptimeEsClient, monitorId, stepIndex, timestamp, + location, }); if (step === null) { diff --git a/x-pack/plugins/watcher/public/application/lib/api.ts b/x-pack/plugins/watcher/public/application/lib/api.ts index 1957ee8a52e28..61ea124695cb9 100644 --- a/x-pack/plugins/watcher/public/application/lib/api.ts +++ b/x-pack/plugins/watcher/public/application/lib/api.ts @@ -91,7 +91,7 @@ export const deleteWatches = async (watchIds: string[]) => { const body = JSON.stringify({ watchIds, }); - const { results } = await getHttpClient().post(`${basePath}/watches/delete`, { body }); + const { results } = await getHttpClient().post(`${basePath}/watches/delete`, { body }); return results; }; @@ -110,7 +110,7 @@ export const activateWatch = async (id: string) => { }; export const loadWatch = async (id: string) => { - const { watch } = await getHttpClient().get(`${basePath}/watch/${id}`); + const { watch } = await getHttpClient().get(`${basePath}/watch/${id}`); return Watch.fromUpstreamJson(watch); }; @@ -122,12 +122,12 @@ export const getMatchingIndices = async (pattern: string) => { pattern = `${pattern}*`; } const body = JSON.stringify({ pattern }); - const { indices } = await getHttpClient().post(`${basePath}/indices`, { body }); + const { indices } = await getHttpClient().post(`${basePath}/indices`, { body }); return indices; }; export const fetchFields = async (indexes: string[]) => { - const { fields } = await getHttpClient().post(`${basePath}/fields`, { + const { fields } = await getHttpClient().post(`${basePath}/fields`, { body: JSON.stringify({ indexes }), }); return fields; @@ -190,7 +190,7 @@ export const useLoadSettings = () => { }; export const ackWatchAction = async (watchId: string, actionId: string) => { - const { watchStatus } = await getHttpClient().put( + const { watchStatus } = await getHttpClient().put( `${basePath}/watch/${watchId}/action/${actionId}/acknowledge` ); return WatchStatus.fromUpstreamJson(watchStatus); diff --git a/x-pack/scripts/functional_tests_server.js b/x-pack/scripts/functional_tests_server.js old mode 100644 new mode 100755 diff --git a/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts b/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts index c7b6bbb84436f..24cf4699d952c 100644 --- a/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts +++ b/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts @@ -58,7 +58,11 @@ export default function ({ getService }: FtrProviderContext) { }, strategy: 'securitySolutionSearchStrategy', }); - expect(networkDns.rawResponse.aggregations?.dns_count).to.eql({ value: 6604 }); + // This can have a odd unknown flake if we do anything more strict than this. + const dnsCount = networkDns.rawResponse.aggregations?.dns_count as unknown as { + value: number; + }; + expect(dnsCount.value).to.be.above(0); }); }); }); diff --git a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts index f0f917e865fa9..d5bf0bd21c7e8 100644 --- a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts @@ -87,7 +87,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { serviceInventoryAPIResponse.body.items[0].transactionErrorRate; const errorRateChartApiMean = meanBy( - transactionsErrorRateChartAPIResponse.body.currentPeriod.transactionErrorRate.filter( + transactionsErrorRateChartAPIResponse.body.currentPeriod.timeseries.filter( (item) => isFiniteNumber(item.y) && item.y > 0 ), 'y' diff --git a/x-pack/test/apm_api_integration/tests/errors/distribution.ts b/x-pack/test/apm_api_integration/tests/errors/distribution.ts index 4f4b457de86bd..487b5ff8a12c9 100644 --- a/x-pack/test/apm_api_integration/tests/errors/distribution.ts +++ b/x-pack/test/apm_api_integration/tests/errors/distribution.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { first, last, sumBy } from 'lodash'; import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number'; @@ -15,6 +14,7 @@ import { import { RecursivePartial } from '../../../../plugins/apm/typings/common'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { registry } from '../../common/registry'; +import { config, generateData } from './generate_data'; type ErrorsDistribution = APIReturnType<'GET /internal/apm/services/{serviceName}/errors/distribution'>; @@ -65,59 +65,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { { config: 'basic', archives: ['apm_mappings_only_8.0.0'] }, () => { describe('errors distribution', () => { - const appleTransaction = { - name: 'GET /apple 🍎 ', - successRate: 75, - failureRate: 25, - }; - const bananaTransaction = { - name: 'GET /banana 🍌', - successRate: 50, - failureRate: 50, - }; - + const { appleTransaction, bananaTransaction } = config; before(async () => { - const serviceGoProdInstance = service(serviceName, 'production', 'go').instance( - 'instance-a' - ); - - const interval = '1m'; - - const indices = [appleTransaction, bananaTransaction] - .map((transaction, index) => { - return [ - ...timerange(start, end) - .interval(interval) - .rate(transaction.successRate) - .flatMap((timestamp) => - serviceGoProdInstance - .transaction(transaction.name) - .timestamp(timestamp) - .duration(1000) - .success() - .serialize() - ), - ...timerange(start, end) - .interval(interval) - .rate(transaction.failureRate) - .flatMap((timestamp) => - serviceGoProdInstance - .transaction(transaction.name) - .errors( - serviceGoProdInstance - .error(`Error ${index}`, transaction.name) - .timestamp(timestamp) - ) - .duration(1000) - .timestamp(timestamp) - .failure() - .serialize() - ), - ]; - }) - .flatMap((_) => _); - - await synthtraceEsClient.index(indices); + await generateData({ serviceName, start, end, synthtraceEsClient }); }); after(() => synthtraceEsClient.clean()); @@ -154,48 +104,83 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('with comparison', () => { - let errorsDistribution: ErrorsDistribution; - before(async () => { - const fiveMinutes = 5 * 60 * 1000; - const response = await callApi({ - query: { - start: new Date(end - fiveMinutes).toISOString(), - end: new Date(end).toISOString(), - comparisonStart: new Date(start).toISOString(), - comparisonEnd: new Date(start + fiveMinutes).toISOString(), - }, + describe('when data is returned', () => { + let errorsDistribution: ErrorsDistribution; + before(async () => { + const fiveMinutes = 5 * 60 * 1000; + const response = await callApi({ + query: { + start: new Date(end - fiveMinutes).toISOString(), + end: new Date(end).toISOString(), + comparisonStart: new Date(start).toISOString(), + comparisonEnd: new Date(start + fiveMinutes).toISOString(), + }, + }); + errorsDistribution = response.body; }); - errorsDistribution = response.body; - }); - it('returns some data', () => { - const hasCurrentPeriodData = errorsDistribution.currentPeriod.some(({ y }) => - isFiniteNumber(y) - ); + it('returns some data', () => { + const hasCurrentPeriodData = errorsDistribution.currentPeriod.some(({ y }) => + isFiniteNumber(y) + ); - const hasPreviousPeriodData = errorsDistribution.previousPeriod.some(({ y }) => - isFiniteNumber(y) - ); + const hasPreviousPeriodData = errorsDistribution.previousPeriod.some(({ y }) => + isFiniteNumber(y) + ); - expect(hasCurrentPeriodData).to.equal(true); - expect(hasPreviousPeriodData).to.equal(true); - }); + expect(hasCurrentPeriodData).to.equal(true); + expect(hasPreviousPeriodData).to.equal(true); + }); - it('has same start time for both periods', () => { - expect(first(errorsDistribution.currentPeriod)?.x).to.equal( - first(errorsDistribution.previousPeriod)?.x - ); - }); + it('has same start time for both periods', () => { + expect(first(errorsDistribution.currentPeriod)?.x).to.equal( + first(errorsDistribution.previousPeriod)?.x + ); + }); - it('has same end time for both periods', () => { - expect(last(errorsDistribution.currentPeriod)?.x).to.equal( - last(errorsDistribution.previousPeriod)?.x - ); + it('has same end time for both periods', () => { + expect(last(errorsDistribution.currentPeriod)?.x).to.equal( + last(errorsDistribution.previousPeriod)?.x + ); + }); + + it('returns same number of buckets for both periods', () => { + expect(errorsDistribution.currentPeriod.length).to.equal( + errorsDistribution.previousPeriod.length + ); + }); }); - it('returns same number of buckets for both periods', () => { - expect(errorsDistribution.currentPeriod.length).to.equal( - errorsDistribution.previousPeriod.length - ); + describe('when no data is returned', () => { + let errorsDistribution: ErrorsDistribution; + before(async () => { + const response = await callApi({ + query: { + start: '2021-01-03T00:00:00.000Z', + end: '2021-01-03T00:15:00.000Z', + comparisonStart: '2021-01-02T00:00:00.000Z', + comparisonEnd: '2021-01-02T00:15:00.000Z', + }, + }); + errorsDistribution = response.body; + }); + + it('has same start time for both periods', () => { + expect(first(errorsDistribution.currentPeriod)?.x).to.equal( + first(errorsDistribution.previousPeriod)?.x + ); + }); + + it('has same end time for both periods', () => { + expect(last(errorsDistribution.currentPeriod)?.x).to.equal( + last(errorsDistribution.previousPeriod)?.x + ); + }); + + it('returns same number of buckets for both periods', () => { + expect(errorsDistribution.currentPeriod.length).to.equal( + errorsDistribution.previousPeriod.length + ); + }); }); }); }); diff --git a/x-pack/test/apm_api_integration/tests/errors/error_group_list.ts b/x-pack/test/apm_api_integration/tests/errors/error_group_list.ts new file mode 100644 index 0000000000000..4b5cbf4a2662a --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/errors/error_group_list.ts @@ -0,0 +1,150 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import expect from '@kbn/expect'; +import { service, timerange } from '@elastic/apm-synthtrace'; +import { + APIClientRequestParamsOf, + APIReturnType, +} from '../../../../plugins/apm/public/services/rest/createCallApmApi'; +import { RecursivePartial } from '../../../../plugins/apm/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +type ErrorGroups = APIReturnType<'GET /internal/apm/services/{serviceName}/errors'>['errorGroups']; + +export default function ApiTest({ getService }: FtrProviderContext) { + const apmApiClient = getService('apmApiClient'); + const synthtraceEsClient = getService('synthtraceEsClient'); + + const serviceName = 'synth-go'; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + + async function callApi( + overrides?: RecursivePartial< + APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/errors'>['params'] + > + ) { + return await apmApiClient.readUser({ + endpoint: `GET /internal/apm/services/{serviceName}/errors`, + params: { + path: { serviceName, ...overrides?.path }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + environment: 'ENVIRONMENT_ALL', + kuery: '', + ...overrides?.query, + }, + }, + }); + } + + registry.when('when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles empty state', async () => { + const response = await callApi(); + expect(response.status).to.be(200); + expect(response.body.errorGroups).to.empty(); + }); + }); + + registry.when( + 'when data is loaded', + { config: 'basic', archives: ['apm_mappings_only_8.0.0'] }, + () => { + describe('errors group', () => { + const appleTransaction = { + name: 'GET /apple 🍎 ', + successRate: 75, + failureRate: 25, + }; + + const bananaTransaction = { + name: 'GET /banana 🍌', + successRate: 50, + failureRate: 50, + }; + + before(async () => { + const serviceInstance = service(serviceName, 'production', 'go').instance('instance-a'); + + await synthtraceEsClient.index([ + ...timerange(start, end) + .interval('1m') + .rate(appleTransaction.successRate) + .flatMap((timestamp) => + serviceInstance + .transaction(appleTransaction.name) + .timestamp(timestamp) + .duration(1000) + .success() + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(appleTransaction.failureRate) + .flatMap((timestamp) => + serviceInstance + .transaction(appleTransaction.name) + .errors(serviceInstance.error('error 1', 'foo').timestamp(timestamp)) + .duration(1000) + .timestamp(timestamp) + .failure() + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(bananaTransaction.successRate) + .flatMap((timestamp) => + serviceInstance + .transaction(bananaTransaction.name) + .timestamp(timestamp) + .duration(1000) + .success() + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(bananaTransaction.failureRate) + .flatMap((timestamp) => + serviceInstance + .transaction(bananaTransaction.name) + .errors(serviceInstance.error('error 2', 'bar').timestamp(timestamp)) + .duration(1000) + .timestamp(timestamp) + .failure() + .serialize() + ), + ]); + }); + + after(() => synthtraceEsClient.clean()); + + describe('returns the correct data', () => { + let errorGroups: ErrorGroups; + before(async () => { + const response = await callApi(); + errorGroups = response.body.errorGroups; + }); + + it('returns correct number of errors', () => { + expect(errorGroups.length).to.equal(2); + expect(errorGroups.map((error) => error.message).sort()).to.eql(['error 1', 'error 2']); + }); + + it('returns correct occurences', () => { + const numberOfBuckets = 15; + expect(errorGroups.map((error) => error.occurrenceCount).sort()).to.eql([ + appleTransaction.failureRate * numberOfBuckets, + bananaTransaction.failureRate * numberOfBuckets, + ]); + }); + }); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts new file mode 100644 index 0000000000000..f7874b1c61495 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { service, SynthtraceEsClient, timerange } from '@elastic/apm-synthtrace'; + +export const config = { + appleTransaction: { + name: 'GET /apple 🍎 ', + successRate: 75, + failureRate: 25, + }, + bananaTransaction: { + name: 'GET /banana 🍌', + successRate: 50, + failureRate: 50, + }, +}; + +export async function generateData({ + synthtraceEsClient, + serviceName, + start, + end, +}: { + synthtraceEsClient: SynthtraceEsClient; + serviceName: string; + start: number; + end: number; +}) { + const serviceGoProdInstance = service(serviceName, 'production', 'go').instance('instance-a'); + + const interval = '1m'; + + const { bananaTransaction, appleTransaction } = config; + + const documents = [appleTransaction, bananaTransaction] + .map((transaction, index) => { + return [ + ...timerange(start, end) + .interval(interval) + .rate(transaction.successRate) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction(transaction.name) + .timestamp(timestamp) + .duration(1000) + .success() + .serialize() + ), + ...timerange(start, end) + .interval(interval) + .rate(transaction.failureRate) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction(transaction.name) + .errors( + serviceGoProdInstance.error(`Error ${index}`, transaction.name).timestamp(timestamp) + ) + .duration(1000) + .timestamp(timestamp) + .failure() + .serialize() + ), + ]; + }) + .flatMap((_) => _); + + await synthtraceEsClient.index(documents); +} diff --git a/x-pack/test/apm_api_integration/tests/errors/group_id.ts b/x-pack/test/apm_api_integration/tests/errors/group_id.ts new file mode 100644 index 0000000000000..ef9e293355a7f --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/errors/group_id.ts @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import expect from '@kbn/expect'; +import { + APIClientRequestParamsOf, + APIReturnType, +} from '../../../../plugins/apm/public/services/rest/createCallApmApi'; +import { RecursivePartial } from '../../../../plugins/apm/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; +import { config, generateData } from './generate_data'; + +type ErrorsDistribution = + APIReturnType<'GET /internal/apm/services/{serviceName}/errors/{groupId}'>; + +export default function ApiTest({ getService }: FtrProviderContext) { + const apmApiClient = getService('apmApiClient'); + const synthtraceEsClient = getService('synthtraceEsClient'); + + const serviceName = 'synth-go'; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + + async function callApi( + overrides?: RecursivePartial< + APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/errors/{groupId}'>['params'] + > + ) { + const response = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/errors/{groupId}', + params: { + path: { + serviceName, + groupId: 'foo', + ...overrides?.path, + }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + environment: 'ENVIRONMENT_ALL', + kuery: '', + ...overrides?.query, + }, + }, + }); + return response; + } + + registry.when('when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await callApi(); + expect(response.status).to.be(200); + expect(response.body.occurrencesCount).to.be(0); + }); + }); + + registry.when( + 'when data is loaded', + { config: 'basic', archives: ['apm_mappings_only_8.0.0'] }, + () => { + const { bananaTransaction } = config; + describe('error group id', () => { + before(async () => { + await generateData({ serviceName, start, end, synthtraceEsClient }); + }); + + after(() => synthtraceEsClient.clean()); + + describe('return correct data', () => { + let errorsDistribution: ErrorsDistribution; + before(async () => { + const response = await callApi({ + path: { groupId: '0000000000000000000000000Error 1' }, + }); + errorsDistribution = response.body; + }); + + it('displays correct number of occurrences', () => { + const numberOfBuckets = 15; + expect(errorsDistribution.occurrencesCount).to.equal( + bananaTransaction.failureRate * numberOfBuckets + ); + }); + }); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index 29b40b6ff62cf..46966834a176e 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -241,10 +241,19 @@ export default function apmApiIntegrationTests(providerContext: FtrProviderConte loadTestFile(require.resolve('./latency/service_apis')); }); + // Errors + describe('errors/group_id', function () { + loadTestFile(require.resolve('./errors/group_id')); + }); + describe('errors/distribution', function () { loadTestFile(require.resolve('./errors/distribution')); }); + describe('errors/error_group_list', function () { + loadTestFile(require.resolve('./errors/error_group_list')); + }); + // Dependencies describe('dependencies/metadata', function () { loadTestFile(require.resolve('./dependencies/metadata')); diff --git a/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts b/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts index 89f818f58e875..0507bc8f28b47 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts @@ -38,8 +38,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const body = response.body as ErrorRate; expect(body).to.be.eql({ - currentPeriod: { noHits: true, transactionErrorRate: [], average: null }, - previousPeriod: { noHits: true, transactionErrorRate: [], average: null }, + currentPeriod: { timeseries: [], average: null }, + previousPeriod: { timeseries: [], average: null }, }); }); @@ -62,8 +62,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const body = response.body as ErrorRate; expect(body).to.be.eql({ - currentPeriod: { noHits: true, transactionErrorRate: [], average: null }, - previousPeriod: { noHits: true, transactionErrorRate: [], average: null }, + currentPeriod: { timeseries: [], average: null }, + previousPeriod: { timeseries: [], average: null }, }); }); }); @@ -89,10 +89,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0); expect(errorRateResponse.previousPeriod.average).to.be(null); - expect(errorRateResponse.currentPeriod.transactionErrorRate.length).to.be.greaterThan(0); - expect(errorRateResponse.previousPeriod.transactionErrorRate).to.empty(); + expect(errorRateResponse.currentPeriod.timeseries.length).to.be.greaterThan(0); + expect(errorRateResponse.previousPeriod.timeseries).to.empty(); - const nonNullDataPoints = errorRateResponse.currentPeriod.transactionErrorRate.filter( + const nonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter( ({ y }) => y !== null ); @@ -101,24 +101,18 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('has the correct start date', () => { expectSnapshot( - new Date( - first(errorRateResponse.currentPeriod.transactionErrorRate)?.x ?? NaN - ).toISOString() + new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() ).toMatchInline(`"2021-08-03T06:50:00.000Z"`); }); it('has the correct end date', () => { expectSnapshot( - new Date( - last(errorRateResponse.currentPeriod.transactionErrorRate)?.x ?? NaN - ).toISOString() + new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); }); it('has the correct number of buckets', () => { - expectSnapshot(errorRateResponse.currentPeriod.transactionErrorRate.length).toMatchInline( - `61` - ); + expectSnapshot(errorRateResponse.currentPeriod.timeseries.length).toMatchInline(`61`); }); it('has the correct calculation for average', () => { @@ -128,7 +122,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); it('has the correct error rate', () => { - expectSnapshot(errorRateResponse.currentPeriod.transactionErrorRate).toMatch(); + expectSnapshot(errorRateResponse.currentPeriod.timeseries).toMatch(); }); }); @@ -157,14 +151,15 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0); expect(errorRateResponse.previousPeriod.average).to.be.greaterThan(0); - expect(errorRateResponse.currentPeriod.transactionErrorRate.length).to.be.greaterThan(0); - expect(errorRateResponse.previousPeriod.transactionErrorRate.length).to.be.greaterThan(0); + expect(errorRateResponse.currentPeriod.timeseries.length).to.be.greaterThan(0); + expect(errorRateResponse.previousPeriod.timeseries.length).to.be.greaterThan(0); - const currentPeriodNonNullDataPoints = - errorRateResponse.currentPeriod.transactionErrorRate.filter(({ y }) => y !== null); + const currentPeriodNonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter( + ({ y }) => y !== null + ); const previousPeriodNonNullDataPoints = - errorRateResponse.previousPeriod.transactionErrorRate.filter(({ y }) => y !== null); + errorRateResponse.previousPeriod.timeseries.filter(({ y }) => y !== null); expect(currentPeriodNonNullDataPoints.length).to.be.greaterThan(0); expect(previousPeriodNonNullDataPoints.length).to.be.greaterThan(0); @@ -172,37 +167,25 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('has the correct start date', () => { expectSnapshot( - new Date( - first(errorRateResponse.currentPeriod.transactionErrorRate)?.x ?? NaN - ).toISOString() + new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() ).toMatchInline(`"2021-08-03T07:05:10.000Z"`); expectSnapshot( - new Date( - first(errorRateResponse.previousPeriod.transactionErrorRate)?.x ?? NaN - ).toISOString() + new Date(first(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString() ).toMatchInline(`"2021-08-03T07:05:10.000Z"`); }); it('has the correct end date', () => { expectSnapshot( - new Date( - last(errorRateResponse.currentPeriod.transactionErrorRate)?.x ?? NaN - ).toISOString() + new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() ).toMatchInline(`"2021-08-03T07:20:10.000Z"`); expectSnapshot( - new Date( - last(errorRateResponse.previousPeriod.transactionErrorRate)?.x ?? NaN - ).toISOString() + new Date(last(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString() ).toMatchInline(`"2021-08-03T07:20:10.000Z"`); }); it('has the correct number of buckets', () => { - expectSnapshot(errorRateResponse.currentPeriod.transactionErrorRate.length).toMatchInline( - `91` - ); - expectSnapshot( - errorRateResponse.previousPeriod.transactionErrorRate.length - ).toMatchInline(`91`); + expectSnapshot(errorRateResponse.currentPeriod.timeseries.length).toMatchInline(`91`); + expectSnapshot(errorRateResponse.previousPeriod.timeseries.length).toMatchInline(`91`); }); it('has the correct calculation for average', () => { @@ -215,13 +198,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); it('has the correct error rate', () => { - expectSnapshot(errorRateResponse.currentPeriod.transactionErrorRate).toMatch(); - expectSnapshot(errorRateResponse.previousPeriod.transactionErrorRate).toMatch(); + expectSnapshot(errorRateResponse.currentPeriod.timeseries).toMatch(); + expectSnapshot(errorRateResponse.previousPeriod.timeseries).toMatch(); }); it('matches x-axis on current period and previous period', () => { - expect(errorRateResponse.currentPeriod.transactionErrorRate.map(({ x }) => x)).to.be.eql( - errorRateResponse.previousPeriod.transactionErrorRate.map(({ x }) => x) + expect(errorRateResponse.currentPeriod.timeseries.map(({ x }) => x)).to.be.eql( + errorRateResponse.previousPeriod.timeseries.map(({ x }) => x) ); }); }); diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index ae769bd01b52d..848dbc8fd50af 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -809,16 +809,18 @@ export const getSimpleRuleOutputWithWebHookAction = (actionId: string): Partial< export const waitFor = async ( functionToTest: () => Promise, functionName: string, - maxTimeout: number = 20000, - timeoutWait: number = 10 + maxTimeout: number = 800000, + timeoutWait: number = 250 ): Promise => { let found = false; let numberOfTries = 0; - - while (!found && numberOfTries < Math.floor(maxTimeout / timeoutWait)) { + const maxTries = Math.floor(maxTimeout / timeoutWait); + while (!found && numberOfTries < maxTries) { if (await functionToTest()) { found = true; } else { + // eslint-disable-next-line no-console + console.log(`Try number ${numberOfTries} out of ${maxTries} for function ${functionName}`); numberOfTries++; } @@ -940,9 +942,9 @@ export const createRule = async ( if (rule.rule_id != null) { // eslint-disable-next-line no-console console.log( - `When creating a rule found an unexpected conflict (409), will attempt a cleanup and one time re-try. This usually indicates a bad cleanup or race condition within the tests: ${JSON.stringify( + `Did not get an expected 200 "ok" when creating a rule (createRule). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( response.body - )}` + )}, status: ${JSON.stringify(response.status)}` ); await deleteRule(supertest, rule.rule_id); const secondResponseTry = await supertest @@ -986,7 +988,7 @@ export const deleteRule = async ( if (response.status !== 200) { // eslint-disable-next-line no-console console.log( - `Did not get an expected 200 "ok" when deleting the rule. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + `Did not get an expected 200 "ok" when deleting the rule (deleteRule). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( response.body )}, status: ${JSON.stringify(response.status)}` ); @@ -1023,12 +1025,19 @@ export const updateRule = async ( supertest: SuperTest.SuperTest, updatedRule: UpdateRulesSchema ): Promise => { - const { body } = await supertest + const response = await supertest .put(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(updatedRule) - .expect(200); - return body; + .send(updatedRule); + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when updating a rule (updateRule). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + return response.body; }; /** @@ -1037,12 +1046,19 @@ export const updateRule = async ( * @param supertest The supertest deps */ export const createNewAction = async (supertest: SuperTest.SuperTest) => { - const { body } = await supertest + const response = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') - .send(getWebHookAction()) - .expect(200); - return body; + .send(getWebHookAction()); + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when creating a new action. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + return response.body; }; /** @@ -1059,14 +1075,21 @@ export const findImmutableRuleById = async ( total: number; data: FullResponseSchema[]; }> => { - const { body } = await supertest + const response = await supertest .get( `${DETECTION_ENGINE_RULES_URL}/_find?filter=alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:true" AND alert.attributes.tags: "${INTERNAL_RULE_ID_KEY}:${ruleId}"` ) .set('kbn-xsrf', 'true') - .send() - .expect(200); - return body; + .send(); + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when finding an immutable rule by id (findImmutableRuleById). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + return response.body; }; /** @@ -1077,12 +1100,20 @@ export const findImmutableRuleById = async ( export const getPrePackagedRulesStatus = async ( supertest: SuperTest.SuperTest ): Promise => { - const { body } = await supertest + const response = await supertest .get(`${DETECTION_ENGINE_PREPACKAGED_URL}/_status`) .set('kbn-xsrf', 'true') - .send() - .expect(200); - return body; + .send(); + + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when getting a pre-packaged rule status. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + return response.body; }; /** @@ -1104,9 +1135,9 @@ export const createExceptionList = async ( if (exceptionList.list_id != null) { // eslint-disable-next-line no-console console.log( - `When creating an exception list found an unexpected conflict (409), will attempt a cleanup and one time re-try. This usually indicates a bad cleanup or race condition within the tests: ${JSON.stringify( + `When creating an exception list found an unexpected conflict (409) creating an exception list (createExceptionList), will attempt a cleanup and one time re-try. This usually indicates a bad cleanup or race condition within the tests: ${JSON.stringify( response.body - )}` + )}, status: ${JSON.stringify(response.status)}` ); await deleteExceptionList(supertest, exceptionList.list_id); const secondResponseTry = await supertest @@ -1152,7 +1183,7 @@ export const deleteExceptionList = async ( if (response.status !== 200) { // eslint-disable-next-line no-console console.log( - `Did not get an expected 200 "ok" when deleting an exception list. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + `Did not get an expected 200 "ok" when deleting an exception list (deleteExceptionList). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( response.body )}, status: ${JSON.stringify(response.status)}` ); @@ -1179,7 +1210,7 @@ export const createExceptionListItem = async ( if (response.status !== 200) { // eslint-disable-next-line no-console console.log( - `Did not get an expected 200 "ok" when creating an exception list item. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + `Did not get an expected 200 "ok" when creating an exception list item (createExceptionListItem). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( response.body )}, status: ${JSON.stringify(response.status)}` ); @@ -1197,11 +1228,19 @@ export const getRule = async ( supertest: SuperTest.SuperTest, ruleId: string ): Promise => { - const { body } = await supertest + const response = await supertest .get(`${DETECTION_ENGINE_RULES_URL}?rule_id=${ruleId}`) - .set('kbn-xsrf', 'true') - .expect(200); - return body; + .set('kbn-xsrf', 'true'); + + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when getting a rule (getRule). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + return response.body; }; export const waitForAlertToComplete = async ( @@ -1209,11 +1248,16 @@ export const waitForAlertToComplete = async ( id: string ): Promise => { await waitFor(async () => { - const { body: alertBody } = await supertest - .get(`/api/alerts/alert/${id}/state`) - .set('kbn-xsrf', 'true') - .expect(200); - return alertBody.previousStartedAt != null; + const response = await supertest.get(`/api/alerts/alert/${id}/state`).set('kbn-xsrf', 'true'); + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when waiting for an alert to complete (waitForAlertToComplete). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + return response.body.previousStartedAt != null; }, 'waitForAlertToComplete'); }; @@ -1229,12 +1273,28 @@ export const waitForRuleSuccessOrStatus = async ( ): Promise => { await waitFor(async () => { try { - const { body } = await supertest + const response = await supertest .post(`${DETECTION_ENGINE_RULES_URL}/_find_statuses`) .set('kbn-xsrf', 'true') - .send({ ids: [id] }) - .expect(200); - return body[id]?.current_status?.status === status; + .send({ ids: [id] }); + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when waiting for a rule success or status (waitForRuleSuccessOrStatus). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + if (response.body[id]?.current_status?.status !== status) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected status of ${status} while waiting for a rule success or status for rule id ${id} (waitForRuleSuccessOrStatus). Will continue retrying until status is found. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + + return response.body[id]?.current_status?.status === status; } catch (e) { if ((e as Error).message.includes('got 503 "Service Unavailable"')) { return false; @@ -1274,11 +1334,21 @@ export const getSignalsByRuleIds = async ( supertest: SuperTest.SuperTest, ruleIds: string[] ): Promise> => { - const { body: signalsOpen }: { body: estypes.SearchResponse } = await supertest + const response = await supertest .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) .set('kbn-xsrf', 'true') - .send(getQuerySignalsRuleId(ruleIds)) - .expect(200); + .send(getQuerySignalsRuleId(ruleIds)); + + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when getting a signal by rule_id (getSignalsByRuleIds). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + + const { body: signalsOpen }: { body: estypes.SearchResponse } = response; return signalsOpen; }; @@ -1293,11 +1363,20 @@ export const getSignalsByIds = async ( ids: string[], size?: number ): Promise> => { - const { body: signalsOpen }: { body: estypes.SearchResponse } = await supertest + const response = await supertest .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) .set('kbn-xsrf', 'true') - .send(getQuerySignalsId(ids, size)) - .expect(200); + .send(getQuerySignalsId(ids, size)); + + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when getting a signal by id. CI issues could happen (getSignalsByIds). Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + const { body: signalsOpen }: { body: estypes.SearchResponse } = response; return signalsOpen; }; @@ -1310,11 +1389,20 @@ export const getSignalsById = async ( supertest: SuperTest.SuperTest, id: string ): Promise> => { - const { body: signalsOpen }: { body: estypes.SearchResponse } = await supertest + const response = await supertest .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) .set('kbn-xsrf', 'true') - .send(getQuerySignalsId([id])) - .expect(200); + .send(getQuerySignalsId([id])); + + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when getting signals by id (getSignalsById). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } + const { body: signalsOpen }: { body: estypes.SearchResponse } = response; return signalsOpen; }; @@ -1322,10 +1410,19 @@ export const installPrePackagedRules = async ( supertest: SuperTest.SuperTest ): Promise => { await countDownTest(async () => { - const { status } = await supertest + const { status, body } = await supertest .put(DETECTION_ENGINE_PREPACKAGED_URL) .set('kbn-xsrf', 'true') .send(); + if (status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when installing pre-packaged rules (installPrePackagedRules) yet. Retrying until we get a 200 "ok". body: ${JSON.stringify( + body + )}, status: ${JSON.stringify(status)}` + ); + } + return status === 200; }, 'installPrePackagedRules'); }; @@ -1480,12 +1577,19 @@ export const createRuleWithExceptionEntries = async ( exceptions_list: [...maybeExceptionList, ...maybeEndpointList], }; const ruleResponse = await createRule(supertest, ruleWithException); - await supertest + const response = await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send({ rule_id: ruleResponse.rule_id, enabled: true }) - .expect(200); + .send({ rule_id: ruleResponse.rule_id, enabled: true }); + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when patching a rule with exception entries (createRuleWithExceptionEntries). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } return ruleResponse; }; @@ -1542,14 +1646,22 @@ export const startSignalsMigration = async ({ supertest: SuperTest.SuperTest; indices: string[]; }): Promise => { - const { - body: { indices: created }, - }: { body: { indices: CreateMigrationResponse[] } } = await supertest + const response = await supertest .post(DETECTION_ENGINE_SIGNALS_MIGRATION_URL) .set('kbn-xsrf', 'true') - .send({ index: indices }) - .expect(200); + .send({ index: indices }); + const { + body: { indices: created }, + }: { body: { indices: CreateMigrationResponse[] } } = response; + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when starting a signals migration (startSignalsMigration). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } return created; }; @@ -1566,14 +1678,22 @@ export const finalizeSignalsMigration = async ({ supertest: SuperTest.SuperTest; migrationIds: string[]; }): Promise => { - const { - body: { migrations }, - }: { body: { migrations: FinalizeMigrationResponse[] } } = await supertest + const response = await supertest .post(DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL) .set('kbn-xsrf', 'true') - .send({ migration_ids: migrationIds }) - .expect(200); + .send({ migration_ids: migrationIds }); + const { + body: { migrations }, + }: { body: { migrations: FinalizeMigrationResponse[] } } = response; + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when finalizing signals migration (finalizeSignalsMigration). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } return migrations; }; diff --git a/x-pack/test/examples/embedded_lens/embedded_example.ts b/x-pack/test/examples/embedded_lens/embedded_example.ts index 3a0891079f24e..d11495f0450b4 100644 --- a/x-pack/test/examples/embedded_lens/embedded_example.ts +++ b/x-pack/test/examples/embedded_lens/embedded_example.ts @@ -16,8 +16,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); async function checkData() { - const data = await elasticChart.getChartDebugData(); - expect(data!.bars![0].bars.length).to.eql(24); + await retry.try(async () => { + const data = await elasticChart.getChartDebugData(); + expect(data!.bars![0].bars.length).to.eql(24); + }); } describe('show and save', () => { diff --git a/x-pack/test/fleet_cypress/agent.ts b/x-pack/test/fleet_cypress/agent.ts new file mode 100644 index 0000000000000..e05a21c6a63e3 --- /dev/null +++ b/x-pack/test/fleet_cypress/agent.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ToolingLog } from '@kbn/dev-utils'; +import axios, { AxiosRequestConfig } from 'axios'; +import { ChildProcess, spawn } from 'child_process'; +import { getLatestVersion } from './artifact_manager'; +import { Manager } from './resource_manager'; + +interface AgentManagerParams { + user: string; + password: string; + kibanaUrl: string; + esHost: string; +} + +export class AgentManager extends Manager { + private params: AgentManagerParams; + private log: ToolingLog; + private agentProcess?: ChildProcess; + private requestOptions: AxiosRequestConfig; + constructor(params: AgentManagerParams, log: ToolingLog) { + super(); + this.log = log; + this.params = params; + this.requestOptions = { + headers: { + 'kbn-xsrf': 'kibana', + }, + auth: { + username: this.params.user, + password: this.params.password, + }, + }; + } + + public async setup() { + this.log.info('Running agent preconfig'); + return await axios.post( + `${this.params.kibanaUrl}/api/fleet/agents/setup`, + {}, + this.requestOptions + ); + } + + public async startAgent() { + this.log.info('Getting agent enrollment key'); + const { data: apiKeys } = await axios.get( + this.params.kibanaUrl + '/api/fleet/enrollment-api-keys', + this.requestOptions + ); + const policy = apiKeys.list[1]; + + this.log.info('Running the agent'); + + const artifact = `docker.elastic.co/beats/elastic-agent:${await getLatestVersion()}`; + this.log.info(artifact); + + const args = [ + 'run', + '--add-host', + 'host.docker.internal:host-gateway', + '--env', + 'FLEET_ENROLL=1', + '--env', + `FLEET_URL=http://host.docker.internal:8220`, + '--env', + `FLEET_ENROLLMENT_TOKEN=${policy.api_key}`, + '--env', + 'FLEET_INSECURE=true', + '--rm', + artifact, + ]; + + this.agentProcess = spawn('docker', args, { stdio: 'inherit' }); + + // Wait til we see the agent is online + let done = false; + let retries = 0; + while (!done) { + await new Promise((r) => setTimeout(r, 5000)); + const { data: agents } = await axios.get( + `${this.params.kibanaUrl}/api/fleet/agents`, + this.requestOptions + ); + done = agents.list[0]?.status === 'online'; + if (++retries > 12) { + this.log.error('Giving up on enrolling the agent after a minute'); + throw new Error('Agent timed out while coming online'); + } + } + + return { policyId: policy.policy_id as string }; + } + + protected _cleanup() { + this.log.info('Cleaning up the agent process'); + if (this.agentProcess) { + if (!this.agentProcess.kill(9)) { + this.log.warning('Unable to kill agent process'); + } + + this.agentProcess.on('close', () => { + this.log.info('Agent process closed'); + }); + delete this.agentProcess; + } + return; + } +} diff --git a/x-pack/test/fleet_cypress/artifact_manager.ts b/x-pack/test/fleet_cypress/artifact_manager.ts new file mode 100644 index 0000000000000..aea0eb8bbec86 --- /dev/null +++ b/x-pack/test/fleet_cypress/artifact_manager.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import axios from 'axios'; +import { last } from 'lodash'; + +export async function getLatestVersion(): Promise { + const response: any = await axios('https://artifacts-api.elastic.co/v1/versions'); + return last(response.data.versions as string[]) || '8.0.0-SNAPSHOT'; +} diff --git a/x-pack/test/fleet_cypress/cli_config.ts b/x-pack/test/fleet_cypress/cli_config.ts new file mode 100644 index 0000000000000..b8eb78e6a4abc --- /dev/null +++ b/x-pack/test/fleet_cypress/cli_config.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +import { FleetCypressCliTestRunner } from './runner'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const cypressConfig = await readConfigFile(require.resolve('./config.ts')); + return { + ...cypressConfig.getAll(), + + testRunner: FleetCypressCliTestRunner, + }; +} diff --git a/x-pack/test/fleet_cypress/config.ts b/x-pack/test/fleet_cypress/config.ts new file mode 100644 index 0000000000000..14898f81aac12 --- /dev/null +++ b/x-pack/test/fleet_cypress/config.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +import { CA_CERT_PATH } from '@kbn/dev-utils'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const kibanaCommonTestsConfig = await readConfigFile( + require.resolve('../../../test/common/config.js') + ); + const xpackFunctionalTestsConfig = await readConfigFile( + require.resolve('../functional/config.js') + ); + + return { + ...kibanaCommonTestsConfig.getAll(), + + esTestCluster: { + ...xpackFunctionalTestsConfig.get('esTestCluster'), + serverArgs: [ + ...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs'), + // define custom es server here + // API Keys is enabled at the top level + 'xpack.security.enabled=true', + 'http.host=0.0.0.0', + ], + }, + + kbnTestServer: { + ...xpackFunctionalTestsConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs'), + '--csp.strict=false', + // define custom kibana server args here + `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`, + ], + }, + }; +} diff --git a/x-pack/test/fleet_cypress/fleet_server.ts b/x-pack/test/fleet_cypress/fleet_server.ts new file mode 100644 index 0000000000000..fe2b8c7459229 --- /dev/null +++ b/x-pack/test/fleet_cypress/fleet_server.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ChildProcess, spawn } from 'child_process'; +import { ToolingLog } from '@kbn/dev-utils'; +import axios from 'axios'; +import { Manager } from './resource_manager'; +import { getLatestVersion } from './artifact_manager'; + +export interface ElasticsearchConfig { + esHost: string; + user: string; + password: string; + port: string; +} + +export class FleetManager extends Manager { + private fleetProcess?: ChildProcess; + private esConfig: ElasticsearchConfig; + private log: ToolingLog; + constructor(esConfig: ElasticsearchConfig, log: ToolingLog) { + super(); + this.esConfig = esConfig; + this.log = log; + } + public async setup(): Promise { + this.log.info('Setting fleet up'); + return new Promise(async (res, rej) => { + try { + const response = await axios.post( + `${this.esConfig.esHost}/_security/service/elastic/fleet-server/credential/token` + ); + const serviceToken = response.data.token.value; + const artifact = `docker.elastic.co/beats/elastic-agent:${await getLatestVersion()}`; + this.log.info(artifact); + + const host = 'host.docker.internal'; + + const args = [ + 'run', + '-p', + `8220:8220`, + '--add-host', + 'host.docker.internal:host-gateway', + '--env', + 'FLEET_SERVER_ENABLE=true', + '--env', + `FLEET_SERVER_ELASTICSEARCH_HOST=http://${host}:${this.esConfig.port}`, + '--env', + `FLEET_SERVER_SERVICE_TOKEN=${serviceToken}`, + '--rm', + artifact, + ]; + this.fleetProcess = spawn('docker', args, { + stdio: 'inherit', + }); + this.fleetProcess.on('error', rej); + setTimeout(res, 15000); + } catch (error) { + rej(error); + } + }); + } + + protected _cleanup() { + this.log.info('Removing old fleet config'); + if (this.fleetProcess) { + this.log.info('Closing fleet process'); + if (!this.fleetProcess.kill(9)) { + this.log.warning('Unable to kill fleet server process'); + } + + this.fleetProcess.on('close', () => { + this.log.info('Fleet server process closed'); + }); + delete this.fleetProcess; + } + } +} diff --git a/x-pack/test/fleet_cypress/ftr_provider_context.d.ts b/x-pack/test/fleet_cypress/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..aa56557c09df8 --- /dev/null +++ b/x-pack/test/fleet_cypress/ftr_provider_context.d.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { GenericFtrProviderContext } from '@kbn/test'; + +import { services } from './services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/fleet_cypress/resource_manager.ts b/x-pack/test/fleet_cypress/resource_manager.ts new file mode 100644 index 0000000000000..e892021155417 --- /dev/null +++ b/x-pack/test/fleet_cypress/resource_manager.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +const CLEANUP_EVENTS = ['SIGINT', 'exit', 'uncaughtException', 'unhandledRejection']; +export class Manager { + private cleaned = false; + constructor() { + const cleanup = () => this.cleanup(); + CLEANUP_EVENTS.forEach((ev) => process.on(ev, cleanup)); + } + // This must be a synchronous method because it is used in the unhandledException and exit event handlers + public cleanup() { + // Since this can be called multiple places we proxy it with some protection + if (this._cleanup && !this.cleaned) { + this.cleaned = true; + this._cleanup(); + } + } + protected _cleanup?(): void; +} diff --git a/x-pack/test/fleet_cypress/runner.ts b/x-pack/test/fleet_cypress/runner.ts new file mode 100644 index 0000000000000..b49bfbdc091e2 --- /dev/null +++ b/x-pack/test/fleet_cypress/runner.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { resolve } from 'path'; +import Url from 'url'; + +import { withProcRunner } from '@kbn/dev-utils'; + +import { FtrProviderContext } from './ftr_provider_context'; + +import { AgentManager } from './agent'; +import { FleetManager } from './fleet_server'; + +async function withFleetAgent( + { getService }: FtrProviderContext, + runner: (runnerEnv: Record) => Promise +) { + const log = getService('log'); + const config = getService('config'); + + const esHost = Url.format(config.get('servers.elasticsearch')); + const esConfig = { + user: config.get('servers.elasticsearch.username'), + password: config.get('servers.elasticsearch.password'), + esHost, + port: config.get('servers.elasticsearch.port'), + }; + const fleetManager = new FleetManager(esConfig, log); + + const agentManager = new AgentManager( + { + ...esConfig, + kibanaUrl: Url.format({ + protocol: config.get('servers.kibana.protocol'), + hostname: config.get('servers.kibana.hostname'), + port: config.get('servers.kibana.port'), + }), + }, + log + ); + + // Since the managers will create uncaughtException event handlers we need to exit manually + process.on('uncaughtException', (err) => { + // eslint-disable-next-line no-console + console.error('Encountered error; exiting after cleanup.', err); + process.exit(1); + }); + + await agentManager.setup(); + await fleetManager.setup(); + try { + await runner({}); + } finally { + fleetManager.cleanup(); + agentManager.cleanup(); + } +} + +export async function FleetCypressCliTestRunner(context: FtrProviderContext) { + await startFleetAgent(context, 'run'); +} + +export async function FleetCypressVisualTestRunner(context: FtrProviderContext) { + await startFleetAgent(context, 'open'); +} + +function startFleetAgent(context: FtrProviderContext, cypressCommand: string) { + const log = context.getService('log'); + const config = context.getService('config'); + return withFleetAgent(context, (runnerEnv) => + withProcRunner(log, async (procs) => { + await procs.run('cypress', { + cmd: 'yarn', + args: [`cypress:${cypressCommand}`], + cwd: resolve(__dirname, '../../plugins/fleet'), + env: { + FORCE_COLOR: '1', + // eslint-disable-next-line @typescript-eslint/naming-convention + CYPRESS_baseUrl: Url.format(config.get('servers.kibana')), + // eslint-disable-next-line @typescript-eslint/naming-convention + CYPRESS_protocol: config.get('servers.kibana.protocol'), + // eslint-disable-next-line @typescript-eslint/naming-convention + CYPRESS_hostname: config.get('servers.kibana.hostname'), + // eslint-disable-next-line @typescript-eslint/naming-convention + CYPRESS_configport: config.get('servers.kibana.port'), + CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), + CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'), + CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'), + CYPRESS_KIBANA_URL: Url.format({ + protocol: config.get('servers.kibana.protocol'), + hostname: config.get('servers.kibana.hostname'), + port: config.get('servers.kibana.port'), + }), + ...runnerEnv, + ...process.env, + }, + wait: true, + }); + }) + ); +} diff --git a/x-pack/test/fleet_cypress/services.ts b/x-pack/test/fleet_cypress/services.ts new file mode 100644 index 0000000000000..5e063134081ad --- /dev/null +++ b/x-pack/test/fleet_cypress/services.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from '../../../test/common/services'; diff --git a/x-pack/test/fleet_cypress/visual_config.ts b/x-pack/test/fleet_cypress/visual_config.ts new file mode 100644 index 0000000000000..1a343b52c1161 --- /dev/null +++ b/x-pack/test/fleet_cypress/visual_config.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +import { FleetCypressVisualTestRunner } from './runner'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const cypressConfig = await readConfigFile(require.resolve('./config.ts')); + return { + ...cypressConfig.getAll(), + + testRunner: FleetCypressVisualTestRunner, + }; +} diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index ebe76ee52499b..7efa86c3acf28 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -177,7 +177,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('does not show Management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Discover']); + expect(navLinks).to.eql(['Discover']); }); it(`does not allow navigation to advanced settings; shows "not found" error`, async () => { diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts index 5a73f31c8427f..983a3101b9e31 100644 --- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts +++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts @@ -67,7 +67,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows canvas navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Canvas']); + expect(navLinks).to.eql(['Canvas']); }); it(`landing page shows "Create new workpad" button`, async () => { @@ -142,7 +142,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows canvas navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Canvas']); + expect(navLinks).to.eql(['Canvas']); }); it(`landing page shows disabled "Create new workpad" button`, async () => { diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts index 70f6fc49f0063..e7aa3e6a54e60 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts +++ b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts @@ -89,11 +89,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('only shows the dashboard navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map((link) => link.text)).to.eql([ - 'Overview', - 'Dashboard', - 'Stack Management', - ]); + expect(navLinks.map((link) => link.text)).to.eql(['Dashboard', 'Stack Management']); }); it(`landing page shows "Create new Dashboard" button`, async () => { @@ -296,7 +292,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows dashboard navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Dashboard']); + expect(navLinks).to.eql(['Dashboard']); }); it(`landing page doesn't show "Create new Dashboard" button`, async () => { @@ -427,7 +423,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows dashboard navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Dashboard']); + expect(navLinks).to.eql(['Dashboard']); }); it(`landing page doesn't show "Create new Dashboard" button`, async () => { @@ -502,7 +498,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - describe('no dashboard privileges', () => { + // FLAKY: https://github.com/elastic/kibana/issues/116881 + describe.skip('no dashboard privileges', () => { before(async () => { await security.role.create('no_dashboard_privileges_role', { elasticsearch: { diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index 2010bfd56d2af..8ebf277d63cbe 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -91,7 +91,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows discover navlink', async () => { const navLinks = await appsMenu.readLinks(); expect(navLinks.map((link) => link.text)).to.eql([ - 'Overview', 'Discover', 'Stack Management', // because `global_discover_all_role` enables search sessions and reporting ]); @@ -201,7 +200,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows discover navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Discover']); + expect(navLinks).to.eql(['Discover']); }); it(`doesn't show save button`, async () => { @@ -293,7 +292,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows discover navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Discover']); + expect(navLinks).to.eql(['Discover']); }); it(`doesn't show save button`, async () => { diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts index 913a5034bacc5..69f2f585d8dba 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts @@ -67,7 +67,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows graph navlink', async () => { const navLinks = await appsMenu.readLinks(); - expect(navLinks.map((link) => link.text)).to.eql(['Overview', 'Graph']); + expect(navLinks.map((link) => link.text)).to.eql(['Graph']); }); it('landing page shows "Create new graph" button', async () => { @@ -130,7 +130,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows graph navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Graph']); + expect(navLinks).to.eql(['Graph']); }); it('does not show a "Create new Workspace" button', async () => { diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index c1610ebe0709f..d04ec8f4d66b4 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -179,7 +179,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('does not show Management navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Discover']); + expect(navLinks).to.eql(['Discover']); }); it(`doesn't show Index Patterns in management side-nav`, async () => { diff --git a/x-pack/test/functional/apps/management/feature_controls/management_security.ts b/x-pack/test/functional/apps/management/feature_controls/management_security.ts index 8235bf6e1e9e2..5366274cd6f58 100644 --- a/x-pack/test/functional/apps/management/feature_controls/management_security.ts +++ b/x-pack/test/functional/apps/management/feature_controls/management_security.ts @@ -36,7 +36,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should not show the Stack Management nav link', async () => { const links = await appsMenu.readLinks(); - expect(links.map((link) => link.text)).to.eql(['Overview', 'Dashboard']); + expect(links.map((link) => link.text)).to.eql(['Dashboard']); }); it('should render the "application not found" view when navigating to management directly', async () => { diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index b141aeea16cfe..dcd82ea05ccf3 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -165,7 +165,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows Maps navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Maps']); + expect(navLinks).to.eql(['Maps']); }); it(`does not show create new button`, async () => { diff --git a/x-pack/test/functional/apps/maps/index.js b/x-pack/test/functional/apps/maps/index.js index 33184f2d35213..6a2a843682f26 100644 --- a/x-pack/test/functional/apps/maps/index.js +++ b/x-pack/test/functional/apps/maps/index.js @@ -79,7 +79,7 @@ export default function ({ loadTestFile, getService }) { loadTestFile(require.resolve('./joins')); loadTestFile(require.resolve('./mapbox_styles')); loadTestFile(require.resolve('./mvt_scaling')); - loadTestFile(require.resolve('./mvt_super_fine')); + loadTestFile(require.resolve('./mvt_geotile_grid')); 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_geotile_grid.js similarity index 52% rename from x-pack/test/functional/apps/maps/mvt_super_fine.js rename to x-pack/test/functional/apps/maps/mvt_geotile_grid.js index 6c5065a77c1d2..ffda75f8bf98a 100644 --- a/x-pack/test/functional/apps/maps/mvt_super_fine.js +++ b/x-pack/test/functional/apps/maps/mvt_geotile_grid.js @@ -14,13 +14,12 @@ export default function ({ getPageObjects, getService }) { const inspector = getService('inspector'); const security = getService('security'); - describe('mvt grid layer', () => { + describe('mvt geotile 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 () => { @@ -28,7 +27,8 @@ export default function ({ getPageObjects, getService }) { await security.testUser.restoreDefaults(); }); - it('should render with mvt-source', async () => { + it('should render with mvt-source (style meta from ES)', async () => { + await PageObjects.maps.loadSavedMap('MVT geotile grid (style meta from ES)'); const mapboxStyle = await PageObjects.maps.getMapboxStyle(); //Source should be correct @@ -79,5 +79,95 @@ export default function ({ getPageObjects, getService }) { 'fill-opacity': 0.75, }); }); + + it('should render with mvt-source (style meta from local - count)', async () => { + await PageObjects.maps.loadSavedMap('MVT geotile grid (style meta from local - count)'); + const mapboxStyle = await PageObjects.maps.getMapboxStyle(); + + 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', '_count'], null], + 0, + ['max', ['min', ['to-number', ['get', '_count']], 10], 1], + ], + 0, + ], + 0, + 'rgba(0,0,0,0)', + 1, + '#ecf1f7', + 2.125, + '#d9e3ef', + 3.25, + '#c5d5e7', + 4.375, + '#b2c7df', + 5.5, + '#9eb9d8', + 6.625, + '#8bacd0', + 7.75, + '#769fc8', + 8.875, + '#6092c0', + ], + 'fill-opacity': 0.75, + }); + }); + + it('should render with mvt-source (style meta from local - metric)', async () => { + await PageObjects.maps.loadSavedMap('MVT geotile grid (style meta from local - metric)'); + const mapboxStyle = await PageObjects.maps.getMapboxStyle(); + + 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', 'sum_of_bytes.value'], null], + -1, + ['max', ['min', ['to-number', ['get', 'sum_of_bytes.value']], 14941], 0], + ], + -1, + ], + -1, + 'rgba(0,0,0,0)', + 0, + '#ecf1f7', + 1867.625, + '#d9e3ef', + 3735.25, + '#c5d5e7', + 5602.875, + '#b2c7df', + 7470.5, + '#9eb9d8', + 9338.125, + '#8bacd0', + 11205.75, + '#769fc8', + 13073.375, + '#6092c0', + ], + 'fill-opacity': 0.75, + }); + }); }); } diff --git a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js index 72a6ff8e1af23..931afc83e8415 100644 --- a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js +++ b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js @@ -15,7 +15,8 @@ export default function ({ getService, getPageObjects }) { const pipelinesList = getService('monitoringLogstashPipelines'); const lsClusterSummaryStatus = getService('monitoringLogstashSummaryStatus'); - describe('Logstash pipelines', () => { + // FLAKY: https://github.com/elastic/kibana/issues/116070 + describe.skip('Logstash pipelines', () => { const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); before(async () => { diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts index 7bfae9ba36be4..d089ab47c0cf7 100644 --- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts +++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts @@ -214,7 +214,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows visualize navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Visualize Library']); + expect(navLinks).to.eql(['Visualize Library']); }); it(`landing page shows "Create new Visualization" button`, async () => { @@ -329,7 +329,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows visualize navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Visualize Library']); + expect(navLinks).to.eql(['Visualize Library']); }); it(`landing page shows "Create new Visualization" button`, async () => { diff --git a/x-pack/test/functional/fixtures/kbn_archiver/maps.json b/x-pack/test/functional/fixtures/kbn_archiver/maps.json index 78e49997d5c9e..94ab038ae973b 100644 --- a/x-pack/test/functional/fixtures/kbn_archiver/maps.json +++ b/x-pack/test/functional/fixtures/kbn_archiver/maps.json @@ -725,7 +725,7 @@ "description": "", "layerListJSON": "[{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\":\"SUPER_FINE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}],\"indexPatternRefName\":\"layer_0_source_index_pattern\",\"applyGlobalQuery\":true},\"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},\"settings\":{\"autoFitToDataBounds\":false}}", - "title": "geo grid vector grid example SUPER_FINE resolution", + "title": "MVT geotile grid (style meta from ES)", "uiStateJSON": "{\"isDarkMode\":false}" }, "coreMigrationVersion": "8.0.0", @@ -744,6 +744,56 @@ "version": "WzU1LDJd" } +{ + "attributes": { + "description":"", + "layerListJSON":"[{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\":\"SUPER_FINE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}],\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_0_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\",\"type\":\"ORDINAL\"}},\"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}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"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-21T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}", + "title":"MVT geotile grid (style meta from local - count)", + "uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[\"g1xkv\"]}" + }, + "coreMigrationVersion":"8.1.0", + "id":"943443a0-3b48-11ec-8a0d-af01166a5cc3", + "migrationVersion": { + "map":"8.0.0" + }, + "references": [ + { + "id":"c698b940-e149-11e8-a35a-370a8516603a", + "name":"layer_0_source_index_pattern", + "type":"index-pattern" + } + ], + "type":"map", + "updated_at":"2021-11-01T19:20:50.287Z", + "version":"WzkwLDFd" +} + +{ + "attributes": { + "description":"", + "layerListJSON":"[{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\":\"SUPER_FINE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"sum\",\"field\":\"bytes\"}],\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_0_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"origin\":\"source\",\"name\":\"sum_of_bytes\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false}}},\"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}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"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-20T04:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}", + "title":"MVT geotile grid (style meta from local - metric)", + "uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[\"g1xkv\"]}" + }, + "coreMigrationVersion":"8.1.0", + "id":"9ff6f170-3b56-11ec-9cfb-57b0ede90800", + "migrationVersion": { + "map":"8.0.0" + }, + "references": [ + { + "id":"c698b940-e149-11e8-a35a-370a8516603a", + "name":"layer_0_source_index_pattern", + "type":"index-pattern" + } + ], + "type":"map", + "updated_at":"2021-11-01T21:01:40.951Z", + "version":"WzkyLDFd" +} + { "attributes": { "description": "", diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index f47d17039b5ae..7e29b94c85fa3 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -16,7 +16,7 @@ const DATE_WITH_DATA = { }; const ALERTS_FLYOUT_SELECTOR = 'alertsFlyout'; -const COPY_TO_CLIPBOARD_BUTTON_SELECTOR = 'copy-to-clipboard'; +const FILTER_FOR_VALUE_BUTTON_SELECTOR = 'filter-for-value'; const ALERTS_TABLE_CONTAINER_SELECTOR = 'events-viewer-panel'; const ACTION_COLUMN_INDEX = 1; @@ -149,16 +149,12 @@ export function ObservabilityAlertsCommonProvider({ // Cell actions - const copyToClipboardButtonExists = async () => { - return await testSubjects.exists(COPY_TO_CLIPBOARD_BUTTON_SELECTOR); - }; - - const getCopyToClipboardButton = async () => { - return await testSubjects.find(COPY_TO_CLIPBOARD_BUTTON_SELECTOR); + const filterForValueButtonExists = async () => { + return await testSubjects.exists(FILTER_FOR_VALUE_BUTTON_SELECTOR); }; const getFilterForValueButton = async () => { - return await testSubjects.find('filter-for-value'); + return await testSubjects.find(FILTER_FOR_VALUE_BUTTON_SELECTOR); }; const openActionsMenuForRow = async (rowIndex: number) => { @@ -216,15 +212,14 @@ export function ObservabilityAlertsCommonProvider({ getQueryBar, clearQueryBar, closeAlertsFlyout, + filterForValueButtonExists, getAlertsFlyout, getAlertsFlyoutDescriptionListDescriptions, getAlertsFlyoutDescriptionListTitles, getAlertsFlyoutOrFail, getAlertsFlyoutTitle, getAlertsFlyoutViewInAppButtonOrFail, - getCopyToClipboardButton, getFilterForValueButton, - copyToClipboardButtonExists, getNoDataPageOrFail, getNoDataStateOrFail, getTableCells, diff --git a/x-pack/test/lists_api_integration/utils.ts b/x-pack/test/lists_api_integration/utils.ts index eda32c7fe9fb8..8a2a7a8ca65ff 100644 --- a/x-pack/test/lists_api_integration/utils.ts +++ b/x-pack/test/lists_api_integration/utils.ts @@ -116,20 +116,25 @@ export const removeExceptionListServerGeneratedProperties = ( export const waitFor = async ( functionToTest: () => Promise, functionName: string, - maxTimeout: number = 5000, - timeoutWait: number = 10 + maxTimeout: number = 800000, + timeoutWait: number = 250 ) => { await new Promise(async (resolve, reject) => { try { let found = false; let numberOfTries = 0; + const maxTries = Math.floor(maxTimeout / timeoutWait); - while (!found && numberOfTries < Math.floor(maxTimeout / timeoutWait)) { + while (!found && numberOfTries < maxTries) { const itPasses = await functionToTest(); if (itPasses) { found = true; } else { + // eslint-disable-next-line no-console + console.log( + `Try number ${numberOfTries} out of ${maxTries} for function ${functionName}` + ); numberOfTries++; } @@ -219,7 +224,7 @@ export const importFile = async ( if (response.status !== 200) { // eslint-disable-next-line no-console console.log( - `Did not get an expected 200 "ok" When importing a file. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + `Did not get an expected 200 "ok" When importing a file (importFile). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( response.body )}, status: ${JSON.stringify(response.status)}` ); @@ -246,12 +251,20 @@ export const importTextFile = async ( contents: string[], fileName: string ): Promise => { - await supertest + const response = await supertest .post(`${LIST_ITEM_URL}/_import?type=${type}`) .set('kbn-xsrf', 'true') .attach('file', getImportListItemAsBuffer(contents), fileName) - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(200); + .expect('Content-Type', 'application/json; charset=utf-8'); + + if (response.status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when importing a text file (importTextFile). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( + response.body + )}, status: ${JSON.stringify(response.status)}` + ); + } // although we have pushed the list and its items, it is async so we // have to wait for the contents before continuing @@ -271,10 +284,17 @@ export const waitForListItem = async ( fileName: string ): Promise => { await waitFor(async () => { - const { status } = await supertest + const { status, body } = await supertest .get(`${LIST_ITEM_URL}?list_id=${fileName}&value=${itemValue}`) .send(); - + if (status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when waiting for a list item (waitForListItem) yet. Retrying until we get a 200 "ok". body: ${JSON.stringify( + body + )}, status: ${JSON.stringify(status)}` + ); + } return status === 200; }, `waitForListItem fileName: "${fileName}" itemValue: "${itemValue}"`); }; @@ -310,9 +330,17 @@ export const waitForTextListItem = async ( await waitFor(async () => { const promises = await Promise.all( tokens.map(async (token) => { - const { status } = await supertest + const { status, body } = await supertest .get(`${LIST_ITEM_URL}?list_id=${fileName}&value=${token}`) .send(); + if (status !== 200) { + // eslint-disable-next-line no-console + console.log( + `Did not get an expected 200 "ok" when waiting for a text list item (waitForTextListItem) yet. Retrying until we get a 200 "ok". body: ${JSON.stringify( + body + )}, status: ${JSON.stringify(status)}` + ); + } return status === 200; }) ); diff --git a/x-pack/test/observability_functional/apps/observability/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/alerts/index.ts index 112c24f7c3a88..216a9736fbe87 100644 --- a/x-pack/test/observability_functional/apps/observability/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/alerts/index.ts @@ -189,19 +189,15 @@ export default ({ getService }: FtrProviderContext) => { await alertStatusCell.moveMouseTo(); await retry.waitFor( 'cell actions visible', - async () => await observability.alerts.common.copyToClipboardButtonExists() + async () => await observability.alerts.common.filterForValueButtonExists() ); }); }); afterEach(async () => { await observability.alerts.common.clearQueryBar(); - }); - - it('Copy button works', async () => { - // NOTE: We don't have access to the clipboard in a headless environment, - // so we'll just check the button is clickable in the functional tests. - await (await observability.alerts.common.getCopyToClipboardButton()).click(); + // Reset the query bar by hiding the dropdown + await observability.alerts.common.submitQuery(''); }); it('Filter for value works', async () => { diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts b/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts index d1dc091992dd6..6a2139a70dde5 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts @@ -24,6 +24,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/reporting/logs'); await esArchiver.load('x-pack/test/functional/es_archives/logstash_functional'); + await reportingAPI.migrateReportingIndices(); // ensure that the ILM policy exists for the first test }); after(async () => { diff --git a/x-pack/test/security_solution_cypress/runner.ts b/x-pack/test/security_solution_cypress/runner.ts index 4283b85af0c17..a111c327b1ac6 100644 --- a/x-pack/test/security_solution_cypress/runner.ts +++ b/x-pack/test/security_solution_cypress/runner.ts @@ -117,7 +117,6 @@ export async function SecuritySolutionCypressUpgradeCliTestRunner({ getService, }: FtrProviderContext) { const log = getService('log'); - const config = getService('config'); await withProcRunner(log, async (procs) => { await procs.run('cypress', { @@ -126,10 +125,10 @@ export async function SecuritySolutionCypressUpgradeCliTestRunner({ cwd: resolve(__dirname, '../../plugins/security_solution'), env: { FORCE_COLOR: '1', - CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')), - CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), - CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'), - CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'), + CYPRESS_BASE_URL: process.env.TEST_KIBANA_URL, + CYPRESS_ELASTICSEARCH_URL: process.env.TEST_ES_URL, + CYPRESS_ELASTICSEARCH_USERNAME: process.env.TEST_ES_USER, + CYPRESS_ELASTICSEARCH_PASSWORD: process.env.TEST_ES_PASS, ...process.env, }, wait: true,