diff --git a/docs/apm/api.asciidoc b/docs/apm/api.asciidoc index 54159b642dd1..2fbeea0534fc 100644 --- a/docs/apm/api.asciidoc +++ b/docs/apm/api.asciidoc @@ -355,6 +355,7 @@ allowing you to easily see how these events are impacting the performance of you By default, annotations are stored in a newly created `observability-annotations` index. The name of this index can be changed in your `config.yml` by editing `xpack.observability.annotations.index`. +If you change the default index name, you'll also need to <> accordingly. The following APIs are available: diff --git a/docs/apm/apm-app-users.asciidoc b/docs/apm/apm-app-users.asciidoc index 442a07d27972..d766c866f87e 100644 --- a/docs/apm/apm-app-users.asciidoc +++ b/docs/apm/apm-app-users.asciidoc @@ -4,7 +4,7 @@ :beat_default_index_prefix: apm :beat_kib_app: APM app -:annotation_index: `observability-annotations` +:annotation_index: observability-annotations ++++ Users and privileges @@ -102,6 +102,54 @@ Here are two examples: *********************************** *********************************** //// +[role="xpack"] +[[apm-app-annotation-user-create]] +=== APM app annotation user + +++++ +Create an annotation user +++++ + +NOTE: By default, the `apm_user` built-in role provides access to Observability annotations. +You only need to create an annotation user if the default annotation index +defined in <> has been customized. + +[[apm-app-annotation-user]] +==== Annotation user + +View deployment annotations in the APM app. + +. Create a new role, named something like `annotation_user`, +and assign the following privileges: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +|Index +|`read` on +\{ANNOTATION_INDEX\}+^1^ +|Read-only access to the observability annotation index + +|Index +|`view_index_metadata` on +\{ANNOTATION_INDEX\}+^1^ +|Read-only access to observability annotation index metadata +|==== ++ +^1^ +\{ANNOTATION_INDEX\}+ should be the index name you've defined in +<>. + +. Assign the `annotation_user` created previously, and the built-in roles necessary to create +a <> or <> APM reader to any users that need to view annotations in the APM app + +[[apm-app-annotation-api]] +==== Annotation API + +See <>. + +//// +*********************************** *********************************** +//// + [role="xpack"] [[apm-app-central-config-user]] === APM app central config user diff --git a/package.json b/package.json index 8e51f9207eaf..2f6b643b0260 100644 --- a/package.json +++ b/package.json @@ -455,9 +455,10 @@ "is-path-inside": "^2.1.0", "istanbul-instrumenter-loader": "3.0.1", "jest": "^25.5.4", - "jest-environment-jsdom-thirteen": "^1.0.1", + "jest-canvas-mock": "^2.2.0", "jest-circus": "^25.5.4", "jest-cli": "^25.5.4", + "jest-environment-jsdom-thirteen": "^1.0.1", "jest-raw-loader": "^1.0.1", "jimp": "^0.9.6", "json5": "^1.0.1", diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index 1466865df8d9..211cfac3806a 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -1,5 +1,71 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`builds expected bundles, saves bundle counts to metadata: OptimizerConfig 1`] = ` +OptimizerConfig { + "bundles": Array [ + Bundle { + "cache": BundleCache { + "path": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/target/public/.kbn-optimizer-cache, + "state": undefined, + }, + "contextDir": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar, + "id": "bar", + "outputDir": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/target/public, + "publicDirNames": Array [ + "public", + ], + "sourceRoot": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo, + "type": "plugin", + }, + Bundle { + "cache": BundleCache { + "path": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/target/public/.kbn-optimizer-cache, + "state": undefined, + }, + "contextDir": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo, + "id": "foo", + "outputDir": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/target/public, + "publicDirNames": Array [ + "public", + ], + "sourceRoot": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo, + "type": "plugin", + }, + ], + "cache": true, + "dist": false, + "inspectWorkers": false, + "maxWorkerCount": 1, + "plugins": Array [ + Object { + "directory": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar, + "extraPublicDirs": Array [], + "id": "bar", + "isUiPlugin": true, + }, + Object { + "directory": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo, + "extraPublicDirs": Array [], + "id": "foo", + "isUiPlugin": true, + }, + Object { + "directory": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/nested/baz, + "extraPublicDirs": Array [], + "id": "baz", + "isUiPlugin": false, + }, + ], + "profileWebpack": false, + "repoRoot": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo, + "themeTags": Array [ + "v7dark", + "v7light", + ], + "watch": false, +} +`; + exports[`prepares assets for distribution: bar bundle 1`] = `"(function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{enumerable:true,get:getter})}};__webpack_require__.r=function(exports){if(typeof Symbol!==\\"undefined\\"&&Symbol.toStringTag){Object.defineProperty(exports,Symbol.toStringTag,{value:\\"Module\\"})}Object.defineProperty(exports,\\"__esModule\\",{value:true})};__webpack_require__.t=function(value,mode){if(mode&1)value=__webpack_require__(value);if(mode&8)return value;if(mode&4&&typeof value===\\"object\\"&&value&&value.__esModule)return value;var ns=Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns,\\"default\\",{enumerable:true,value:value});if(mode&2&&typeof value!=\\"string\\")for(var key in value)__webpack_require__.d(ns,key,function(key){return value[key]}.bind(null,key));return ns};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module[\\"default\\"]}:function getModuleExports(){return module};__webpack_require__.d(getter,\\"a\\",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p=\\"\\";return __webpack_require__(__webpack_require__.s=5)})([function(module,exports,__webpack_require__){\\"use strict\\";var isOldIE=function isOldIE(){var memo;return function memorize(){if(typeof memo===\\"undefined\\"){memo=Boolean(window&&document&&document.all&&!window.atob)}return memo}}();var getTarget=function getTarget(){var memo={};return function memorize(target){if(typeof memo[target]===\\"undefined\\"){var styleTarget=document.querySelector(target);if(window.HTMLIFrameElement&&styleTarget instanceof window.HTMLIFrameElement){try{styleTarget=styleTarget.contentDocument.head}catch(e){styleTarget=null}}memo[target]=styleTarget}return memo[target]}}();var stylesInDom=[];function getIndexByIdentifier(identifier){var result=-1;for(var i=0;i { await del(TMP_DIR); }); -// FLAKY: https://github.com/elastic/kibana/issues/70762 -it.skip('builds expected bundles, saves bundle counts to metadata', async () => { +it('builds expected bundles, saves bundle counts to metadata', async () => { const config = OptimizerConfig.create({ repoRoot: MOCK_REPO_DIR, pluginScanDirs: [Path.resolve(MOCK_REPO_DIR, 'plugins')], @@ -75,7 +74,11 @@ it.skip('builds expected bundles, saves bundle counts to metadata', async () => expect(config).toMatchSnapshot('OptimizerConfig'); const msgs = await runOptimizer(config) - .pipe(logOptimizerState(log, config), toArray()) + .pipe( + logOptimizerState(log, config), + filter((x) => x.event?.type !== 'worker stdio'), + toArray() + ) .toPromise(); const assert = (statement: string, truth: boolean, altStates?: OptimizerUpdate[]) => { @@ -168,8 +171,7 @@ it.skip('builds expected bundles, saves bundle counts to metadata', async () => `); }); -// FLAKY: https://github.com/elastic/kibana/issues/70764 -it.skip('uses cache on second run and exist cleanly', async () => { +it('uses cache on second run and exist cleanly', async () => { const config = OptimizerConfig.create({ repoRoot: MOCK_REPO_DIR, pluginScanDirs: [Path.resolve(MOCK_REPO_DIR, 'plugins')], diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/afterparamchange.png b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/afterparamchange.png deleted file mode 100644 index bc41213edc7b..000000000000 Binary files a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/afterparamchange.png and /dev/null differ diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/afterresize.png b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/afterresize.png deleted file mode 100644 index 3788a57ae242..000000000000 Binary files a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/afterresize.png and /dev/null differ diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/basicdraw.png b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/basicdraw.png deleted file mode 100644 index 3716867865e4..000000000000 Binary files a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/basicdraw.png and /dev/null differ diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/simpleload.png b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/simpleload.png deleted file mode 100644 index 6ea090562d46..000000000000 Binary files a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/simpleload.png and /dev/null differ diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/tag_cloud_visualization.js b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/tag_cloud_visualization.js deleted file mode 100644 index 4a6e9e776521..000000000000 --- a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/tag_cloud_visualization.js +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { ImageComparator } from 'test_utils/image_comparator'; -import basicdrawPng from './basicdraw.png'; -import afterresizePng from './afterresize.png'; -import afterparamChange from './afterparamchange.png'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ExprVis } from '../../../../../../plugins/visualizations/public/expressions/vis'; - -// Replace with mock when converting to jest tests -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { seedColors } from '../../../../../../plugins/charts/public/services/colors/seed_colors'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BaseVisType } from '../../../../../../plugins/visualizations/public/vis_types/base_vis_type'; -// Will be replaced with new path when tests are moved -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { createTagCloudVisTypeDefinition } from '../../../../../../plugins/vis_type_tagcloud/public/tag_cloud_type'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { createTagCloudVisualization } from '../../../../../../plugins/vis_type_tagcloud/public/components/tag_cloud_visualization'; -import { npStart } from 'ui/new_platform'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setFormatService } from '../../../../../../plugins/vis_type_tagcloud/public/services'; - -const THRESHOLD = 0.65; -const PIXEL_DIFF = 64; -describe('TagCloudVisualizationTest', function () { - let domNode; - let vis; - let imageComparator; - - const dummyTableGroup = { - columns: [ - { - id: 'col-0', - title: 'geo.dest: Descending', - }, - { - id: 'col-1', - title: 'Count', - }, - ], - rows: [ - { 'col-0': 'CN', 'col-1': 26 }, - { 'col-0': 'IN', 'col-1': 17 }, - { 'col-0': 'US', 'col-1': 6 }, - { 'col-0': 'DE', 'col-1': 4 }, - { 'col-0': 'BR', 'col-1': 3 }, - ], - }; - const TagCloudVisualization = createTagCloudVisualization({ - colors: { - seedColors, - }, - }); - - before(() => setFormatService(npStart.plugins.data.fieldFormats)); - - beforeEach(ngMock.module('kibana')); - - describe('TagCloudVisualization - basics', function () { - beforeEach(async function () { - const visType = new BaseVisType(createTagCloudVisTypeDefinition({ colors: seedColors })); - setupDOM('512px', '512px'); - imageComparator = new ImageComparator(); - vis = new ExprVis({ - type: visType, - params: { - bucket: { accessor: 0, format: {} }, - metric: { accessor: 0, format: {} }, - }, - data: {}, - }); - }); - - afterEach(function () { - teardownDOM(); - imageComparator.destroy(); - }); - - it('simple draw', async function () { - const tagcloudVisualization = new TagCloudVisualization(domNode, vis); - - await tagcloudVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - const svgNode = domNode.querySelector('svg'); - const mismatchedPixels = await imageComparator.compareDOMContents( - svgNode.outerHTML, - 512, - 512, - basicdrawPng, - THRESHOLD - ); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('with resize', async function () { - const tagcloudVisualization = new TagCloudVisualization(domNode, vis); - await tagcloudVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - domNode.style.width = '256px'; - domNode.style.height = '368px'; - await tagcloudVisualization.render(dummyTableGroup, vis.params, { - resize: true, - params: false, - aggs: false, - data: false, - uiState: false, - }); - - const svgNode = domNode.querySelector('svg'); - const mismatchedPixels = await imageComparator.compareDOMContents( - svgNode.outerHTML, - 256, - 368, - afterresizePng, - THRESHOLD - ); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('with param change', async function () { - const tagcloudVisualization = new TagCloudVisualization(domNode, vis); - await tagcloudVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - domNode.style.width = '256px'; - domNode.style.height = '368px'; - vis.params.orientation = 'right angled'; - vis.params.minFontSize = 70; - await tagcloudVisualization.render(dummyTableGroup, vis.params, { - resize: true, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - const svgNode = domNode.querySelector('svg'); - const mismatchedPixels = await imageComparator.compareDOMContents( - svgNode.outerHTML, - 256, - 368, - afterparamChange, - THRESHOLD - ); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - }); - - function setupDOM(width, height) { - domNode = document.createElement('div'); - domNode.style.top = '0'; - domNode.style.left = '0'; - domNode.style.width = width; - domNode.style.height = height; - domNode.style.position = 'fixed'; - domNode.style.border = '1px solid blue'; - domNode.style['pointer-events'] = 'none'; - document.body.appendChild(domNode); - } - - function teardownDOM() { - domNode.innerHTML = ''; - document.body.removeChild(domNode); - } -}); diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 7bfb14b8bfa1..8df9f08e9c40 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -18,7 +18,7 @@ */ import { keys, last, mapValues, reduce, zipObject } from 'lodash'; -import { Executor } from '../executor'; +import { Executor, ExpressionExecOptions } from '../executor'; import { createExecutionContainer, ExecutionContainer } from './container'; import { createError } from '../util'; import { Defer, now } from '../../../kibana_utils/common'; @@ -31,6 +31,7 @@ import { parse, formatExpression, parseExpression, + ExpressionAstNode, } from '../ast'; import { ExecutionContext, DefaultInspectorAdapters } from './types'; import { getType, ExpressionValue } from '../expression_types'; @@ -382,7 +383,7 @@ export class Execution< const resolveArgFns = mapValues(argAstsWithDefaults, (asts, argName) => { return asts.map((item: ExpressionAstExpression) => { return async (subInput = input) => { - const output = await this.params.executor.interpret(item, subInput, { + const output = await this.interpret(item, subInput, { debug: this.params.debug, }); if (isExpressionValueError(output)) throw output.error; @@ -415,4 +416,28 @@ export class Execution< // function which would be treated as a promise return { resolvedArgs }; } + + public async interpret( + ast: ExpressionAstNode, + input: T, + options?: ExpressionExecOptions + ): Promise { + switch (getType(ast)) { + case 'expression': + const execution = this.params.executor.createExecution( + ast as ExpressionAstExpression, + this.context, + options + ); + execution.start(input); + return await execution.result; + case 'string': + case 'number': + case 'null': + case 'boolean': + return ast; + default: + throw new Error(`Unknown AST object: ${JSON.stringify(ast)}`); + } + } } diff --git a/src/plugins/expressions/common/executor/executor.ts b/src/plugins/expressions/common/executor/executor.ts index 2ecbc5f75a9e..2b5f9f2556d8 100644 --- a/src/plugins/expressions/common/executor/executor.ts +++ b/src/plugins/expressions/common/executor/executor.ts @@ -26,8 +26,7 @@ import { Execution, ExecutionParams } from '../execution/execution'; import { IRegistry } from '../types'; import { ExpressionType } from '../expression_types/expression_type'; import { AnyExpressionTypeDefinition } from '../expression_types/types'; -import { getType } from '../expression_types'; -import { ExpressionAstExpression, ExpressionAstNode } from '../ast'; +import { ExpressionAstExpression } from '../ast'; import { typeSpecs } from '../expression_types/specs'; import { functionSpecs } from '../expression_functions/specs'; @@ -154,34 +153,6 @@ export class Executor = Record( - ast: ExpressionAstNode, - input: T, - options?: ExpressionExecOptions - ): Promise { - switch (getType(ast)) { - case 'expression': - return await this.interpretExpression(ast as ExpressionAstExpression, input, options); - case 'string': - case 'number': - case 'null': - case 'boolean': - return ast; - default: - throw new Error(`Unknown AST object: ${JSON.stringify(ast)}`); - } - } - - public async interpretExpression( - ast: string | ExpressionAstExpression, - input: T, - options?: ExpressionExecOptions - ): Promise { - const execution = this.createExecution(ast, undefined, options); - execution.start(input); - return await execution.result; - } - /** * Execute expression and return result. * diff --git a/src/plugins/vis_type_tagcloud/public/components/__snapshots__/tag_cloud.test.js.snap b/src/plugins/vis_type_tagcloud/public/components/__snapshots__/tag_cloud.test.js.snap new file mode 100644 index 000000000000..e32425a09542 --- /dev/null +++ b/src/plugins/vis_type_tagcloud/public/components/__snapshots__/tag_cloud.test.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`tag cloud tests tagcloudscreenshot should render simple image 1`] = `"foobarfoobar"`; diff --git a/src/plugins/vis_type_tagcloud/public/components/__snapshots__/tag_cloud_visualization.test.js.snap b/src/plugins/vis_type_tagcloud/public/components/__snapshots__/tag_cloud_visualization.test.js.snap new file mode 100644 index 000000000000..dbc3dd1202cb --- /dev/null +++ b/src/plugins/vis_type_tagcloud/public/components/__snapshots__/tag_cloud_visualization.test.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TagCloudVisualizationTest TagCloudVisualization - basics simple draw 1`] = `"CNINUSDEBR"`; + +exports[`TagCloudVisualizationTest TagCloudVisualization - basics with param change 1`] = `"CNINUSDEBR"`; + +exports[`TagCloudVisualizationTest TagCloudVisualization - basics with resize 1`] = `"CNINUSDEBR"`; diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/tag_cloud.js b/src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js similarity index 72% rename from src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/tag_cloud.js rename to src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js index 35c7b77687b9..89a6a67bcb2f 100644 --- a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_tagcloud/tag_cloud.js +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js @@ -17,22 +17,27 @@ * under the License. */ -import expect from '@kbn/expect'; import _ from 'lodash'; import d3 from 'd3'; +import 'jest-canvas-mock'; import { fromNode, delay } from 'bluebird'; -import { ImageComparator } from 'test_utils/image_comparator'; -import simpleloadPng from './simpleload.png'; +import { TagCloud } from './tag_cloud'; +import { setHTMLElementOffset, setSVGElementGetBBox } from '../../../../test_utils/public'; -// Replace with mock when converting to jest tests -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { seedColors } from '../../../../../../plugins/charts/public/services/colors/seed_colors'; -// Will be replaced with new path when tests are moved -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { TagCloud } from '../../../../../../plugins/vis_type_tagcloud/public/components/tag_cloud'; +describe('tag cloud tests', () => { + let SVGElementGetBBoxSpyInstance; + let HTMLElementOffsetMockInstance; + + beforeEach(() => { + setupDOM(); + }); + + afterEach(() => { + SVGElementGetBBoxSpyInstance.mockRestore(); + HTMLElementOffsetMockInstance.mockRestore(); + }); -describe('tag cloud tests', function () { const minValue = 1; const maxValue = 9; const midValue = (minValue + maxValue) / 2; @@ -100,16 +105,15 @@ describe('tag cloud tests', function () { let domNode; let tagCloud; - const colorScale = d3.scale.ordinal().range(seedColors); + const colorScale = d3.scale + .ordinal() + .range(['#00a69b', '#57c17b', '#6f87d8', '#663db8', '#bc52bc', '#9e3533', '#daa05d']); function setupDOM() { domNode = document.createElement('div'); - domNode.style.top = '0'; - domNode.style.left = '0'; - domNode.style.width = '512px'; - domNode.style.height = '512px'; - domNode.style.position = 'fixed'; - domNode.style['pointer-events'] = 'none'; + SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(); + HTMLElementOffsetMockInstance = setHTMLElementOffset(512, 512); + document.body.appendChild(domNode); } @@ -126,42 +130,39 @@ describe('tag cloud tests', function () { sqrtScaleTest, biggerFontTest, trimDataTest, - ].forEach(function (test) { + ].forEach(function (currentTest) { describe(`should position elements correctly for options: ${JSON.stringify( - test.options - )}`, function () { - beforeEach(async function () { - setupDOM(); + currentTest.options + )}`, () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); - tagCloud.setData(test.data); - tagCloud.setOptions(test.options); + tagCloud.setData(currentTest.data); + tagCloud.setOptions(currentTest.options); await fromNode((cb) => tagCloud.once('renderComplete', cb)); }); afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); - it( + test( 'positions should be ok', - handleExpectedBlip(function () { + handleExpectedBlip(() => { const textElements = domNode.querySelectorAll('text'); - verifyTagProperties(test.expected, textElements, tagCloud); + verifyTagProperties(currentTest.expected, textElements, tagCloud); }) ); }); }); - [5, 100, 200, 300, 500].forEach(function (timeout) { - describe(`should only send single renderComplete event at the very end, using ${timeout}ms timeout`, function () { - beforeEach(async function () { - setupDOM(); - + [5, 100, 200, 300, 500].forEach((timeout) => { + describe(`should only send single renderComplete event at the very end, using ${timeout}ms timeout`, () => { + beforeEach(async () => { //TagCloud takes at least 600ms to complete (due to d3 animation) //renderComplete should only notify at the last one tagCloud = new TagCloud(domNode, colorScale); @@ -176,16 +177,16 @@ describe('tag cloud tests', function () { afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); - it( + test( 'positions should be ok', - handleExpectedBlip(function () { + handleExpectedBlip(() => { const textElements = domNode.querySelectorAll('text'); verifyTagProperties(logScaleTest.expected, textElements, tagCloud); }) @@ -193,9 +194,8 @@ describe('tag cloud tests', function () { }); }); - describe('should use the latest state before notifying (when modifying options multiple times)', function () { - beforeEach(async function () { - setupDOM(); + describe('should use the latest state before notifying (when modifying options multiple times)', () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); tagCloud.setOptions(baseTest.options); @@ -205,53 +205,53 @@ describe('tag cloud tests', function () { afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); - it( + test( 'positions should be ok', - handleExpectedBlip(function () { + handleExpectedBlip(() => { const textElements = domNode.querySelectorAll('text'); verifyTagProperties(logScaleTest.expected, textElements, tagCloud); }) ); }); - describe('should use the latest state before notifying (when modifying data multiple times)', function () { - beforeEach(async function () { - setupDOM(); + describe('should use the latest state before notifying (when modifying data multiple times)', () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); tagCloud.setOptions(baseTest.options); tagCloud.setData(trimDataTest.data); + await fromNode((cb) => tagCloud.once('renderComplete', cb)); }); afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); - it( + test( 'positions should be ok', - handleExpectedBlip(function () { + handleExpectedBlip(() => { const textElements = domNode.querySelectorAll('text'); verifyTagProperties(trimDataTest.expected, textElements, tagCloud); }) ); }); - describe('should not get multiple render-events', function () { + describe('should not get multiple render-events', () => { let counter; - beforeEach(function () { + beforeEach(() => { counter = 0; - setupDOM(); + return new Promise((resolve, reject) => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); @@ -281,31 +281,32 @@ describe('tag cloud tests', function () { afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); - it( + test( 'positions should be ok', - handleExpectedBlip(function () { + handleExpectedBlip(() => { const textElements = domNode.querySelectorAll('text'); verifyTagProperties(logScaleTest.expected, textElements, tagCloud); }) ); }); - describe('should show correct data when state-updates are interleaved with resize event', function () { - beforeEach(async function () { - setupDOM(); + describe('should show correct data when state-updates are interleaved with resize event', () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(logScaleTest.data); tagCloud.setOptions(logScaleTest.options); await delay(1000); //let layout run - domNode.style.width = '600px'; - domNode.style.height = '600px'; + + SVGElementGetBBoxSpyInstance.mockRestore(); + SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(600, 600); + tagCloud.resize(); //triggers new layout setTimeout(() => { //change the options at the very end too @@ -317,26 +318,23 @@ describe('tag cloud tests', function () { afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); - it( + test( 'positions should be ok', - handleExpectedBlip(function () { + handleExpectedBlip(() => { const textElements = domNode.querySelectorAll('text'); verifyTagProperties(baseTest.expected, textElements, tagCloud); }) ); }); - describe(`should not put elements in view when container is too small`, function () { - beforeEach(async function () { - setupDOM(); - domNode.style.width = '1px'; - domNode.style.height = '1px'; + describe(`should not put elements in view when container is too small`, () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); tagCloud.setOptions(baseTest.options); @@ -345,10 +343,10 @@ describe('tag cloud tests', function () { afterEach(teardownDOM); - it('completeness should not be ok', function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.INCOMPLETE); + test('completeness should not be ok', () => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.INCOMPLETE); }); - it('positions should not be ok', function () { + test('positions should not be ok', () => { const textElements = domNode.querySelectorAll('text'); for (let i = 0; i < textElements; i++) { const bbox = textElements[i].getBoundingClientRect(); @@ -357,96 +355,73 @@ describe('tag cloud tests', function () { }); }); - describe(`tags should fit after making container bigger`, function () { - beforeEach(async function () { - setupDOM(); - domNode.style.width = '1px'; - domNode.style.height = '1px'; - + describe(`tags should fit after making container bigger`, () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); tagCloud.setOptions(baseTest.options); await fromNode((cb) => tagCloud.once('renderComplete', cb)); //make bigger - domNode.style.width = '512px'; - domNode.style.height = '512px'; + tagCloud._size = [600, 600]; tagCloud.resize(); await fromNode((cb) => tagCloud.once('renderComplete', cb)); }); afterEach(teardownDOM); - it( + test( 'completeness should be ok', - handleExpectedBlip(function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.COMPLETE); + handleExpectedBlip(() => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.COMPLETE); }) ); }); - describe(`tags should no longer fit after making container smaller`, function () { - beforeEach(async function () { - setupDOM(); + describe(`tags should no longer fit after making container smaller`, () => { + beforeEach(async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); tagCloud.setOptions(baseTest.options); await fromNode((cb) => tagCloud.once('renderComplete', cb)); //make smaller - domNode.style.width = '1px'; - domNode.style.height = '1px'; + tagCloud._size = []; tagCloud.resize(); await fromNode((cb) => tagCloud.once('renderComplete', cb)); }); afterEach(teardownDOM); - it('completeness should not be ok', function () { - expect(tagCloud.getStatus()).to.equal(TagCloud.STATUS.INCOMPLETE); + test('completeness should not be ok', () => { + expect(tagCloud.getStatus()).toEqual(TagCloud.STATUS.INCOMPLETE); }); }); - describe('tagcloudscreenshot', function () { - let imageComparator; - beforeEach(async function () { - setupDOM(); - imageComparator = new ImageComparator(); - }); + describe('tagcloudscreenshot', () => { + afterEach(teardownDOM); - afterEach(() => { - imageComparator.destroy(); - teardownDOM(); - }); - - it('should render simple image', async function () { + test('should render simple image', async () => { tagCloud = new TagCloud(domNode, colorScale); tagCloud.setData(baseTest.data); tagCloud.setOptions(baseTest.options); await fromNode((cb) => tagCloud.once('renderComplete', cb)); - const mismatchedPixels = await imageComparator.compareDOMContents( - domNode.innerHTML, - 512, - 512, - simpleloadPng, - 0.5 - ); - expect(mismatchedPixels).to.be.lessThan(64); + expect(domNode.innerHTML).toMatchSnapshot(); }); }); function verifyTagProperties(expectedValues, actualElements, tagCloud) { - expect(actualElements.length).to.equal(expectedValues.length); + expect(actualElements.length).toEqual(expectedValues.length); expectedValues.forEach((test, index) => { try { - expect(actualElements[index].style.fontSize).to.equal(test.fontSize); + expect(actualElements[index].style.fontSize).toEqual(test.fontSize); } catch (e) { throw new Error('fontsize is not correct: ' + e.message); } try { - expect(actualElements[index].innerHTML).to.equal(test.text); + expect(actualElements[index].innerHTML).toEqual(test.text); } catch (e) { throw new Error('fontsize is not correct: ' + e.message); } @@ -470,14 +445,14 @@ describe('tag cloud tests', function () { debugInfo: ${JSON.stringify(tagCloud.getDebugInfo())}`; try { - expect(bbox.top >= 0 && bbox.top <= domNode.offsetHeight).to.be(shouldBeInside); + expect(bbox.top >= 0 && bbox.top <= domNode.offsetHeight).toBe(shouldBeInside); } catch (e) { throw new Error( 'top boundary of tag should have been ' + (shouldBeInside ? 'inside' : 'outside') + message ); } try { - expect(bbox.bottom >= 0 && bbox.bottom <= domNode.offsetHeight).to.be(shouldBeInside); + expect(bbox.bottom >= 0 && bbox.bottom <= domNode.offsetHeight).toBe(shouldBeInside); } catch (e) { throw new Error( 'bottom boundary of tag should have been ' + @@ -486,14 +461,14 @@ describe('tag cloud tests', function () { ); } try { - expect(bbox.left >= 0 && bbox.left <= domNode.offsetWidth).to.be(shouldBeInside); + expect(bbox.left >= 0 && bbox.left <= domNode.offsetWidth).toBe(shouldBeInside); } catch (e) { throw new Error( 'left boundary of tag should have been ' + (shouldBeInside ? 'inside' : 'outside') + message ); } try { - expect(bbox.right >= 0 && bbox.right <= domNode.offsetWidth).to.be(shouldBeInside); + expect(bbox.right >= 0 && bbox.right <= domNode.offsetWidth).toBe(shouldBeInside); } catch (e) { throw new Error( 'right boundary of tag should have been ' + @@ -532,7 +507,7 @@ describe('tag cloud tests', function () { } function handleExpectedBlip(assertion) { - return function () { + return () => { if (!shouldAssert()) { return; } diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.test.js b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.test.js new file mode 100644 index 000000000000..7f96066c1607 --- /dev/null +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.test.js @@ -0,0 +1,176 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import 'jest-canvas-mock'; + +import { createTagCloudVisTypeDefinition } from '../tag_cloud_type'; +import { createTagCloudVisualization } from './tag_cloud_visualization'; +import { setFormatService } from '../services'; +import { dataPluginMock } from '../../../data/public/mocks'; +import { setHTMLElementOffset, setSVGElementGetBBox } from '../../../../test_utils/public'; + +const seedColors = ['#00a69b', '#57c17b', '#6f87d8', '#663db8', '#bc52bc', '#9e3533', '#daa05d']; + +describe('TagCloudVisualizationTest', () => { + let domNode; + let vis; + let SVGElementGetBBoxSpyInstance; + let HTMLElementOffsetMockInstance; + + const dummyTableGroup = { + columns: [ + { + id: 'col-0', + title: 'geo.dest: Descending', + }, + { + id: 'col-1', + title: 'Count', + }, + ], + rows: [ + { 'col-0': 'CN', 'col-1': 26 }, + { 'col-0': 'IN', 'col-1': 17 }, + { 'col-0': 'US', 'col-1': 6 }, + { 'col-0': 'DE', 'col-1': 4 }, + { 'col-0': 'BR', 'col-1': 3 }, + ], + }; + const TagCloudVisualization = createTagCloudVisualization({ + colors: { + seedColors, + }, + }); + + const originTransformSVGElement = window.SVGElement.prototype.transform; + + beforeAll(() => { + setFormatService(dataPluginMock.createStartContract().fieldFormats); + Object.defineProperties(window.SVGElement.prototype, { + transform: { + get: () => ({ + baseVal: { + consolidate: () => {}, + }, + }), + configurable: true, + }, + }); + }); + + afterAll(() => { + SVGElementGetBBoxSpyInstance.mockRestore(); + HTMLElementOffsetMockInstance.mockRestore(); + window.SVGElement.prototype.transform = originTransformSVGElement; + }); + + describe('TagCloudVisualization - basics', () => { + beforeEach(async () => { + const visType = createTagCloudVisTypeDefinition({ colors: seedColors }); + setupDOM(512, 512); + + vis = { + type: visType, + params: { + bucket: { accessor: 0, format: {} }, + metric: { accessor: 0, format: {} }, + scale: 'linear', + orientation: 'single', + }, + data: {}, + }; + }); + + test('simple draw', async () => { + const tagcloudVisualization = new TagCloudVisualization(domNode, vis); + + await tagcloudVisualization.render(dummyTableGroup, vis.params, { + resize: false, + params: true, + aggs: true, + data: true, + uiState: false, + }); + + const svgNode = domNode.querySelector('svg'); + expect(svgNode.outerHTML).toMatchSnapshot(); + }); + + test('with resize', async () => { + const tagcloudVisualization = new TagCloudVisualization(domNode, vis); + await tagcloudVisualization.render(dummyTableGroup, vis.params, { + resize: false, + params: true, + aggs: true, + data: true, + uiState: false, + }); + + domNode.style.width = '256px'; + domNode.style.height = '368px'; + await tagcloudVisualization.render(dummyTableGroup, vis.params, { + resize: true, + params: false, + aggs: false, + data: false, + uiState: false, + }); + + const svgNode = domNode.querySelector('svg'); + expect(svgNode.outerHTML).toMatchSnapshot(); + }); + + test('with param change', async function () { + const tagcloudVisualization = new TagCloudVisualization(domNode, vis); + await tagcloudVisualization.render(dummyTableGroup, vis.params, { + resize: false, + params: true, + aggs: true, + data: true, + uiState: false, + }); + + SVGElementGetBBoxSpyInstance.mockRestore(); + SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(256, 368); + + HTMLElementOffsetMockInstance.mockRestore(); + HTMLElementOffsetMockInstance = setHTMLElementOffset(256, 386); + + vis.params.orientation = 'right angled'; + vis.params.minFontSize = 70; + await tagcloudVisualization.render(dummyTableGroup, vis.params, { + resize: true, + params: true, + aggs: false, + data: false, + uiState: false, + }); + + const svgNode = domNode.querySelector('svg'); + expect(svgNode.outerHTML).toMatchSnapshot(); + }); + }); + + function setupDOM(width, height) { + domNode = document.createElement('div'); + + HTMLElementOffsetMockInstance = setHTMLElementOffset(width, height); + SVGElementGetBBoxSpyInstance = setSVGElementGetBBox(width, height); + } +}); diff --git a/src/test_utils/public/helpers/index.ts b/src/test_utils/public/helpers/index.ts index 79dc29e83bc3..c8447743ee28 100644 --- a/src/test_utils/public/helpers/index.ts +++ b/src/test_utils/public/helpers/index.ts @@ -24,3 +24,5 @@ export { WithStore } from './redux_helpers'; export { WithMemoryRouter, WithRoute, reactRouterMock } from './router_helpers'; export * from './utils'; + +export { setSVGElementGetBBox, setHTMLElementOffset } from './jsdom_svg_mocks'; diff --git a/src/test_utils/public/helpers/jsdom_svg_mocks.ts b/src/test_utils/public/helpers/jsdom_svg_mocks.ts new file mode 100644 index 000000000000..dbc8266f663f --- /dev/null +++ b/src/test_utils/public/helpers/jsdom_svg_mocks.ts @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const setSVGElementGetBBox = ( + width: number, + height: number, + x: number = 0, + y: number = 0 +) => { + const SVGElementPrototype = SVGElement.prototype as any; + const originalGetBBox = SVGElementPrototype.getBBox; + + // getBBox is not in the SVGElement.prototype object by default, so we cannot use jest.spyOn for that case + SVGElementPrototype.getBBox = jest.fn(() => ({ + x, + y, + width, + height, + })); + + return { + mockRestore: () => { + SVGElementPrototype.getBBox = originalGetBBox; + }, + }; +}; + +export const setHTMLElementOffset = (width: number, height: number) => { + const offsetWidthSpy = jest.spyOn(window.HTMLElement.prototype, 'offsetWidth', 'get'); + offsetWidthSpy.mockReturnValue(width); + + const offsetHeightSpy = jest.spyOn(window.HTMLElement.prototype, 'offsetHeight', 'get'); + offsetHeightSpy.mockReturnValue(height); + + return { + mockRestore: () => { + offsetWidthSpy.mockRestore(); + offsetHeightSpy.mockRestore(); + }, + }; +}; diff --git a/src/test_utils/public/index.ts b/src/test_utils/public/index.ts new file mode 100644 index 000000000000..4f46dfe1578d --- /dev/null +++ b/src/test_utils/public/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { setSVGElementGetBBox, setHTMLElementOffset } from './helpers'; diff --git a/x-pack/index.js b/x-pack/index.js index 2d2e42650cfa..66fe05e8f035 100644 --- a/x-pack/index.js +++ b/x-pack/index.js @@ -9,15 +9,7 @@ import { monitoring } from './legacy/plugins/monitoring'; import { security } from './legacy/plugins/security'; import { beats } from './legacy/plugins/beats_management'; import { spaces } from './legacy/plugins/spaces'; -import { ingestManager } from './legacy/plugins/ingest_manager'; module.exports = function (kibana) { - return [ - xpackMain(kibana), - monitoring(kibana), - spaces(kibana), - security(kibana), - ingestManager(kibana), - beats(kibana), - ]; + return [xpackMain(kibana), monitoring(kibana), spaces(kibana), security(kibana), beats(kibana)]; }; diff --git a/x-pack/legacy/plugins/ingest_manager/index.ts b/x-pack/legacy/plugins/ingest_manager/index.ts deleted file mode 100644 index 2b20bf16f240..000000000000 --- a/x-pack/legacy/plugins/ingest_manager/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { resolve } from 'path'; - -export function ingestManager(kibana: any) { - return new kibana.Plugin({ - id: 'ingestManager', - require: ['kibana', 'elasticsearch', 'xpack_main'], - publicDir: resolve(__dirname, '../../../plugins/ingest_manager/public'), - }); -} diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts index 7231f01671e0..74a9061b5df2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts @@ -52,8 +52,12 @@ export function dropdownControl(): ExpressionFunctionDefinition< fn: (input, { valueColumn, filterColumn, filterGroup }) => { let choices = []; - if (input.rows[0][valueColumn]) { - choices = uniq(input.rows.map((row) => row[valueColumn])).sort(); + const filteredRows = input.rows.filter( + (row) => row[valueColumn] !== null && row[valueColumn] !== undefined + ); + + if (filteredRows.length > 0) { + choices = uniq(filteredRows.map((row) => row[valueColumn])).sort(); } const column = filterColumn || valueColumn; diff --git a/x-pack/plugins/infra/public/components/source_configuration/add_log_column_popover.tsx b/x-pack/plugins/infra/public/components/source_configuration/add_log_column_popover.tsx deleted file mode 100644 index 9f55126a1440..000000000000 --- a/x-pack/plugins/infra/public/components/source_configuration/add_log_column_popover.tsx +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiBadge, EuiButton, EuiPopover, EuiPopoverTitle, EuiSelectable } from '@elastic/eui'; -import { EuiSelectableOption } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React, { useCallback, useMemo } from 'react'; -import { v4 as uuidv4 } from 'uuid'; - -import { LogColumnConfiguration } from '../../utils/source_configuration'; -import { useVisibilityState } from '../../utils/use_visibility_state'; -import { euiStyled } from '../../../../observability/public'; - -interface SelectableColumnOption { - optionProps: EuiSelectableOption; - columnConfiguration: LogColumnConfiguration; -} - -export const AddLogColumnButtonAndPopover: React.FunctionComponent<{ - addLogColumn: (logColumnConfiguration: LogColumnConfiguration) => void; - availableFields: string[]; - isDisabled?: boolean; -}> = ({ addLogColumn, availableFields, isDisabled }) => { - const { isVisible: isOpen, show: openPopover, hide: closePopover } = useVisibilityState(false); - - const availableColumnOptions = useMemo( - () => [ - { - optionProps: { - append: , - 'data-test-subj': 'addTimestampLogColumn', - // this key works around EuiSelectable using a lowercased label as - // key, which leads to conflicts with field names - key: 'timestamp', - label: 'Timestamp', - }, - columnConfiguration: { - timestampColumn: { - id: uuidv4(), - }, - }, - }, - { - optionProps: { - 'data-test-subj': 'addMessageLogColumn', - append: , - // this key works around EuiSelectable using a lowercased label as - // key, which leads to conflicts with field names - key: 'message', - label: 'Message', - }, - columnConfiguration: { - messageColumn: { - id: uuidv4(), - }, - }, - }, - ...availableFields.map((field) => ({ - optionProps: { - 'data-test-subj': `addFieldLogColumn addFieldLogColumn:${field}`, - // this key works around EuiSelectable using a lowercased label as - // key, which leads to conflicts with fields that only differ in the - // case (e.g. the metricbeat mongodb module) - key: `field-${field}`, - label: field, - }, - columnConfiguration: { - fieldColumn: { - id: uuidv4(), - field, - }, - }, - })), - ], - [availableFields] - ); - - const availableOptions = useMemo( - () => availableColumnOptions.map((availableColumnOption) => availableColumnOption.optionProps), - [availableColumnOptions] - ); - - const handleColumnSelection = useCallback( - (selectedOptions: EuiSelectableOption[]) => { - closePopover(); - - const selectedOptionIndex = selectedOptions.findIndex( - (selectedOption) => selectedOption.checked === 'on' - ); - const selectedOption = availableColumnOptions[selectedOptionIndex]; - - addLogColumn(selectedOption.columnConfiguration); - }, - [addLogColumn, availableColumnOptions, closePopover] - ); - - return ( - - - - } - closePopover={closePopover} - id="addLogColumn" - isOpen={isOpen} - ownFocus - panelPaddingSize="none" - > - - {(list, search) => ( - - {search} - {list} - - )} - - - ); -}; - -const searchProps = { - 'data-test-subj': 'fieldSearchInput', -}; - -const selectableListProps = { - showIcons: false, -}; - -const SystemColumnBadge: React.FunctionComponent = () => ( - - - -); - -const SelectableContent = euiStyled.div` - width: 400px; -`; diff --git a/x-pack/plugins/infra/public/components/source_configuration/fields_configuration_panel.tsx b/x-pack/plugins/infra/public/components/source_configuration/fields_configuration_panel.tsx index 369f07be67bf..5ad05deafd69 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/fields_configuration_panel.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/fields_configuration_panel.tsx @@ -27,9 +27,7 @@ interface FieldsConfigurationPanelProps { isLoading: boolean; readOnly: boolean; podFieldProps: InputFieldProps; - tiebreakerFieldProps: InputFieldProps; timestampFieldProps: InputFieldProps; - displaySettings: 'metrics' | 'logs'; } export const FieldsConfigurationPanel = ({ @@ -38,15 +36,12 @@ export const FieldsConfigurationPanel = ({ isLoading, readOnly, podFieldProps, - tiebreakerFieldProps, timestampFieldProps, - displaySettings, }: FieldsConfigurationPanelProps) => { const isHostValueDefault = hostFieldProps.value === 'host.name'; const isContainerValueDefault = containerFieldProps.value === 'container.id'; const isPodValueDefault = podFieldProps.value === 'kubernetes.pod.uid'; const isTimestampValueDefault = timestampFieldProps.value === '@timestamp'; - const isTiebreakerValueDefault = tiebreakerFieldProps.value === '_doc'; return ( @@ -139,194 +134,141 @@ export const FieldsConfigurationPanel = ({ /> - {displaySettings === 'logs' && ( - <> - - - - } - description={ - - } - > - _doc, - }} - /> - } - isInvalid={tiebreakerFieldProps.isInvalid} - label={ - - } - > - - - - - )} - {displaySettings === 'metrics' && ( - <> - - - - } - description={ - - } - > - container.id, - }} - /> - } - isInvalid={containerFieldProps.isInvalid} - label={ - - } - > - - - - - - - } - description={ - - } - > - host.name, - }} - /> - } - isInvalid={hostFieldProps.isInvalid} - label={ - - } - > - - - - - - - } - description={ - - } - > - kubernetes.pod.uid, - }} - /> - } - isInvalid={podFieldProps.isInvalid} - label={ - - } - > - - - - - )} + + + + } + description={ + + } + > + container.id, + }} + /> + } + isInvalid={containerFieldProps.isInvalid} + label={ + + } + > + + + + + + + } + description={ + + } + > + host.name, + }} + /> + } + isInvalid={hostFieldProps.isInvalid} + label={ + + } + > + + + + + + + } + description={ + + } + > + kubernetes.pod.uid, + }} + /> + } + isInvalid={podFieldProps.isInvalid} + label={ + + } + > + + + ); }; diff --git a/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_panel.tsx b/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_panel.tsx index 1d634b781bd3..e9817331ace9 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_panel.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/indices_configuration_panel.tsx @@ -21,17 +21,13 @@ import { InputFieldProps } from './input_fields'; interface IndicesConfigurationPanelProps { isLoading: boolean; readOnly: boolean; - logAliasFieldProps: InputFieldProps; metricAliasFieldProps: InputFieldProps; - displaySettings: 'metrics' | 'logs'; } export const IndicesConfigurationPanel = ({ isLoading, readOnly, - logAliasFieldProps, metricAliasFieldProps, - displaySettings, }: IndicesConfigurationPanelProps) => ( @@ -43,101 +39,51 @@ export const IndicesConfigurationPanel = ({ - {displaySettings === 'metrics' && ( - - - - } - description={ + + + } + description={ + + } + > + metrics-*,metricbeat-*, + }} + /> + } + isInvalid={metricAliasFieldProps.isInvalid} + label={ + } > - metricbeat-*, - }} - /> - } - isInvalid={metricAliasFieldProps.isInvalid} - label={ - - } - > - - - - )} - {displaySettings === 'logs' && ( - - - - } - description={ - - } - > - filebeat-*, - }} - /> - } - isInvalid={logAliasFieldProps.isInvalid} - label={ - - } - > - - - - )} + disabled={isLoading} + readOnly={readOnly} + isLoading={isLoading} + {...metricAliasFieldProps} + /> + + ); diff --git a/x-pack/plugins/infra/public/components/source_configuration/log_columns_configuration_panel.tsx b/x-pack/plugins/infra/public/components/source_configuration/log_columns_configuration_panel.tsx deleted file mode 100644 index 46ab1e65c29d..000000000000 --- a/x-pack/plugins/infra/public/components/source_configuration/log_columns_configuration_panel.tsx +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - EuiButtonIcon, - EuiEmptyPrompt, - EuiForm, - EuiPanel, - EuiSpacer, - EuiText, - EuiTitle, - EuiFlexGroup, - EuiFlexItem, - EuiDragDropContext, - EuiDraggable, - EuiDroppable, - EuiIcon, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React, { useCallback } from 'react'; -import { DragHandleProps, DropResult } from '../../../../observability/public'; - -import { AddLogColumnButtonAndPopover } from './add_log_column_popover'; -import { - FieldLogColumnConfigurationProps, - LogColumnConfigurationProps, -} from './log_columns_configuration_form_state'; -import { LogColumnConfiguration } from '../../utils/source_configuration'; - -interface LogColumnsConfigurationPanelProps { - availableFields: string[]; - isLoading: boolean; - logColumnConfiguration: LogColumnConfigurationProps[]; - addLogColumn: (logColumn: LogColumnConfiguration) => void; - moveLogColumn: (sourceIndex: number, destinationIndex: number) => void; -} - -export const LogColumnsConfigurationPanel: React.FunctionComponent = ({ - addLogColumn, - moveLogColumn, - availableFields, - isLoading, - logColumnConfiguration, -}) => { - const onDragEnd = useCallback( - ({ source, destination }: DropResult) => - destination && moveLogColumn(source.index, destination.index), - [moveLogColumn] - ); - - return ( - - - - -

- -

-
-
- - - -
- {logColumnConfiguration.length > 0 ? ( - - - <> - {/* Fragment here necessary for typechecking */} - {logColumnConfiguration.map((column, index) => ( - - {(provided) => ( - - )} - - ))} - - - - ) : ( - - )} -
- ); -}; - -interface LogColumnConfigurationPanelProps { - logColumnConfigurationProps: LogColumnConfigurationProps; - dragHandleProps: DragHandleProps; -} - -const LogColumnConfigurationPanel: React.FunctionComponent = ( - props -) => ( - <> - - {props.logColumnConfigurationProps.type === 'timestamp' ? ( - - ) : props.logColumnConfigurationProps.type === 'message' ? ( - - ) : ( - - )} - -); - -const TimestampLogColumnConfigurationPanel: React.FunctionComponent = ({ - logColumnConfigurationProps, - dragHandleProps, -}) => ( - timestamp, - }} - /> - } - removeColumn={logColumnConfigurationProps.remove} - dragHandleProps={dragHandleProps} - /> -); - -const MessageLogColumnConfigurationPanel: React.FunctionComponent = ({ - logColumnConfigurationProps, - dragHandleProps, -}) => ( - - } - removeColumn={logColumnConfigurationProps.remove} - dragHandleProps={dragHandleProps} - /> -); - -const FieldLogColumnConfigurationPanel: React.FunctionComponent<{ - logColumnConfigurationProps: FieldLogColumnConfigurationProps; - dragHandleProps: DragHandleProps; -}> = ({ - logColumnConfigurationProps: { - logColumnConfiguration: { field }, - remove, - }, - dragHandleProps, -}) => { - const fieldLogColumnTitle = i18n.translate( - 'xpack.infra.sourceConfiguration.fieldLogColumnTitle', - { - defaultMessage: 'Field', - } - ); - return ( - - - -
- -
-
- {fieldLogColumnTitle} - - {field} - - - - -
-
- ); -}; - -const ExplainedLogColumnConfigurationPanel: React.FunctionComponent<{ - fieldName: React.ReactNode; - helpText: React.ReactNode; - removeColumn: () => void; - dragHandleProps: DragHandleProps; -}> = ({ fieldName, helpText, removeColumn, dragHandleProps }) => ( - - - -
- -
-
- {fieldName} - - - {helpText} - - - - - -
-
-); - -const RemoveLogColumnButton: React.FunctionComponent<{ - onClick?: () => void; - columnDescription: string; -}> = ({ onClick, columnDescription }) => { - const removeColumnLabel = i18n.translate( - 'xpack.infra.sourceConfiguration.removeLogColumnButtonLabel', - { - defaultMessage: 'Remove {columnDescription} column', - values: { columnDescription }, - } - ); - - return ( - - ); -}; - -const LogColumnConfigurationEmptyPrompt: React.FunctionComponent = () => ( - - - - } - body={ -

- -

- } - /> -); diff --git a/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx b/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx index 43bdc1f4cedc..53b62f8dda04 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/source_configuration_settings.tsx @@ -22,19 +22,16 @@ import { Source } from '../../containers/source'; import { FieldsConfigurationPanel } from './fields_configuration_panel'; import { IndicesConfigurationPanel } from './indices_configuration_panel'; import { NameConfigurationPanel } from './name_configuration_panel'; -import { LogColumnsConfigurationPanel } from './log_columns_configuration_panel'; import { useSourceConfigurationFormState } from './source_configuration_form_state'; import { SourceLoadingPage } from '../source_loading_page'; import { Prompt } from '../../utils/navigation_warning_prompt'; interface SourceConfigurationSettingsProps { shouldAllowEdit: boolean; - displaySettings: 'metrics' | 'logs'; } export const SourceConfigurationSettings = ({ shouldAllowEdit, - displaySettings, }: SourceConfigurationSettingsProps) => { const { createSourceConfiguration, @@ -45,16 +42,8 @@ export const SourceConfigurationSettings = ({ updateSourceConfiguration, } = useContext(Source.Context); - const availableFields = useMemo( - () => (source && source.status ? source.status.indexFields.map((field) => field.name) : []), - [source] - ); - const { - addLogColumn, - moveLogColumn, indicesConfigurationProps, - logColumnConfigurationProps, errors, resetForm, isFormDirty, @@ -119,10 +108,8 @@ export const SourceConfigurationSettings = ({ @@ -133,23 +120,10 @@ export const SourceConfigurationSettings = ({ isLoading={isLoading} podFieldProps={indicesConfigurationProps.podField} readOnly={!isWriteable} - tiebreakerFieldProps={indicesConfigurationProps.tiebreakerField} timestampFieldProps={indicesConfigurationProps.timestampField} - displaySettings={displaySettings} /> - {displaySettings === 'logs' && ( - - - - )} {errors.length > 0 ? ( <> diff --git a/x-pack/plugins/infra/public/pages/logs/settings/indices_configuration_panel.tsx b/x-pack/plugins/infra/public/pages/logs/settings/indices_configuration_panel.tsx index 83effaa3d51a..b1dc55fe5c18 100644 --- a/x-pack/plugins/infra/public/pages/logs/settings/indices_configuration_panel.tsx +++ b/x-pack/plugins/infra/public/pages/logs/settings/indices_configuration_panel.tsx @@ -62,7 +62,7 @@ export const IndicesConfigurationPanel = ({ id="xpack.infra.sourceConfiguration.logIndicesRecommendedValue" defaultMessage="The recommended value is {defaultValue}" values={{ - defaultValue: filebeat-*, + defaultValue: logs-*,filebeat-*, }} /> } diff --git a/x-pack/plugins/infra/public/pages/metrics/settings.tsx b/x-pack/plugins/infra/public/pages/metrics/settings.tsx index 7d4f35b19da7..b0aa67b5f081 100644 --- a/x-pack/plugins/infra/public/pages/metrics/settings.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/settings.tsx @@ -15,7 +15,6 @@ export const MetricsSettingsPage = () => { ); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts new file mode 100644 index 000000000000..3ad1031f574e --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { MetricExpressionParams } from '../types'; +import { getElasticsearchMetricQuery } from './metric_query'; + +describe("The Metric Threshold Alert's getElasticsearchMetricQuery", () => { + const expressionParams = { + metric: 'system.is.a.good.puppy.dog', + aggType: 'avg', + timeUnit: 'm', + timeSize: 1, + } as MetricExpressionParams; + + const timefield = '@timestamp'; + const groupBy = 'host.doggoname'; + + describe('when passed no filterQuery', () => { + const searchBody = getElasticsearchMetricQuery(expressionParams, timefield, groupBy); + test('includes a range filter', () => { + expect( + searchBody.query.bool.filter.find((filter) => filter.hasOwnProperty('range')) + ).toBeTruthy(); + }); + + test('includes a metric field filter', () => { + expect(searchBody.query.bool.filter).toMatchObject( + expect.arrayContaining([{ exists: { field: 'system.is.a.good.puppy.dog' } }]) + ); + }); + }); + + describe('when passed a filterQuery', () => { + const filterQuery = + // This is adapted from a real-world query that previously broke alerts + // We want to make sure it doesn't override any existing filters + '{"bool":{"filter":[{"bool":{"filter":[{"bool":{"must_not":[{"bool":{"should":[{"query_string":{"query":"bark*","fields":["host.name^1.0"],"type":"best_fields","default_operator":"or","max_determinized_states":10000,"enable_position_increments":true,"fuzziness":"AUTO","fuzzy_prefix_length":0,"fuzzy_max_expansions":50,"phrase_slop":0,"escape":false,"auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":1}}],"adjust_pure_negative":true,"minimum_should_match":"1","boost":1}}],"adjust_pure_negative":true,"boost":1}},{"bool":{"must_not":[{"bool":{"should":[{"query_string":{"query":"woof*","fields":["host.name^1.0"],"type":"best_fields","default_operator":"or","max_determinized_states":10000,"enable_position_increments":true,"fuzziness":"AUTO","fuzzy_prefix_length":0,"fuzzy_max_expansions":50,"phrase_slop":0,"escape":false,"auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":1}}],"adjust_pure_negative":true,"minimum_should_match":"1","boost":1}}],"adjust_pure_negative":true,"boost":1}}],"adjust_pure_negative":true,"boost":1}}],"adjust_pure_negative":true,"boost":1}}'; + + const searchBody = getElasticsearchMetricQuery( + expressionParams, + timefield, + groupBy, + filterQuery + ); + test('includes a range filter', () => { + expect( + searchBody.query.bool.filter.find((filter) => filter.hasOwnProperty('range')) + ).toBeTruthy(); + }); + + test('includes a metric field filter', () => { + expect(searchBody.query.bool.filter).toMatchObject( + expect.arrayContaining([{ exists: { field: 'system.is.a.good.puppy.dog' } }]) + ); + }); + }); +}); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts index 5680035d9d60..15506a30529c 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts @@ -11,11 +11,11 @@ import { createPercentileAggregation } from './create_percentile_aggregation'; const MINIMUM_BUCKETS = 5; -const getParsedFilterQuery: ( - filterQuery: string | undefined -) => Record | Array> = (filterQuery) => { - if (!filterQuery) return {}; - return JSON.parse(filterQuery).bool; +const getParsedFilterQuery: (filterQuery: string | undefined) => Record | null = ( + filterQuery +) => { + if (!filterQuery) return null; + return JSON.parse(filterQuery); }; export const getElasticsearchMetricQuery = ( @@ -129,9 +129,8 @@ export const getElasticsearchMetricQuery = ( filter: [ ...rangeFilters, ...metricFieldFilters, - ...(Array.isArray(parsedFilterQuery) ? parsedFilterQuery : []), + ...(parsedFilterQuery ? [parsedFilterQuery] : []), ], - ...(!Array.isArray(parsedFilterQuery) ? parsedFilterQuery : {}), }, }, size: 0, diff --git a/x-pack/plugins/infra/server/lib/sources/defaults.ts b/x-pack/plugins/infra/server/lib/sources/defaults.ts index ba22b4db62d6..b096bed84fa9 100644 --- a/x-pack/plugins/infra/server/lib/sources/defaults.ts +++ b/x-pack/plugins/infra/server/lib/sources/defaults.ts @@ -9,8 +9,8 @@ import { InfraSourceConfiguration } from '../../../common/http_api/source_api'; export const defaultSourceConfiguration: InfraSourceConfiguration = { name: 'Default', description: '', - metricAlias: 'metricbeat-*', - logAlias: 'filebeat-*,kibana_sample_data_logs*', + metricAlias: 'metrics-*,metricbeat-*', + logAlias: 'logs-*,filebeat-*,kibana_sample_data_logs*', fields: { container: 'container.id', host: 'host.name', diff --git a/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts b/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts new file mode 100644 index 000000000000..59a22d33de85 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.test.ts @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { migrationMocks } from 'src/core/server/mocks'; +import { addNewIndexingStrategyIndexNames } from './7_9_0_add_new_indexing_strategy_index_names'; +import { infraSourceConfigurationSavedObjectName } from '../saved_object_type'; + +describe('infra source configuration migration function for 7.9.0', () => { + test('adds "logs-*" when the logAlias contains "filebeat-*"', () => { + const unmigratedConfiguration = createTestSourceConfiguration( + 'filebeat-*,custom-log-index-*', + 'custom-metric-index-*' + ); + + const migratedConfiguration = addNewIndexingStrategyIndexNames( + unmigratedConfiguration, + migrationMocks.createContext() + ); + + expect(migratedConfiguration).toStrictEqual( + createTestSourceConfiguration('filebeat-*,custom-log-index-*,logs-*', 'custom-metric-index-*') + ); + }); + + test('doesn\'t add "logs-*" when the logAlias doesn\'t contain "filebeat-*"', () => { + const unmigratedConfiguration = createTestSourceConfiguration( + 'custom-log-index-*', + 'custom-metric-index-*' + ); + + const migratedConfiguration = addNewIndexingStrategyIndexNames( + unmigratedConfiguration, + migrationMocks.createContext() + ); + + expect(migratedConfiguration).toStrictEqual(unmigratedConfiguration); + }); + + test('doesn\'t add "logs-*" when the logAlias already contains it', () => { + const unmigratedConfiguration = createTestSourceConfiguration( + 'filebeat-*,logs-*,custom-log-index-*', + 'custom-metric-index-*' + ); + + const migratedConfiguration = addNewIndexingStrategyIndexNames( + unmigratedConfiguration, + migrationMocks.createContext() + ); + + expect(migratedConfiguration).toStrictEqual(unmigratedConfiguration); + }); + + test('adds "metrics-*" when the logAlias contains "metricbeat-*"', () => { + const unmigratedConfiguration = createTestSourceConfiguration( + 'custom-log-index-*', + 'metricbeat-*,custom-metric-index-*' + ); + + const migratedConfiguration = addNewIndexingStrategyIndexNames( + unmigratedConfiguration, + migrationMocks.createContext() + ); + + expect(migratedConfiguration).toStrictEqual( + createTestSourceConfiguration( + 'custom-log-index-*', + 'metricbeat-*,custom-metric-index-*,metrics-*' + ) + ); + }); + + test('doesn\'t add "metrics-*" when the logAlias doesn\'t contain "metricbeat-*"', () => { + const unmigratedConfiguration = createTestSourceConfiguration( + 'custom-log-index-*', + 'custom-metric-index-*' + ); + + const migratedConfiguration = addNewIndexingStrategyIndexNames( + unmigratedConfiguration, + migrationMocks.createContext() + ); + + expect(migratedConfiguration).toStrictEqual(unmigratedConfiguration); + }); + + test('doesn\'t add "metrics-*" when the metricAlias already contains it', () => { + const unmigratedConfiguration = createTestSourceConfiguration( + 'custom-log-index-*', + 'metrics-*,metricbeat-*,custom-metric-index-*' + ); + + const migratedConfiguration = addNewIndexingStrategyIndexNames( + unmigratedConfiguration, + migrationMocks.createContext() + ); + + expect(migratedConfiguration).toStrictEqual(unmigratedConfiguration); + }); +}); + +const createTestSourceConfiguration = (logAlias: string, metricAlias: string) => ({ + attributes: { + name: 'TEST CONFIGURATION', + description: '', + fields: { + pod: 'TEST POD FIELD', + host: 'TEST HOST FIELD', + message: ['TEST MESSAGE FIELD'], + container: 'TEST CONTAINER FIELD', + timestamp: 'TEST TIMESTAMP FIELD', + tiebreaker: 'TEST TIEBREAKER FIELD', + }, + inventoryDefaultView: '0', + metricsExplorerDefaultView: '0', + logColumns: [ + { + fieldColumn: { + id: 'TEST FIELD COLUMN ID', + field: 'TEST FIELD COLUMN FIELD', + }, + }, + ], + logAlias, + metricAlias, + }, + id: 'TEST_ID', + type: infraSourceConfigurationSavedObjectName, +}); diff --git a/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.ts b/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.ts new file mode 100644 index 000000000000..0d5563191d1b --- /dev/null +++ b/x-pack/plugins/infra/server/lib/sources/migrations/7_9_0_add_new_indexing_strategy_index_names.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedObjectMigrationFn } from 'src/core/server'; +import { InfraSourceConfiguration } from '../../../../common/http_api/source_api'; + +export const addNewIndexingStrategyIndexNames: SavedObjectMigrationFn< + InfraSourceConfiguration, + InfraSourceConfiguration +> = (sourceConfigurationDocument) => { + const oldLogAliasSegments = sourceConfigurationDocument.attributes.logAlias.split(','); + const oldMetricAliasSegments = sourceConfigurationDocument.attributes.metricAlias.split(','); + + const newLogAliasSegment = 'logs-*'; + const newMetricAliasSegment = 'metrics-*'; + + return { + ...sourceConfigurationDocument, + attributes: { + ...sourceConfigurationDocument.attributes, + logAlias: + oldLogAliasSegments.includes('filebeat-*') && + !oldLogAliasSegments.includes(newLogAliasSegment) + ? [...oldLogAliasSegments, newLogAliasSegment].join(',') + : sourceConfigurationDocument.attributes.logAlias, + metricAlias: + oldMetricAliasSegments.includes('metricbeat-*') && + !oldMetricAliasSegments.includes(newMetricAliasSegment) + ? [...oldMetricAliasSegments, newMetricAliasSegment].join(',') + : sourceConfigurationDocument.attributes.metricAlias, + }, + }; +}; diff --git a/x-pack/plugins/infra/server/lib/sources/saved_object_type.ts b/x-pack/plugins/infra/server/lib/sources/saved_object_type.ts index a36ef8d1a892..11db18d6bf79 100644 --- a/x-pack/plugins/infra/server/lib/sources/saved_object_type.ts +++ b/x-pack/plugins/infra/server/lib/sources/saved_object_type.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths import { SavedObjectsType } from 'src/core/server'; +import { addNewIndexingStrategyIndexNames } from './migrations/7_9_0_add_new_indexing_strategy_index_names'; export const infraSourceConfigurationSavedObjectName = 'infrastructure-ui-source'; @@ -86,4 +86,7 @@ export const infraSourceConfigurationSavedObjectType: SavedObjectsType = { }, }, }, + migrations: { + '7.9.0': addNewIndexingStrategyIndexNames, + }, }; diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 3ee3039e9e1c..0d2825f0aa80 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -175,6 +175,12 @@ export interface Dataset { package: string; path: string; ingest_pipeline: string; + elasticsearch?: RegistryElasticsearch; +} + +export interface RegistryElasticsearch { + 'index_template.settings'?: object; + 'index_template.mappings'?: object; } // EPR types this as `[]map[string]interface{}` @@ -272,6 +278,7 @@ export interface IndexTemplate { data_stream: { timestamp_field: string; }; + composed_of: string[]; _meta: object; } diff --git a/x-pack/plugins/ingest_manager/common/types/models/package_config.ts b/x-pack/plugins/ingest_manager/common/types/models/package_config.ts index e9595bab0174..0ff56e6d05d3 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/package_config.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/package_config.ts @@ -55,9 +55,14 @@ export interface NewPackageConfig { inputs: NewPackageConfigInput[]; } +export interface UpdatePackageConfig extends NewPackageConfig { + version?: string; +} + export interface PackageConfig extends Omit { id: string; inputs: PackageConfigInput[]; + version?: string; revision: number; updated_at: string; updated_by: string; @@ -65,4 +70,4 @@ export interface PackageConfig extends Omit { created_by: string; } -export type PackageConfigSOAttributes = Omit; +export type PackageConfigSOAttributes = Omit; diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/package_config.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/package_config.ts index 4b8abbde47d5..e62645debb74 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/package_config.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/package_config.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { PackageConfig, NewPackageConfig } from '../models'; +import { PackageConfig, NewPackageConfig, UpdatePackageConfig } from '../models'; export interface GetPackageConfigsRequest { query: { @@ -42,7 +42,7 @@ export interface CreatePackageConfigResponse { } export type UpdatePackageConfigRequest = GetOnePackageConfigRequest & { - body: NewPackageConfig; + body: UpdatePackageConfig; }; export type UpdatePackageConfigResponse = CreatePackageConfigResponse; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/page_paths.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/page_paths.ts index 9881d5e40d8a..9f1088a94aa9 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/page_paths.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/page_paths.ts @@ -53,7 +53,7 @@ export const PAGE_ROUTING_PATHS = { fleet_agent_details_events: '/fleet/agents/:agentId', fleet_agent_details_details: '/fleet/agents/:agentId/details', fleet_enrollment_tokens: '/fleet/enrollment-tokens', - data_streams: '/data-streams', + data_streams: '/datasets', }; export const pagePathGetters: { @@ -80,5 +80,5 @@ export const pagePathGetters: { fleet_agent_details: ({ agentId, tabId }) => `/fleet/agents/${agentId}${tabId ? `/${tabId}` : ''}`, fleet_enrollment_tokens: () => '/fleet/enrollment-tokens', - data_streams: () => '/data-streams', + data_streams: () => '/datasets', }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx index 2b92987963ef..293638cff50b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx @@ -207,7 +207,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { text: i18n.translate('xpack.ingestManager.breadcrumbs.datastreamsPageTitle', { - defaultMessage: 'Data streams', + defaultMessage: 'Datasets', }), }, ], diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/use_request.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/use_request.ts index fbbc482fb96a..1486c2e50b7a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/use_request.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/use_request.ts @@ -17,33 +17,39 @@ let httpClient: HttpSetup; export type UseRequestConfig = _UseRequestConfig; +interface RequestError extends Error { + statusCode?: number; +} + export const setHttpClient = (client: HttpSetup) => { httpClient = client; }; -export const sendRequest = ( +export const sendRequest = ( config: SendRequestConfig -): Promise> => { +): Promise> => { if (!httpClient) { throw new Error('sendRequest has no http client set'); } - return _sendRequest(httpClient, config); + return _sendRequest(httpClient, config); }; -export const useRequest = (config: UseRequestConfig) => { +export const useRequest = (config: UseRequestConfig) => { if (!httpClient) { throw new Error('sendRequest has no http client set'); } - return _useRequest(httpClient, config); + return _useRequest(httpClient, config); }; export type SendConditionalRequestConfig = | (SendRequestConfig & { shouldSendRequest: true }) | (Partial & { shouldSendRequest: false }); -export const useConditionalRequest = (config: SendConditionalRequestConfig) => { +export const useConditionalRequest = ( + config: SendConditionalRequestConfig +) => { const [state, setState] = useState<{ - error: Error | null; + error: RequestError | null; data: D | null; isLoading: boolean; }>({ @@ -70,7 +76,7 @@ export const useConditionalRequest = (config: SendConditionalRequestCon isLoading: true, error: null, }); - const res = await sendRequest({ + const res = await sendRequest({ method: config.method, path: config.path, query: config.query, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 5e0cba7383e9..1f356301b714 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -103,7 +103,7 @@ export const DefaultLayout: React.FunctionComponent = ({ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx index 7fbcdbb9738c..52fd95d66367 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_package_config_page/index.tsx @@ -16,7 +16,7 @@ import { EuiFlexItem, EuiSpacer, } from '@elastic/eui'; -import { AgentConfig, PackageInfo, NewPackageConfig } from '../../../types'; +import { AgentConfig, PackageInfo, UpdatePackageConfig } from '../../../types'; import { useLink, useBreadcrumbs, @@ -72,7 +72,7 @@ export const EditPackageConfigPage: React.FunctionComponent = () => { const [loadingError, setLoadingError] = useState(); const [agentConfig, setAgentConfig] = useState(); const [packageInfo, setPackageInfo] = useState(); - const [packageConfig, setPackageConfig] = useState({ + const [packageConfig, setPackageConfig] = useState({ name: '', description: '', namespace: '', @@ -80,6 +80,7 @@ export const EditPackageConfigPage: React.FunctionComponent = () => { enabled: true, output_id: '', inputs: [], + version: '', }); // Retrieve agent config, package, and package config info @@ -160,7 +161,7 @@ export const EditPackageConfigPage: React.FunctionComponent = () => { const hasErrors = validationResults ? validationHasErrors(validationResults) : false; // Update package config method - const updatePackageConfig = (updatedFields: Partial) => { + const updatePackageConfig = (updatedFields: Partial) => { const newPackageConfig = { ...packageConfig, ...updatedFields, @@ -178,7 +179,7 @@ export const EditPackageConfigPage: React.FunctionComponent = () => { } }; - const updatePackageConfigValidation = (newPackageConfig?: NewPackageConfig) => { + const updatePackageConfigValidation = (newPackageConfig?: UpdatePackageConfig) => { if (packageInfo) { const newValidationResult = validatePackageConfig( newPackageConfig || packageConfig, @@ -234,9 +235,31 @@ export const EditPackageConfigPage: React.FunctionComponent = () => { : undefined, }); } else { - notifications.toasts.addError(error, { - title: 'Error', - }); + if (error.statusCode === 409) { + notifications.toasts.addError(error, { + title: i18n.translate('xpack.ingestManager.editPackageConfig.failedNotificationTitle', { + defaultMessage: `Error updating '{packageConfigName}'`, + values: { + packageConfigName: packageConfig.name, + }, + }), + toastMessage: i18n.translate( + 'xpack.ingestManager.editPackageConfig.failedConflictNotificationMessage', + { + defaultMessage: `Data is out of date. Refresh the page to get the latest configuration.`, + } + ), + }); + } else { + notifications.toasts.addError(error, { + title: i18n.translate('xpack.ingestManager.editPackageConfig.failedNotificationTitle', { + defaultMessage: `Error updating '{packageConfigName}'`, + values: { + packageConfigName: packageConfig.name, + }, + }), + }); + } setFormState('VALID'); } }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx index e1583d2e426b..a6e458a4615c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx @@ -32,7 +32,7 @@ const DataStreamListPageLayout: React.FunctionComponent = ({ children }) => (

@@ -177,7 +177,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {

} @@ -220,14 +220,14 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { isLoading ? ( ) : dataStreamsData && !dataStreamsData.data_streams.length ? ( emptyPrompt ) : ( ) } @@ -257,7 +257,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { placeholder: i18n.translate( 'xpack.ingestManager.dataStreamList.searchPlaceholderTitle', { - defaultMessage: 'Filter data streams', + defaultMessage: 'Filter datasets', } ), incremental: true, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_links.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_links.tsx index 436163bafcfe..a453a7f2e28c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_links.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_links.tsx @@ -13,10 +13,7 @@ const removeRelativePath = (relativePath: string): string => export function useLinks() { const { http } = useCore(); return { - toAssets: (path: string) => - http.basePath.prepend( - `/plugins/${PLUGIN_ID}/applications/ingest_manager/sections/epm/assets/${path}` - ), + toAssets: (path: string) => http.basePath.prepend(`/plugins/${PLUGIN_ID}/assets/${path}`), toImage: (path: string) => http.basePath.prepend(epmRouteService.getFilePath(path)), toRelativeImage: ({ path, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx index 87906afb4122..eab6cf087e12 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx @@ -51,14 +51,14 @@ export const OverviewDatastreamSection: React.FC = () => {

@@ -70,7 +70,7 @@ export const OverviewDatastreamSection: React.FC = () => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts index 43ec2f6d1a74..e28d76cae995 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts @@ -15,6 +15,7 @@ export { EnrollmentAPIKey, PackageConfig, NewPackageConfig, + UpdatePackageConfig, PackageConfigInput, PackageConfigInputStream, PackageConfigConfigRecordEntry, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/assets/illustration_integrations_darkmode.svg b/x-pack/plugins/ingest_manager/public/assets/illustration_integrations_darkmode.svg similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/assets/illustration_integrations_darkmode.svg rename to x-pack/plugins/ingest_manager/public/assets/illustration_integrations_darkmode.svg diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/assets/illustration_integrations_lightmode.svg b/x-pack/plugins/ingest_manager/public/assets/illustration_integrations_lightmode.svg similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/assets/illustration_integrations_lightmode.svg rename to x-pack/plugins/ingest_manager/public/assets/illustration_integrations_lightmode.svg diff --git a/x-pack/plugins/ingest_manager/server/routes/package_config/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/package_config/handlers.ts index e212c861ce77..f11275c92bb6 100644 --- a/x-pack/plugins/ingest_manager/server/routes/package_config/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/package_config/handlers.ts @@ -178,7 +178,7 @@ export const updatePackageConfigHandler: RequestHandler< }); } catch (e) { return response.customError({ - statusCode: 500, + statusCode: e.statusCode || 500, body: { message: e.message }, }); } diff --git a/x-pack/plugins/ingest_manager/server/services/agents/enroll.test.ts b/x-pack/plugins/ingest_manager/server/services/agents/enroll.test.ts new file mode 100644 index 000000000000..764564cfa49f --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/agents/enroll.test.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { validateAgentVersion } from './enroll'; +import { appContextService } from '../app_context'; +import { IngestManagerAppContext } from '../../plugin'; + +describe('validateAgentVersion', () => { + it('should throw with agent > kibana version', () => { + appContextService.start(({ + kibanaVersion: '8.0.0', + } as unknown) as IngestManagerAppContext); + expect(() => + validateAgentVersion({ + local: { elastic: { agent: { version: '8.8.0' } } }, + userProvided: {}, + }) + ).toThrowError(/Agent version is not compatible with kibana version/); + }); + it('should work with agent < kibana version', () => { + appContextService.start(({ + kibanaVersion: '8.0.0', + } as unknown) as IngestManagerAppContext); + validateAgentVersion({ local: { elastic: { agent: { version: '7.8.0' } } }, userProvided: {} }); + }); + + it('should work with agent = kibana version', () => { + appContextService.start(({ + kibanaVersion: '8.0.0', + } as unknown) as IngestManagerAppContext); + validateAgentVersion({ local: { elastic: { agent: { version: '8.0.0' } } }, userProvided: {} }); + }); + + it('should work with SNAPSHOT version', () => { + appContextService.start(({ + kibanaVersion: '8.0.0-SNAPSHOT', + } as unknown) as IngestManagerAppContext); + validateAgentVersion({ + local: { elastic: { agent: { version: '8.0.0-SNAPSHOT' } } }, + userProvided: {}, + }); + }); + + it('should work with a agent using SNAPSHOT version', () => { + appContextService.start(({ + kibanaVersion: '7.8.0', + } as unknown) as IngestManagerAppContext); + validateAgentVersion({ + local: { elastic: { agent: { version: '7.8.0-SNAPSHOT' } } }, + userProvided: {}, + }); + }); + + it('should work with a kibana using SNAPSHOT version', () => { + appContextService.start(({ + kibanaVersion: '7.8.0-SNAPSHOT', + } as unknown) as IngestManagerAppContext); + validateAgentVersion({ + local: { elastic: { agent: { version: '7.8.0' } } }, + userProvided: {}, + }); + }); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/agents/enroll.ts b/x-pack/plugins/ingest_manager/server/services/agents/enroll.ts index bf15815e6ae4..b63b1c13e4df 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/enroll.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/enroll.ts @@ -20,11 +20,7 @@ export async function enroll( metadata?: { local: any; userProvided: any }, sharedId?: string ): Promise { - const kibanaVersion = appContextService.getKibanaVersion(); - const version: string | undefined = metadata?.local?.elastic?.agent?.version; - if (!version || semver.compare(version, kibanaVersion) === 1) { - throw Boom.badRequest('Agent version is not compatible with kibana version'); - } + validateAgentVersion(metadata); const existingAgent = sharedId ? await getAgentBySharedId(soClient, sharedId) : null; @@ -92,3 +88,25 @@ async function getAgentBySharedId(soClient: SavedObjectsClientContract, sharedId return null; } + +export function validateAgentVersion(metadata?: { local: any; userProvided: any }) { + const kibanaVersion = semver.parse(appContextService.getKibanaVersion()); + if (!kibanaVersion) { + throw Boom.badRequest('Kibana version is not set'); + } + const version = semver.parse(metadata?.local?.elastic?.agent?.version); + if (!version) { + throw Boom.badRequest('Agent version not provided in metadata.'); + } + + if (!version || !semver.lte(formatVersion(version), formatVersion(kibanaVersion))) { + throw Boom.badRequest('Agent version is not compatible with kibana version'); + } +} + +/** + * used to remove prelease from version as includePrerelease in not working as expected + */ +function formatVersion(version: semver.SemVer) { + return `${version.major}.${version.minor}.${version.patch}`; +} diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap index f5fec020bf5b..848e65b7931e 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap @@ -94,6 +94,7 @@ exports[`tests loading base.yml: base.yml 1`] = ` "data_stream": { "timestamp_field": "@timestamp" }, + "composed_of": [], "_meta": { "package": { "name": "nginx" @@ -197,6 +198,7 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = ` "data_stream": { "timestamp_field": "@timestamp" }, + "composed_of": [], "_meta": { "package": { "name": "coredns" @@ -1684,6 +1686,7 @@ exports[`tests loading system.yml: system.yml 1`] = ` "data_stream": { "timestamp_field": "@timestamp" }, + "composed_of": [], "_meta": { "package": { "name": "system" diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts index a318aecf347d..e14645bbbf5f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts @@ -5,7 +5,13 @@ */ import Boom from 'boom'; -import { Dataset, RegistryPackage, ElasticsearchAssetType, TemplateRef } from '../../../../types'; +import { + Dataset, + RegistryPackage, + ElasticsearchAssetType, + TemplateRef, + RegistryElasticsearch, +} from '../../../../types'; import { CallESAsCurrentUser } from '../../../../types'; import { Field, loadFieldsFromYaml, processFields } from '../../fields/field'; import { getPipelineNameForInstallation } from '../ingest_pipeline/install'; @@ -157,6 +163,98 @@ export async function installTemplateForDataset({ }); } +function putComponentTemplate( + body: object | undefined, + name: string, + callCluster: CallESAsCurrentUser +): { clusterPromise: Promise; name: string } | undefined { + if (body) { + const callClusterParams: { + method: string; + path: string; + ignore: number[]; + body: any; + } = { + method: 'PUT', + path: `/_component_template/${name}`, + ignore: [404], + body, + }; + + return { clusterPromise: callCluster('transport.request', callClusterParams), name }; + } +} + +function buildComponentTemplates(registryElasticsearch: RegistryElasticsearch | undefined) { + let mappingsTemplate; + let settingsTemplate; + + if (registryElasticsearch && registryElasticsearch['index_template.mappings']) { + mappingsTemplate = { + template: { + mappings: { + ...registryElasticsearch['index_template.mappings'], + // temporary change until https://github.com/elastic/elasticsearch/issues/58956 is resolved + // hopefully we'll be able to remove the entire properties section once that issue is resolved + properties: { + // if the timestamp_field changes here: https://github.com/elastic/kibana/blob/master/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts#L309 + // we'll need to update this as well + '@timestamp': { + type: 'date', + }, + }, + }, + }, + }; + } + + if (registryElasticsearch && registryElasticsearch['index_template.settings']) { + settingsTemplate = { + template: { + settings: registryElasticsearch['index_template.settings'], + }, + }; + } + return { settingsTemplate, mappingsTemplate }; +} + +async function installDatasetComponentTemplates( + templateName: string, + registryElasticsearch: RegistryElasticsearch | undefined, + callCluster: CallESAsCurrentUser +) { + const templates: string[] = []; + const componentPromises: Array> = []; + + const compTemplates = buildComponentTemplates(registryElasticsearch); + + const mappings = putComponentTemplate( + compTemplates.mappingsTemplate, + `${templateName}-mappings`, + callCluster + ); + + const settings = putComponentTemplate( + compTemplates.settingsTemplate, + `${templateName}-settings`, + callCluster + ); + + if (mappings) { + templates.push(mappings.name); + componentPromises.push(mappings.clusterPromise); + } + + if (settings) { + templates.push(settings.name); + componentPromises.push(settings.clusterPromise); + } + + // TODO: Check return values for errors + await Promise.all(componentPromises); + return templates; +} + export async function installTemplate({ callCluster, fields, @@ -180,13 +278,22 @@ export async function installTemplate({ packageVersion, }); } + + const composedOfTemplates = await installDatasetComponentTemplates( + templateName, + dataset.elasticsearch, + callCluster + ); + const template = getTemplate({ type: dataset.type, templateName, mappings, pipelineName, packageName, + composedOfTemplates, }); + // TODO: Check return values for errors const callClusterParams: { method: string; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts index 73a6767f6b94..99e568bf771f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts @@ -29,10 +29,37 @@ test('get template', () => { templateName, packageName: 'nginx', mappings: { properties: {} }, + composedOfTemplates: [], }); expect(template.index_patterns).toStrictEqual([`${templateName}-*`]); }); +test('adds composed_of correctly', () => { + const composedOfTemplates = ['component1', 'component2']; + + const template = getTemplate({ + type: 'logs', + templateName: 'name', + packageName: 'nginx', + mappings: { properties: {} }, + composedOfTemplates, + }); + expect(template.composed_of).toStrictEqual(composedOfTemplates); +}); + +test('adds empty composed_of correctly', () => { + const composedOfTemplates: string[] = []; + + const template = getTemplate({ + type: 'logs', + templateName: 'name', + packageName: 'nginx', + mappings: { properties: {} }, + composedOfTemplates, + }); + expect(template.composed_of).toStrictEqual(composedOfTemplates); +}); + test('tests loading base.yml', () => { const ymlPath = path.join(__dirname, '../../fields/tests/base.yml'); const fieldsYML = readFileSync(ymlPath, 'utf-8'); @@ -45,6 +72,7 @@ test('tests loading base.yml', () => { templateName: 'foo', packageName: 'nginx', mappings, + composedOfTemplates: [], }); expect(template).toMatchSnapshot(path.basename(ymlPath)); @@ -62,6 +90,7 @@ test('tests loading coredns.logs.yml', () => { templateName: 'foo', packageName: 'coredns', mappings, + composedOfTemplates: [], }); expect(template).toMatchSnapshot(path.basename(ymlPath)); @@ -79,6 +108,7 @@ test('tests loading system.yml', () => { templateName: 'whatsthis', packageName: 'system', mappings, + composedOfTemplates: [], }); expect(template).toMatchSnapshot(path.basename(ymlPath)); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts index 2de378f71753..e7867532ed17 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts @@ -43,14 +43,16 @@ export function getTemplate({ mappings, pipelineName, packageName, + composedOfTemplates, }: { type: string; templateName: string; mappings: IndexTemplateMappings; pipelineName?: string | undefined; packageName: string; + composedOfTemplates: string[]; }): IndexTemplate { - const template = getBaseTemplate(type, templateName, mappings, packageName); + const template = getBaseTemplate(type, templateName, mappings, packageName, composedOfTemplates); if (pipelineName) { template.template.settings.index.default_pipeline = pipelineName; } @@ -244,7 +246,8 @@ function getBaseTemplate( type: string, templateName: string, mappings: IndexTemplateMappings, - packageName: string + packageName: string, + composedOfTemplates: string[] ): IndexTemplate { return { // This takes precedence over all index templates installed by ES by default (logs-*-* and metrics-*-*) @@ -308,6 +311,7 @@ function getBaseTemplate( data_stream: { timestamp_field: '@timestamp', }, + composed_of: composedOfTemplates, _meta: { package: { name: packageName, diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts new file mode 100644 index 000000000000..ae6493d4716e --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + SavedObject, + SavedObjectsBulkCreateObject, + SavedObjectsClientContract, +} from 'src/core/server'; +import * as Registry from '../../registry'; +import { AssetType, KibanaAssetType, AssetReference } from '../../../../types'; + +type SavedObjectToBe = Required & { type: AssetType }; +export type ArchiveAsset = Pick< + SavedObject, + 'id' | 'attributes' | 'migrationVersion' | 'references' +> & { + type: AssetType; +}; + +export async function getKibanaAsset(key: string) { + const buffer = Registry.getAsset(key); + + // cache values are buffers. convert to string / JSON + return JSON.parse(buffer.toString('utf8')); +} + +export function createSavedObjectKibanaAsset( + jsonAsset: ArchiveAsset, + pkgName: string +): SavedObjectToBe { + // convert that to an object + const asset = changeAssetIds(jsonAsset, pkgName); + + return { + type: asset.type, + id: asset.id, + attributes: asset.attributes, + references: asset.references || [], + migrationVersion: asset.migrationVersion || {}, + }; +} + +// modifies id property and the id property of references objects (not index-pattern) +// to be prepended with the package name to distinguish assets from Beats modules' assets +export const changeAssetIds = (asset: ArchiveAsset, pkgName: string): ArchiveAsset => { + const references = asset.references.map((ref) => { + if (ref.type === KibanaAssetType.indexPattern) return ref; + const id = getAssetId(ref.id, pkgName); + return { ...ref, id }; + }); + return { + ...asset, + id: getAssetId(asset.id, pkgName), + references, + }; +}; + +export const getAssetId = (id: string, pkgName: string) => { + return `${pkgName}-${id}`; +}; + +// TODO: make it an exhaustive list +// e.g. switch statement with cases for each enum key returning `never` for default case +export async function installKibanaAssets(options: { + savedObjectsClient: SavedObjectsClientContract; + pkgName: string; + paths: string[]; +}) { + const { savedObjectsClient, paths, pkgName } = options; + + // Only install Kibana assets during package installation. + const kibanaAssetTypes = Object.values(KibanaAssetType); + const installationPromises = kibanaAssetTypes.map((assetType) => + installKibanaSavedObjects({ savedObjectsClient, assetType, paths, pkgName }) + ); + + // installKibanaSavedObjects returns AssetReference[], so .map creates AssetReference[][] + // call .flat to flatten into one dimensional array + return Promise.all(installationPromises).then((results) => results.flat()); +} + +async function installKibanaSavedObjects({ + savedObjectsClient, + assetType, + paths, + pkgName, +}: { + savedObjectsClient: SavedObjectsClientContract; + assetType: KibanaAssetType; + paths: string[]; + pkgName: string; +}) { + const isSameType = (path: string) => assetType === Registry.pathParts(path).type; + const pathsOfType = paths.filter((path) => isSameType(path)); + const kibanaAssets = await Promise.all(pathsOfType.map((path) => getKibanaAsset(path))); + const toBeSavedObjects = await Promise.all( + kibanaAssets.map((asset) => createSavedObjectKibanaAsset(asset, pkgName)) + ); + + if (toBeSavedObjects.length === 0) { + return []; + } else { + const createResults = await savedObjectsClient.bulkCreate(toBeSavedObjects, { + overwrite: true, + }); + const createdObjects = createResults.saved_objects; + const installed = createdObjects.map(toAssetReference); + return installed; + } +} + +function toAssetReference({ id, type }: SavedObject) { + const reference: AssetReference = { id, type: type as KibanaAssetType }; + + return reference; +} diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/__snapshots__/install.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/__snapshots__/install.test.ts.snap new file mode 100644 index 000000000000..638ed4b6118c --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/__snapshots__/install.test.ts.snap @@ -0,0 +1,133 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`a kibana asset id and its reference ids are appended with package name changeAssetIds output matches snapshot: dashboard.json 1`] = ` +{ + "attributes": { + "description": "Overview dashboard for the Nginx integration in Metrics", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "highlightAll": true, + "query": { + "language": "kuery", + "query": "" + }, + "version": true + } + }, + "optionsJSON": { + "darkTheme": false, + "hidePanelTitles": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "1", + "w": 24, + "x": 24, + "y": 0 + }, + "panelIndex": "1", + "panelRefName": "panel_0", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "2", + "w": 24, + "x": 24, + "y": 12 + }, + "panelIndex": "2", + "panelRefName": "panel_1", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "3", + "w": 24, + "x": 0, + "y": 12 + }, + "panelIndex": "3", + "panelRefName": "panel_2", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "4", + "w": 24, + "x": 0, + "y": 0 + }, + "panelIndex": "4", + "panelRefName": "panel_3", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "5", + "w": 48, + "x": 0, + "y": 24 + }, + "panelIndex": "5", + "panelRefName": "panel_4", + "version": "7.3.0" + } + ], + "timeRestore": false, + "title": "[Metrics Nginx] Overview ECS", + "version": 1 + }, + "id": "nginx-023d2930-f1a5-11e7-a9ef-93c69af7b129-ecs", + "migrationVersion": { + "dashboard": "7.3.0" + }, + "references": [ + { + "id": "metrics-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "nginx-555df8a0-f1a1-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_0", + "type": "search" + }, + { + "id": "nginx-a1d92240-f1a1-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_1", + "type": "map" + }, + { + "id": "nginx-d763a570-f1a1-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_2", + "type": "dashboard" + }, + { + "id": "nginx-47a8e0f0-f1a4-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_3", + "type": "visualization" + }, + { + "id": "nginx-dcbffe30-f1a4-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_4", + "type": "visualization" + } + ], + "type": "dashboard" +} +`; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/dashboard.json b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/dashboard.json new file mode 100644 index 000000000000..e28a61ae5e18 --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/dashboard.json @@ -0,0 +1,129 @@ +{ + "attributes": { + "description": "Overview dashboard for the Nginx integration in Metrics", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [], + "highlightAll": true, + "query": { + "language": "kuery", + "query": "" + }, + "version": true + } + }, + "optionsJSON": { + "darkTheme": false, + "hidePanelTitles": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "1", + "w": 24, + "x": 24, + "y": 0 + }, + "panelIndex": "1", + "panelRefName": "panel_0", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "2", + "w": 24, + "x": 24, + "y": 12 + }, + "panelIndex": "2", + "panelRefName": "panel_1", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "3", + "w": 24, + "x": 0, + "y": 12 + }, + "panelIndex": "3", + "panelRefName": "panel_2", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "4", + "w": 24, + "x": 0, + "y": 0 + }, + "panelIndex": "4", + "panelRefName": "panel_3", + "version": "7.3.0" + }, + { + "embeddableConfig": {}, + "gridData": { + "h": 12, + "i": "5", + "w": 48, + "x": 0, + "y": 24 + }, + "panelIndex": "5", + "panelRefName": "panel_4", + "version": "7.3.0" + } + ], + "timeRestore": false, + "title": "[Metrics Nginx] Overview ECS", + "version": 1 + }, + "id": "023d2930-f1a5-11e7-a9ef-93c69af7b129-ecs", + "migrationVersion": { + "dashboard": "7.3.0" + }, + "references": [ + { + "id": "metrics-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "555df8a0-f1a1-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_0", + "type": "search" + }, + { + "id": "a1d92240-f1a1-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_1", + "type": "map" + }, + { + "id": "d763a570-f1a1-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_2", + "type": "dashboard" + }, + { + "id": "47a8e0f0-f1a4-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_3", + "type": "visualization" + }, + { + "id": "dcbffe30-f1a4-11e7-a9ef-93c69af7b129-ecs", + "name": "panel_4", + "type": "visualization" + } + ], + "type": "dashboard" +} \ No newline at end of file diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/install.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/install.test.ts new file mode 100644 index 000000000000..f9bc4cdbf203 --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/tests/install.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { readFileSync } from 'fs'; +import path from 'path'; +import { getAssetId, changeAssetIds } from '../install'; + +expect.addSnapshotSerializer({ + print(val) { + return JSON.stringify(val, null, 2); + }, + + test(val) { + return val; + }, +}); + +describe('a kibana asset id and its reference ids are appended with package name', () => { + const assetPath = path.join(__dirname, './dashboard.json'); + const kibanaAsset = JSON.parse(readFileSync(assetPath, 'utf-8')); + const pkgName = 'nginx'; + const modifiedAssetObject = changeAssetIds(kibanaAsset, pkgName); + + test('changeAssetIds output matches snapshot', () => { + expect(modifiedAssetObject).toMatchSnapshot(path.basename(assetPath)); + }); + + test('getAssetId', () => { + const id = '47a8e0f0-f1a4-11e7-a9ef-93c69af7b129-ecs'; + expect(getAssetId(id, pkgName)).toBe(`${pkgName}-${id}`); + }); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts deleted file mode 100644 index b623295c5e06..000000000000 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { SavedObject, SavedObjectsBulkCreateObject } from 'src/core/server'; -import { AssetType } from '../../../types'; -import * as Registry from '../registry'; - -type ArchiveAsset = Pick; -type SavedObjectToBe = Required & { type: AssetType }; - -export async function getObject(key: string) { - const buffer = Registry.getAsset(key); - - // cache values are buffers. convert to string / JSON - const json = buffer.toString('utf8'); - // convert that to an object - const asset: ArchiveAsset = JSON.parse(json); - - const { type, file } = Registry.pathParts(key); - const savedObject: SavedObjectToBe = { - type, - id: file.replace('.json', ''), - attributes: asset.attributes, - references: asset.references || [], - migrationVersion: asset.migrationVersion || {}, - }; - - return savedObject; -} diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts index b79f9178ad6a..53ffd5c6e703 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts @@ -23,7 +23,7 @@ export { SearchParams, } from './get'; -export { installKibanaAssets, installPackage, ensureInstalledPackage } from './install'; +export { installPackage, ensureInstalledPackage } from './install'; export { removeInstallation } from './remove'; type RequiredPackage = 'system' | 'endpoint'; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 910283549abd..8f73bc9a0276 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObject, SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsClientContract } from 'src/core/server'; import Boom from 'boom'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants'; import { AssetReference, Installation, - KibanaAssetType, CallESAsCurrentUser, DefaultPackages, ElasticsearchAssetType, @@ -18,7 +17,7 @@ import { } from '../../../types'; import { installIndexPatterns } from '../kibana/index_pattern/install'; import * as Registry from '../registry'; -import { getObject } from './get_objects'; +import { installKibanaAssets } from '../kibana/assets/install'; import { getInstallation, getInstallationObject, isRequiredPackage } from './index'; import { installTemplates } from '../elasticsearch/template/install'; import { generateESIndexPatterns } from '../elasticsearch/template/template'; @@ -121,7 +120,6 @@ export async function installPackage(options: { installKibanaAssets({ savedObjectsClient, pkgName, - pkgVersion, paths, }), installPipelines(registryPackageInfo, paths, callCluster), @@ -185,27 +183,6 @@ export async function installPackage(options: { }); } -// TODO: make it an exhaustive list -// e.g. switch statement with cases for each enum key returning `never` for default case -export async function installKibanaAssets(options: { - savedObjectsClient: SavedObjectsClientContract; - pkgName: string; - pkgVersion: string; - paths: string[]; -}) { - const { savedObjectsClient, paths } = options; - - // Only install Kibana assets during package installation. - const kibanaAssetTypes = Object.values(KibanaAssetType); - const installationPromises = kibanaAssetTypes.map(async (assetType) => - installKibanaSavedObjects({ savedObjectsClient, assetType, paths }) - ); - - // installKibanaSavedObjects returns AssetReference[], so .map creates AssetReference[][] - // call .flat to flatten into one dimensional array - return Promise.all(installationPromises).then((results) => results.flat()); -} - export async function saveInstallationReferences(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; @@ -240,34 +217,3 @@ export async function saveInstallationReferences(options: { return toSaveAssetRefs; } - -async function installKibanaSavedObjects({ - savedObjectsClient, - assetType, - paths, -}: { - savedObjectsClient: SavedObjectsClientContract; - assetType: KibanaAssetType; - paths: string[]; -}) { - const isSameType = (path: string) => assetType === Registry.pathParts(path).type; - const pathsOfType = paths.filter((path) => isSameType(path)); - const toBeSavedObjects = await Promise.all(pathsOfType.map(getObject)); - - if (toBeSavedObjects.length === 0) { - return []; - } else { - const createResults = await savedObjectsClient.bulkCreate(toBeSavedObjects, { - overwrite: true, - }); - const createdObjects = createResults.saved_objects; - const installed = createdObjects.map(toAssetReference); - return installed; - } -} - -function toAssetReference({ id, type }: SavedObject) { - const reference: AssetReference = { id, type: type as KibanaAssetType }; - - return reference; -} diff --git a/x-pack/plugins/ingest_manager/server/services/package_config.ts b/x-pack/plugins/ingest_manager/server/services/package_config.ts index 5a7546bfee2e..9fa51d025ad2 100644 --- a/x-pack/plugins/ingest_manager/server/services/package_config.ts +++ b/x-pack/plugins/ingest_manager/server/services/package_config.ts @@ -15,6 +15,7 @@ import { import { PACKAGE_CONFIG_SAVED_OBJECT_TYPE } from '../constants'; import { NewPackageConfig, + UpdatePackageConfig, PackageConfig, ListWithKuery, PackageConfigSOAttributes, @@ -60,6 +61,7 @@ class PackageConfigService { return { id: newSo.id, + version: newSo.version, ...newSo.attributes, }; } @@ -71,7 +73,7 @@ class PackageConfigService { options?: { user?: AuthenticatedUser } ): Promise { const isoDate = new Date().toISOString(); - const { saved_objects: newSos } = await soClient.bulkCreate>( + const { saved_objects: newSos } = await soClient.bulkCreate( packageConfigs.map((packageConfig) => ({ type: SAVED_OBJECT_TYPE, attributes: { @@ -98,6 +100,7 @@ class PackageConfigService { return newSos.map((newSo) => ({ id: newSo.id, + version: newSo.version, ...newSo.attributes, })); } @@ -117,6 +120,7 @@ class PackageConfigService { return { id: packageConfigSO.id, + version: packageConfigSO.version, ...packageConfigSO.attributes, }; } @@ -137,6 +141,7 @@ class PackageConfigService { return packageConfigSO.saved_objects.map((so) => ({ id: so.id, + version: so.version, ...so.attributes, })); } @@ -163,8 +168,9 @@ class PackageConfigService { }); return { - items: packageConfigs.saved_objects.map((packageConfigSO) => ({ + items: packageConfigs.saved_objects.map((packageConfigSO) => ({ id: packageConfigSO.id, + version: packageConfigSO.version, ...packageConfigSO.attributes, })), total: packageConfigs.total, @@ -176,21 +182,29 @@ class PackageConfigService { public async update( soClient: SavedObjectsClientContract, id: string, - packageConfig: NewPackageConfig, + packageConfig: UpdatePackageConfig, options?: { user?: AuthenticatedUser } ): Promise { const oldPackageConfig = await this.get(soClient, id); + const { version, ...restOfPackageConfig } = packageConfig; if (!oldPackageConfig) { throw new Error('Package config not found'); } - await soClient.update(SAVED_OBJECT_TYPE, id, { - ...packageConfig, - revision: oldPackageConfig.revision + 1, - updated_at: new Date().toISOString(), - updated_by: options?.user?.username ?? 'system', - }); + await soClient.update( + SAVED_OBJECT_TYPE, + id, + { + ...restOfPackageConfig, + revision: oldPackageConfig.revision + 1, + updated_at: new Date().toISOString(), + updated_by: options?.user?.username ?? 'system', + }, + { + version, + } + ); // Bump revision of associated agent config await agentConfigService.bumpRevision(soClient, packageConfig.config_id, { diff --git a/x-pack/plugins/ingest_manager/server/types/index.tsx b/x-pack/plugins/ingest_manager/server/types/index.tsx index 179474d31bc1..a559ca18cfed 100644 --- a/x-pack/plugins/ingest_manager/server/types/index.tsx +++ b/x-pack/plugins/ingest_manager/server/types/index.tsx @@ -21,6 +21,7 @@ export { PackageConfigInput, PackageConfigInputStream, NewPackageConfig, + UpdatePackageConfig, PackageConfigSOAttributes, FullAgentConfigInput, FullAgentConfig, @@ -40,6 +41,7 @@ export { PackageInfo, RegistryVarsEntry, Dataset, + RegistryElasticsearch, AssetReference, ElasticsearchAssetType, IngestAssetType, diff --git a/x-pack/plugins/ingest_manager/server/types/models/package_config.ts b/x-pack/plugins/ingest_manager/server/types/models/package_config.ts index 4b9718dfbe16..0823ccd85a32 100644 --- a/x-pack/plugins/ingest_manager/server/types/models/package_config.ts +++ b/x-pack/plugins/ingest_manager/server/types/models/package_config.ts @@ -66,7 +66,13 @@ export const NewPackageConfigSchema = schema.object({ ...PackageConfigBaseSchema, }); +export const UpdatePackageConfigSchema = schema.object({ + ...PackageConfigBaseSchema, + version: schema.maybe(schema.string()), +}); + export const PackageConfigSchema = schema.object({ ...PackageConfigBaseSchema, id: schema.string(), + version: schema.maybe(schema.string()), }); diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/package_config.ts b/x-pack/plugins/ingest_manager/server/types/rest_spec/package_config.ts index 7b7ae1957c15..630fb55f2654 100644 --- a/x-pack/plugins/ingest_manager/server/types/rest_spec/package_config.ts +++ b/x-pack/plugins/ingest_manager/server/types/rest_spec/package_config.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { NewPackageConfigSchema } from '../models'; +import { NewPackageConfigSchema, UpdatePackageConfigSchema } from '../models'; import { ListWithKuerySchema } from './index'; export const GetPackageConfigsRequestSchema = { @@ -23,7 +23,7 @@ export const CreatePackageConfigRequestSchema = { export const UpdatePackageConfigRequestSchema = { ...GetOnePackageConfigRequestSchema, - body: NewPackageConfigSchema, + body: UpdatePackageConfigSchema, }; export const DeletePackageConfigsRequestSchema = { diff --git a/x-pack/plugins/ml/common/util/validators.ts b/x-pack/plugins/ml/common/util/validators.ts index 5dcdec055310..c14c20917a13 100644 --- a/x-pack/plugins/ml/common/util/validators.ts +++ b/x-pack/plugins/ml/common/util/validators.ts @@ -67,6 +67,8 @@ export function requiredValidator() { export type ValidationResult = object | null; +export type MemoryInputValidatorResult = { invalidUnits: { allowedUnits: string } } | null; + export function memoryInputValidator(allowedUnits = ALLOWED_DATA_UNITS) { return (value: any) => { if (typeof value !== 'string' || value === '') { diff --git a/x-pack/plugins/ml/public/application/components/custom_selection_table/custom_selection_table.js b/x-pack/plugins/ml/public/application/components/custom_selection_table/custom_selection_table.js index c86b716b2f49..274a5ff0ffbb 100644 --- a/x-pack/plugins/ml/public/application/components/custom_selection_table/custom_selection_table.js +++ b/x-pack/plugins/ml/public/application/components/custom_selection_table/custom_selection_table.js @@ -45,6 +45,7 @@ function getError(error) { export function CustomSelectionTable({ checkboxDisabledCheck, columns, + currentPage = 0, filterDefaultFields, filters, items, @@ -52,6 +53,7 @@ export function CustomSelectionTable({ onTableChange, radioDisabledCheck, selectedIds, + setCurrentPaginationData, singleSelection, sortableProperties, tableItemId = 'id', @@ -80,7 +82,7 @@ export function CustomSelectionTable({ }, [selectedIds]); // eslint-disable-line useEffect(() => { - const tablePager = new Pager(currentItems.length, itemsPerPage); + const tablePager = new Pager(currentItems.length, itemsPerPage, currentPage); setPagerSettings({ itemsPerPage: itemsPerPage, firstItemIndex: tablePager.getFirstItemIndex(), @@ -124,6 +126,13 @@ export function CustomSelectionTable({ } } + if (setCurrentPaginationData) { + setCurrentPaginationData({ + pageIndex: pager.getCurrentPageIndex(), + itemsPerPage: pagerSettings.itemsPerPage, + }); + } + onTableChange(currentSelected); } @@ -389,6 +398,7 @@ export function CustomSelectionTable({ CustomSelectionTable.propTypes = { checkboxDisabledCheck: PropTypes.func, columns: PropTypes.array.isRequired, + currentPage: PropTypes.number, filterDefaultFields: PropTypes.array, filters: PropTypes.array, items: PropTypes.array.isRequired, @@ -396,6 +406,7 @@ CustomSelectionTable.propTypes = { onTableChange: PropTypes.func.isRequired, radioDisabledCheck: PropTypes.func, selectedId: PropTypes.array, + setCurrentPaginationData: PropTypes.func, singleSelection: PropTypes.bool, sortableProperties: PropTypes.object, tableItemId: PropTypes.string, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 5715687402bc..aa637f71db1c 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -327,9 +327,14 @@ export const isClassificationEvaluateResponse = ( ); }; +export interface UpdateDataFrameAnalyticsConfig { + allow_lazy_start?: string; + description?: string; + model_memory_limit?: string; +} + export interface DataFrameAnalyticsConfig { id: DataFrameAnalyticsId; - // Description attribute is not supported yet description?: string; dest: { index: IndexName; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts index 58343e26153c..65531009e443 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts @@ -13,6 +13,7 @@ export { useRefreshAnalyticsList, DataFrameAnalyticsId, DataFrameAnalyticsConfig, + UpdateDataFrameAnalyticsConfig, IndexName, IndexPattern, REFRESH_ANALYTICS_LIST_STATE, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts index 2570dd20416b..fde1b2610650 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts @@ -24,6 +24,7 @@ export const useResultsViewConfig = (jobId: string) => { const mlContext = useMlContext(); const [indexPattern, setIndexPattern] = useState(undefined); const [isInitialized, setIsInitialized] = useState(false); + const [needsDestIndexPattern, setNeedsDestIndexPattern] = useState(false); const [isLoadingJobConfig, setIsLoadingJobConfig] = useState(false); const [jobConfig, setJobConfig] = useState(undefined); const [jobCapsServiceErrorMessage, setJobCapsServiceErrorMessage] = useState( @@ -68,6 +69,7 @@ export const useResultsViewConfig = (jobId: string) => { } if (indexP === undefined) { + setNeedsDestIndexPattern(true); const sourceIndex = jobConfigUpdate.source.index[0]; const sourceIndexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex; indexP = await mlContext.indexPatterns.get(sourceIndexPatternId); @@ -100,5 +102,6 @@ export const useResultsViewConfig = (jobId: string) => { jobConfig, jobConfigErrorMessage, jobStatus, + needsDestIndexPattern, }; }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step.tsx index f957dcab2e87..b16300a448a7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step.tsx @@ -19,14 +19,19 @@ export const AdvancedStep: FC = ({ setCurrentStep, stepActivated, }) => { + const showForm = step === ANALYTICS_STEPS.ADVANCED; + const showDetails = step !== ANALYTICS_STEPS.ADVANCED && stepActivated === true; + + const dataTestSubj = `mlAnalyticsCreateJobWizardAdvancedStep${showForm ? ' active' : ''}${ + showDetails ? ' summary' : '' + }`; + return ( - - {step === ANALYTICS_STEPS.ADVANCED && ( + + {showForm && ( )} - {step !== ANALYTICS_STEPS.ADVANCED && stepActivated === true && ( - - )} + {showDetails && } ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx index bc9bb0cce5ae..21b0d3d7dd89 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx @@ -47,7 +47,7 @@ export const AdvancedStepForm: FC = ({ const [advancedParamErrors, setAdvancedParamErrors] = useState({}); const [fetchingAdvancedParamErrors, setFetchingAdvancedParamErrors] = useState(false); - const { setFormState } = actions; + const { setEstimatedModelMemoryLimit, setFormState } = actions; const { form, isJobCreated } = state; const { computeFeatureInfluence, @@ -87,10 +87,15 @@ export const AdvancedStepForm: FC = ({ useEffect(() => { setFetchingAdvancedParamErrors(true); (async function () { - const { success, errorMessage } = await fetchExplainData(form); + const { success, errorMessage, expectedMemory } = await fetchExplainData(form); const paramErrors: AdvancedParamErrors = {}; - if (!success) { + if (success) { + if (modelMemoryLimit !== expectedMemory) { + setEstimatedModelMemoryLimit(expectedMemory); + setFormState({ modelMemoryLimit: expectedMemory }); + } + } else { // Check which field is invalid Object.values(ANALYSIS_ADVANCED_FIELDS).forEach((param) => { if (errorMessage.includes(`[${param}]`)) { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx index c71e7e73b13d..def6acdae14e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, Fragment, memo, useEffect, useState } from 'react'; +import React, { FC, Fragment, useEffect, useState } from 'react'; import { EuiCallOut, EuiFormRow, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; // @ts-ignore no declaration import { LEFT_ALIGNMENT, CENTER_ALIGNMENT, SortableProperties } from '@elastic/eui/lib/services'; @@ -14,6 +14,13 @@ import { FieldSelectionItem } from '../../../../common/analytics'; // @ts-ignore could not find declaration file import { CustomSelectionTable } from '../../../../../components/custom_selection_table'; +const minimumFieldsMessage = i18n.translate( + 'xpack.ml.dataframe.analytics.create.analysisFieldsTable.minimumFieldsMessage', + { + defaultMessage: 'At least one field must be selected.', + } +); + const columns = [ { id: 'checkbox', @@ -22,9 +29,12 @@ const columns = [ width: '32px', }, { - label: i18n.translate('xpack.ml.dataframe.analytics.create.analyticsTable.fieldNameColumn', { - defaultMessage: 'Field name', - }), + label: i18n.translate( + 'xpack.ml.dataframe.analytics.create.analysisFieldsTable.fieldNameColumn', + { + defaultMessage: 'Field name', + } + ), id: 'name', isSortable: true, alignment: LEFT_ALIGNMENT, @@ -68,140 +78,154 @@ const columns = [ ]; const checkboxDisabledCheck = (item: FieldSelectionItem) => - (item.is_included === false && !item.reason?.includes('in excludes list')) || - item.is_required === true; + item.is_required === true || (item.reason && item.reason.includes('unsupported type')); -export const MemoizedAnalysisFieldsTable: FC<{ - excludes: string[]; +export const AnalysisFieldsTable: FC<{ + dependentVariable?: string; + includes: string[]; loadingItems: boolean; - setFormState: any; + setFormState: React.Dispatch>; tableItems: FieldSelectionItem[]; -}> = memo( - ({ excludes, loadingItems, setFormState, tableItems }) => { - const [sortableProperties, setSortableProperties] = useState(); - const [currentSelection, setCurrentSelection] = useState([]); +}> = ({ dependentVariable, includes, loadingItems, setFormState, tableItems }) => { + const [sortableProperties, setSortableProperties] = useState(); + const [currentPaginationData, setCurrentPaginationData] = useState<{ + pageIndex: number; + itemsPerPage: number; + }>({ pageIndex: 0, itemsPerPage: 5 }); + const [minimumFieldsRequiredMessage, setMinimumFieldsRequiredMessage] = useState< + undefined | string + >(undefined); - useEffect(() => { - if (excludes.length > 0) { - setCurrentSelection(excludes); - } - }, [tableItems]); + useEffect(() => { + if (includes.length === 0 && tableItems.length > 0) { + const includedFields: string[] = []; + tableItems.forEach((field) => { + if (field.is_included === true) { + includedFields.push(field.name); + } + }); + setFormState({ includes: includedFields }); + } else if (includes.length > 0) { + setFormState({ includes }); + } + setMinimumFieldsRequiredMessage(undefined); + }, [tableItems]); - // Only set form state on unmount to prevent re-renders due to props changing if exludes was updated on each selection - useEffect(() => { - return () => { - setFormState({ excludes: currentSelection }); - }; - }, [currentSelection]); + useEffect(() => { + let sortablePropertyItems = []; + const defaultSortProperty = 'name'; - useEffect(() => { - let sortablePropertyItems = []; - const defaultSortProperty = 'name'; - - sortablePropertyItems = [ - { - name: 'name', - getValue: (item: any) => item.name.toLowerCase(), - isAscending: true, - }, - { - name: 'is_included', - getValue: (item: any) => item.is_included, - isAscending: true, - }, - { - name: 'is_required', - getValue: (item: any) => item.is_required, - isAscending: true, - }, - ]; - const sortableProps = new SortableProperties(sortablePropertyItems, defaultSortProperty); - - setSortableProperties(sortableProps); - }, []); - - const filters = [ + sortablePropertyItems = [ { - type: 'field_value_selection', - field: 'is_included', - name: i18n.translate('xpack.ml.dataframe.analytics.create.excludedFilterLabel', { - defaultMessage: 'Is included', - }), - multiSelect: false, - options: [ - { - value: true, - view: ( - - {i18n.translate('xpack.ml.dataframe.analytics.create.isIncludedOption', { - defaultMessage: 'Yes', - })} - - ), - }, - { - value: false, - view: ( - - {i18n.translate('xpack.ml.dataframe.analytics.create.isNotIncludedOption', { - defaultMessage: 'No', - })} - - ), - }, - ], + name: 'name', + getValue: (item: any) => item.name.toLowerCase(), + isAscending: true, + }, + { + name: 'is_included', + getValue: (item: any) => item.is_included, + isAscending: true, + }, + { + name: 'is_required', + getValue: (item: any) => item.is_required, + isAscending: true, }, ]; + const sortableProps = new SortableProperties(sortablePropertyItems, defaultSortProperty); - return ( - - + + + + {tableItems.length > 0 && minimumFieldsRequiredMessage === undefined && ( + + {i18n.translate('xpack.ml.dataframe.analytics.create.includedFieldsCount', { + defaultMessage: + '{numFields, plural, one {# field} other {# fields}} included in the analysis', + values: { numFields: includes.length }, + })} + + )} + {tableItems.length === 0 && ( + - - - {tableItems.length === 0 && ( - - - - )} - {tableItems.length > 0 && ( - - { - setCurrentSelection(selection); - }} - selectedIds={currentSelection} - singleSelection={false} - sortableProperties={sortableProperties} - tableItemId={'name'} - /> - - )} - - - ); - }, - (prevProps, nextProps) => prevProps.tableItems.length === nextProps.tableItems.length -); + +
+ )} + {tableItems.length > 0 && ( + + { + // dependent variable must always be in includes + if ( + dependentVariable !== undefined && + dependentVariable !== '' && + selection.length === 0 + ) { + selection = [dependentVariable]; + } + // If nothing selected show minimum fields required message and don't update form yet + if (selection.length === 0) { + setMinimumFieldsRequiredMessage(minimumFieldsMessage); + } else { + setMinimumFieldsRequiredMessage(undefined); + setFormState({ includes: selection }); + } + }} + selectedIds={includes} + setCurrentPaginationData={setCurrentPaginationData} + singleSelection={false} + sortableProperties={sortableProperties} + tableItemId={'name'} + /> + + )} + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step.tsx index 220910535aaf..d818117c9d78 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step.tsx @@ -19,17 +19,19 @@ export const ConfigurationStep: FC = ({ step, stepActivated, }) => { + const showForm = step === ANALYTICS_STEPS.CONFIGURATION; + const showDetails = step !== ANALYTICS_STEPS.CONFIGURATION && stepActivated === true; + + const dataTestSubj = `mlAnalyticsCreateJobWizardConfigurationStep${showForm ? ' active' : ''}${ + showDetails ? ' summary' : '' + }`; + return ( - - {step === ANALYTICS_STEPS.CONFIGURATION && ( + + {showForm && ( )} - {step !== ANALYTICS_STEPS.CONFIGURATION && stepActivated === true && ( - - )} + {showDetails && } ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx index 6603af9aa302..193d7dcce7f5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx @@ -21,6 +21,8 @@ import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics'; import { useMlContext } from '../../../../../contexts/ml'; import { ANALYTICS_STEPS } from '../../page'; +const MAX_INCLUDES_LENGTH = 5; + interface Props { setCurrentStep: React.Dispatch>; state: State; @@ -30,7 +32,7 @@ export const ConfigurationStepDetails: FC = ({ setCurrentStep, state }) = const mlContext = useMlContext(); const { currentIndexPattern } = mlContext; const { form, isJobCreated } = state; - const { dependentVariable, excludes, jobConfigQueryString, jobType, trainingPercent } = form; + const { dependentVariable, includes, jobConfigQueryString, jobType, trainingPercent } = form; const isJobTypeWithDepVar = jobType === ANALYSIS_CONFIG_TYPE.REGRESSION || jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION; @@ -61,10 +63,15 @@ export const ConfigurationStepDetails: FC = ({ setCurrentStep, state }) = const detailsThirdCol = [ { - title: i18n.translate('xpack.ml.dataframe.analytics.create.configDetails.excludedFields', { - defaultMessage: 'Excluded fields', + title: i18n.translate('xpack.ml.dataframe.analytics.create.configDetails.includedFields', { + defaultMessage: 'Included fields', }), - description: excludes.length > 0 ? excludes.join(', ') : UNSET_CONFIG_ITEM, + description: + includes.length > MAX_INCLUDES_LENGTH + ? `${includes.slice(0, MAX_INCLUDES_LENGTH).join(', ')} ... (and ${ + includes.length - MAX_INCLUDES_LENGTH + } more)` + : includes.join(', '), }, ]; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx index 76378dc372f1..b83dd2e4329e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx @@ -39,7 +39,7 @@ import { ANALYTICS_STEPS } from '../../page'; import { ContinueButton } from '../continue_button'; import { JobType } from './job_type'; import { SupportedFieldsMessage } from './supported_fields_message'; -import { MemoizedAnalysisFieldsTable } from './analysis_fields_table'; +import { AnalysisFieldsTable } from './analysis_fields_table'; import { DataGrid } from '../../../../../components/data_grid'; import { fetchExplainData } from '../shared'; import { useIndexData } from '../../hooks'; @@ -49,7 +49,8 @@ import { useSavedSearch } from './use_saved_search'; const requiredFieldsErrorText = i18n.translate( 'xpack.ml.dataframe.analytics.createWizard.requiredFieldsErrorMessage', { - defaultMessage: 'At least one field must be included in the analysis.', + defaultMessage: + 'At least one field must be included in the analysis in addition to the dependent variable.', } ); @@ -69,17 +70,20 @@ export const ConfigurationStepForm: FC = ({ const [dependentVariableOptions, setDependentVariableOptions] = useState< EuiComboBoxOptionOption[] >([]); - const [excludesTableItems, setExcludesTableItems] = useState([]); + const [includesTableItems, setIncludesTableItems] = useState([]); const [maxDistinctValuesError, setMaxDistinctValuesError] = useState( undefined ); + const [unsupportedFieldsError, setUnsupportedFieldsError] = useState( + undefined + ); const { setEstimatedModelMemoryLimit, setFormState } = actions; const { estimatedModelMemoryLimit, form, isJobCreated, requestMessages } = state; const firstUpdate = useRef(true); const { dependentVariable, - excludes, + includes, jobConfigQuery, jobConfigQueryString, jobType, @@ -117,7 +121,8 @@ export const ConfigurationStepForm: FC = ({ dependentVariableEmpty || jobType === undefined || maxDistinctValuesError !== undefined || - requiredFieldsError !== undefined; + requiredFieldsError !== undefined || + unsupportedFieldsError !== undefined; const loadDepVarOptions = async (formState: State['form']) => { setLoadingDepVarOptions(true); @@ -187,7 +192,8 @@ export const ConfigurationStepForm: FC = ({ setLoadingFieldOptions(false); setFieldOptionsFetchFail(false); setMaxDistinctValuesError(undefined); - setExcludesTableItems(fieldSelection ? fieldSelection : []); + setUnsupportedFieldsError(undefined); + setIncludesTableItems(fieldSelection ? fieldSelection : []); setFormState({ ...(shouldUpdateModelMemoryLimit ? { modelMemoryLimit: expectedMemory } : {}), requiredFieldsError: !hasRequiredFields ? requiredFieldsErrorText : undefined, @@ -200,6 +206,7 @@ export const ConfigurationStepForm: FC = ({ } } else { let maxDistinctValuesErrorMessage; + let unsupportedFieldsErrorMessage; if ( jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION && errorMessage.includes('status_exception') && @@ -208,6 +215,10 @@ export const ConfigurationStepForm: FC = ({ maxDistinctValuesErrorMessage = errorMessage; } + if (errorMessage.includes('status_exception') && errorMessage.includes('unsupported type')) { + unsupportedFieldsErrorMessage = errorMessage; + } + if ( errorMessage.includes('status_exception') && errorMessage.includes('Unable to estimate memory usage as no documents') @@ -231,6 +242,7 @@ export const ConfigurationStepForm: FC = ({ setLoadingFieldOptions(false); setFieldOptionsFetchFail(true); setMaxDistinctValuesError(maxDistinctValuesErrorMessage); + setUnsupportedFieldsError(unsupportedFieldsErrorMessage); setFormState({ ...(shouldUpdateModelMemoryLimit ? { modelMemoryLimit: fallbackModelMemoryLimit } : {}), }); @@ -267,7 +279,7 @@ export const ConfigurationStepForm: FC = ({ return () => { debouncedGetExplainData.cancel(); }; - }, [jobType, dependentVariable, trainingPercent, JSON.stringify(excludes), jobConfigQueryString]); + }, [jobType, dependentVariable, trainingPercent, JSON.stringify(includes), jobConfigQueryString]); return ( @@ -392,21 +404,32 @@ export const ConfigurationStepForm: FC = ({ )} - diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/job_type.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/job_type.tsx index f31c9cd28f65..da547ee6255a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/job_type.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/job_type.tsx @@ -71,7 +71,7 @@ export const JobType: FC = ({ type, setFormState }) => { setFormState({ previousJobType: type, jobType: value, - excludes: [], + includes: [], requiredFieldsError: undefined, }); }} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx index 0d1690cf1794..8ad49b84134c 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, Fragment, useState } from 'react'; +import React, { FC, useState } from 'react'; import { EuiButton, EuiCheckbox, @@ -45,7 +45,7 @@ export const CreateStep: FC = ({ actions, state, step }) => { }; return ( - +
{!isJobCreated && !isJobStarted && ( @@ -88,6 +88,6 @@ export const CreateStep: FC = ({ actions, state, step }) => { {isJobCreated === true && showProgress && } {isJobCreated === true && } - +
); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step.tsx index a40813ed2fc3..2e027b7b67e5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step.tsx @@ -19,14 +19,19 @@ export const DetailsStep: FC = ({ step, stepActivated, }) => { + const showForm = step === ANALYTICS_STEPS.DETAILS; + const showDetails = step !== ANALYTICS_STEPS.DETAILS && stepActivated === true; + + const dataTestSubj = `mlAnalyticsCreateJobWizardDetailsStep${showForm ? ' active' : ''}${ + showDetails ? ' summary' : '' + }`; + return ( - - {step === ANALYTICS_STEPS.DETAILS && ( + + {showForm && ( )} - {step !== ANALYTICS_STEPS.DETAILS && stepActivated === true && ( - - )} + {showDetails && } ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx index 67f8472e7ad1..d846ae95c2c7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/details_step/details_step_form.tsx @@ -5,7 +5,15 @@ */ import React, { FC, Fragment, useRef } from 'react'; -import { EuiFieldText, EuiFormRow, EuiLink, EuiSpacer, EuiSwitch, EuiTextArea } from '@elastic/eui'; +import { + EuiFieldText, + EuiFormRow, + EuiLink, + EuiSpacer, + EuiSwitch, + EuiText, + EuiTextArea, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useMlKibana } from '../../../../../contexts/kibana'; @@ -188,15 +196,32 @@ export const DetailsStepForm: FC = ({ /> + {i18n.translate( + 'xpack.ml.dataframe.analytics.create.shouldCreateIndexPatternMessage', + { + defaultMessage: + 'You may not be able to view job results if an index pattern is not created for the destination index.', + } + )} + , + ] + : []), + ]} > = ({ jobId }) => { /> ), status: currentStep >= ANALYTICS_STEPS.ADVANCED ? undefined : ('incomplete' as EuiStepStatus), - 'data-test-subj': 'mlAnalyticsCreateJobWizardAdvancedStep', }, { title: i18n.translate('xpack.ml.dataframe.analytics.creation.detailsStepTitle', { @@ -124,7 +123,6 @@ export const Page: FC = ({ jobId }) => { /> ), status: currentStep >= ANALYTICS_STEPS.DETAILS ? undefined : ('incomplete' as EuiStepStatus), - 'data-test-subj': 'mlAnalyticsCreateJobWizardDetailsStep', }, { title: i18n.translate('xpack.ml.dataframe.analytics.creation.createStepTitle', { @@ -132,7 +130,6 @@ export const Page: FC = ({ jobId }) => { }), children: , status: currentStep >= ANALYTICS_STEPS.CREATE ? undefined : ('incomplete' as EuiStepStatus), - 'data-test-subj': 'mlAnalyticsCreateJobWizardCreateStep', }, ]; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx index 1986c486974c..34ff36c59fa6 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx @@ -38,6 +38,7 @@ export const ExplorationPageWrapper: FC = ({ jobId, title, EvaluatePanel jobConfig, jobConfigErrorMessage, jobStatus, + needsDestIndexPattern, } = useResultsViewConfig(jobId); const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); @@ -64,9 +65,10 @@ export const ExplorationPageWrapper: FC = ({ jobId, title, EvaluatePanel indexPattern !== undefined && isInitialized === true && ( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx index 941fbefd7808..755bac699ce4 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx @@ -33,6 +33,7 @@ import { getTaskStateBadge } from '../../../analytics_management/components/anal import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; import { ExplorationTitle } from '../exploration_title'; import { ExplorationQueryBar } from '../exploration_query_bar'; +import { IndexPatternPrompt } from '../index_pattern_prompt'; import { useExplorationResults } from './use_exploration_results'; @@ -55,12 +56,20 @@ interface Props { indexPattern: IndexPattern; jobConfig: DataFrameAnalyticsConfig; jobStatus?: DATA_FRAME_TASK_STATE; + needsDestIndexPattern: boolean; setEvaluateSearchQuery: React.Dispatch>; title: string; } export const ExplorationResultsTable: FC = React.memo( - ({ indexPattern, jobConfig, jobStatus, setEvaluateSearchQuery, title }) => { + ({ + indexPattern, + jobConfig, + jobStatus, + needsDestIndexPattern, + setEvaluateSearchQuery, + title, + }) => { const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); useEffect(() => { @@ -119,6 +128,7 @@ export const ExplorationResultsTable: FC = React.memo( id="mlDataFrameAnalyticsTableResultsPanel" data-test-subj="mlDFAnalyticsExplorationTablePanel" > + {needsDestIndexPattern && } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index.ts new file mode 100644 index 000000000000..0b012794c942 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { IndexPatternPrompt } from './index_pattern_prompt'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx new file mode 100644 index 000000000000..f478dc639da2 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/index_pattern_prompt/index_pattern_prompt.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; +import { useMlKibana } from '../../../../../contexts/kibana'; + +interface Props { + destIndex: string; +} + +export const IndexPatternPrompt: FC = ({ destIndex }) => { + const { + services: { + http: { basePath }, + }, + } = useMlKibana(); + + return ( + <> + + + + + ), + }} + /> + + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 0b29b7f43bfc..9afb50c11fad 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -33,6 +33,7 @@ import { getTaskStateBadge } from '../../../analytics_management/components/anal import { ExplorationQueryBar } from '../exploration_query_bar'; import { ExplorationTitle } from '../exploration_title'; +import { IndexPatternPrompt } from '../index_pattern_prompt'; import { getFeatureCount } from './common'; import { useOutlierData } from './use_outlier_data'; @@ -49,7 +50,7 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = values: { jobId }, }); - const { indexPattern, jobConfig, jobStatus } = useResultsViewConfig(jobId); + const { indexPattern, jobConfig, jobStatus, needsDestIndexPattern } = useResultsViewConfig(jobId); const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); const outlierData = useOutlierData(indexPattern, jobConfig, searchQuery); @@ -82,6 +83,9 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = return ( + {jobConfig !== undefined && needsDestIndexPattern && ( + + )} { }, analyzed_fields: { includes: [], - excludes: ['id', 'outlier'], + excludes: [], }, model_memory_limit: '1mb', allow_lazy_start: false, @@ -96,7 +96,7 @@ describe('Analytics job clone action', () => { }, }, analyzed_fields: { - includes: [], + includes: ['included_field', 'other_included_field'], excludes: [], }, model_memory_limit: '150mb', @@ -140,6 +140,40 @@ describe('Analytics job clone action', () => { expect(isAdvancedConfig(advancedClassificationJob)).toBe(true); }); + test('should detect advanced classification job with excludes set', () => { + const advancedClassificationJob = { + description: "Classification job with 'bank-marketing' dataset", + source: { + index: ['bank-marketing'], + query: { + match_all: {}, + }, + }, + dest: { + index: 'dest_bank_1', + results_field: 'ml', + }, + analysis: { + classification: { + dependent_variable: 'y', + num_top_classes: 2, + num_top_feature_importance_values: 4, + prediction_field_name: 'y_prediction', + training_percent: 2, + randomize_seed: 6233212276062807000, + }, + }, + analyzed_fields: { + includes: [], + excludes: ['excluded_field', 'other_excluded_field'], + }, + model_memory_limit: '350mb', + allow_lazy_start: false, + }; + + expect(isAdvancedConfig(advancedClassificationJob)).toBe(true); + }); + test('should detect advanced regression job', () => { const advancedRegressionJob = { description: "Outlier detection job with 'glass' dataset", @@ -161,7 +195,7 @@ describe('Analytics job clone action', () => { }, analyzed_fields: { includes: [], - excludes: ['id', 'outlier'], + excludes: [], }, model_memory_limit: '1mb', allow_lazy_start: false, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx index f184c7c5d874..bff54bc28329 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx @@ -217,11 +217,11 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo analyzed_fields: { excludes: { optional: true, - formKey: 'excludes', defaultValue: [], }, includes: { optional: true, + formKey: 'includes', defaultValue: [], }, }, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_edit.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_edit.tsx new file mode 100644 index 000000000000..041b52d0322c --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_edit.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, FC } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; + +import { checkPermission } from '../../../../../capabilities/check_capabilities'; +import { DataFrameAnalyticsListRow } from './common'; + +import { EditAnalyticsFlyout } from './edit_analytics_flyout'; + +interface EditActionProps { + item: DataFrameAnalyticsListRow; +} + +export const EditAction: FC = ({ item }) => { + const canCreateDataFrameAnalytics: boolean = checkPermission('canCreateDataFrameAnalytics'); + + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + const closeFlyout = () => setIsFlyoutVisible(false); + const showFlyout = () => setIsFlyoutVisible(true); + + const buttonEditText = i18n.translate('xpack.ml.dataframe.analyticsList.editActionName', { + defaultMessage: 'Edit', + }); + + const editButton = ( + + {buttonEditText} + + ); + + if (!canCreateDataFrameAnalytics) { + return ( + + {editButton} + + ); + } + + return ( + <> + {editButton} + {isFlyoutVisible && } + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx index b47b23f66853..b03a3a4c4edb 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx @@ -27,6 +27,7 @@ import { getResultsUrl, isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } import { stopAnalytics } from '../../services/analytics_service'; import { StartAction } from './action_start'; +import { EditAction } from './action_edit'; import { DeleteAction } from './action_delete'; interface Props { @@ -133,6 +134,11 @@ export const getActions = ( return stopButton; }, }, + { + render: (item: DataFrameAnalyticsListRow) => { + return ; + }, + }, { render: (item: DataFrameAnalyticsListRow) => { return ; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/edit_analytics_flyout.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/edit_analytics_flyout.tsx new file mode 100644 index 000000000000..b6aed9321e4e --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/edit_analytics_flyout.tsx @@ -0,0 +1,270 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC, useEffect, useState } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { + EuiButton, + EuiButtonEmpty, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiForm, + EuiFormRow, + EuiOverlayMask, + EuiSelect, + EuiTitle, +} from '@elastic/eui'; + +import { useMlKibana } from '../../../../../contexts/kibana'; +import { ml } from '../../../../../services/ml_api_service'; +import { + memoryInputValidator, + MemoryInputValidatorResult, +} from '../../../../../../../common/util/validators'; +import { extractErrorMessage } from '../../../../../../../common/util/errors'; +import { DataFrameAnalyticsListRow, DATA_FRAME_TASK_STATE } from './common'; +import { + useRefreshAnalyticsList, + UpdateDataFrameAnalyticsConfig, +} from '../../../../common/analytics'; + +interface EditAnalyticsJobFlyoutProps { + closeFlyout: () => void; + item: DataFrameAnalyticsListRow; +} + +let mmLValidator: (value: any) => MemoryInputValidatorResult; + +export const EditAnalyticsFlyout: FC = ({ closeFlyout, item }) => { + const { id: jobId, config } = item; + const { state } = item.stats; + const initialAllowLazyStart = + config.allow_lazy_start !== undefined ? String(config.allow_lazy_start) : ''; + + const [allowLazyStart, setAllowLazyStart] = useState(initialAllowLazyStart); + const [description, setDescription] = useState(config.description || ''); + const [modelMemoryLimit, setModelMemoryLimit] = useState(config.model_memory_limit); + const [mmlValidationError, setMmlValidationError] = useState(); + + const { + services: { notifications }, + } = useMlKibana(); + const { refresh } = useRefreshAnalyticsList(); + + // Disable if mml is not valid + const updateButtonDisabled = mmlValidationError !== undefined; + + useEffect(() => { + if (mmLValidator === undefined) { + mmLValidator = memoryInputValidator(); + } + // validate mml and create validation message + if (modelMemoryLimit !== '') { + const validationResult = mmLValidator(modelMemoryLimit); + if (validationResult !== null && validationResult.invalidUnits) { + setMmlValidationError( + i18n.translate('xpack.ml.dataframe.analytics.create.modelMemoryUnitsInvalidError', { + defaultMessage: 'Model memory limit data unit unrecognized. It must be {str}', + values: { str: validationResult.invalidUnits.allowedUnits }, + }) + ); + } else { + setMmlValidationError(undefined); + } + } else { + setMmlValidationError( + i18n.translate('xpack.ml.dataframe.analytics.create.modelMemoryEmptyError', { + defaultMessage: 'Model memory limit must not be empty', + }) + ); + } + }, [modelMemoryLimit]); + + const onSubmit = async () => { + const updateConfig: UpdateDataFrameAnalyticsConfig = Object.assign( + { + allow_lazy_start: allowLazyStart, + description, + }, + modelMemoryLimit && { model_memory_limit: modelMemoryLimit } + ); + + try { + await ml.dataFrameAnalytics.updateDataFrameAnalytics(jobId, updateConfig); + notifications.toasts.addSuccess( + i18n.translate('xpack.ml.dataframe.analyticsList.editFlyoutSuccessMessage', { + defaultMessage: 'Analytics job {jobId} has been updated.', + values: { jobId }, + }) + ); + refresh(); + closeFlyout(); + } catch (e) { + // eslint-disable-next-line + console.error(e); + + notifications.toasts.addDanger({ + title: i18n.translate('xpack.ml.dataframe.analyticsList.editFlyoutErrorMessage', { + defaultMessage: 'Could not save changes to analytics job {jobId}', + values: { + jobId, + }, + }), + text: extractErrorMessage(e), + }); + } + }; + + return ( + + + + +

+ {i18n.translate('xpack.ml.dataframe.analyticsList.editFlyoutTitle', { + defaultMessage: 'Edit {jobId}', + values: { + jobId, + }, + })} +

+
+
+ + + + ) => + setAllowLazyStart(e.target.value) + } + /> + + + setDescription(e.target.value)} + aria-label={i18n.translate( + 'xpack.ml.dataframe.analyticsList.editFlyout.descriptionAriaLabel', + { + defaultMessage: 'Update the job description.', + } + )} + /> + + + setModelMemoryLimit(e.target.value)} + aria-label={i18n.translate( + 'xpack.ml.dataframe.analyticsList.editFlyout.modelMemoryLimitAriaLabel', + { + defaultMessage: 'Update the model memory limit.', + } + )} + /> + + + + + + + + {i18n.translate('xpack.ml.dataframe.analyticsList.editFlyoutCancelButtonText', { + defaultMessage: 'Cancel', + })} + + + + + {i18n.translate('xpack.ml.dataframe.analyticsList.editFlyoutUpdateButtonText', { + defaultMessage: 'Update', + })} + + + + +
+
+ ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts index 8bace7b4f595..81d35679443b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts @@ -116,7 +116,7 @@ export const validateNumTopFeatureImportanceValues = ( }; export const validateAdvancedEditor = (state: State): State => { - const { jobIdEmpty, jobIdValid, jobIdExists, jobType, createIndexPattern, excludes } = state.form; + const { jobIdEmpty, jobIdValid, jobIdExists, jobType, createIndexPattern, includes } = state.form; const { jobConfig } = state; state.advancedEditorMessages = []; @@ -152,7 +152,7 @@ export const validateAdvancedEditor = (state: State): State => { } let dependentVariableEmpty = false; - let excludesValid = true; + let includesValid = true; let trainingPercentValid = true; let numTopFeatureImportanceValuesValid = true; @@ -170,14 +170,19 @@ export const validateAdvancedEditor = (state: State): State => { const dependentVariableName = getDependentVar(jobConfig.analysis) || ''; dependentVariableEmpty = dependentVariableName === ''; - if (!dependentVariableEmpty && excludes.includes(dependentVariableName)) { - excludesValid = false; + if ( + !dependentVariableEmpty && + includes !== undefined && + includes.length > 0 && + !includes.includes(dependentVariableName) + ) { + includesValid = false; state.advancedEditorMessages.push({ error: i18n.translate( - 'xpack.ml.dataframe.analytics.create.advancedEditorMessage.excludesInvalid', + 'xpack.ml.dataframe.analytics.create.advancedEditorMessage.includesInvalid', { - defaultMessage: 'The dependent variable cannot be excluded.', + defaultMessage: 'The dependent variable must be included.', } ), message: '', @@ -321,7 +326,7 @@ export const validateAdvancedEditor = (state: State): State => { state.form.destinationIndexPatternTitleExists = destinationIndexPatternTitleExists; state.isValid = - excludesValid && + includesValid && trainingPercentValid && state.form.modelMemoryLimitUnitValid && !jobIdEmpty && diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts index b9a9caadcebd..d397dfc315da 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts @@ -42,6 +42,37 @@ const regJobConfig = { allow_lazy_start: false, }; +const outlierJobConfig = { + id: 'outlier-test-01', + description: 'outlier test job description', + source: { + index: ['outlier-test-index'], + query: { + match_all: {}, + }, + }, + dest: { + index: 'outlier-test-01-index', + results_field: 'ml', + }, + analysis: { + outlier_detection: { + feature_influence_threshold: 0.01, + outlier_fraction: 0.05, + compute_feature_influence: false, + method: 'lof', + }, + }, + analyzed_fields: { + includes: ['field', 'other_field'], + excludes: [], + }, + model_memory_limit: '22mb', + create_time: 1590514291395, + version: '8.0.0', + allow_lazy_start: false, +}; + describe('useCreateAnalyticsForm', () => { test('state: getJobConfigFromFormState()', () => { const state = getInitialState(); @@ -53,8 +84,8 @@ describe('useCreateAnalyticsForm', () => { expect(jobConfig?.dest?.index).toBe('the-destination-index'); expect(jobConfig?.source?.index).toBe('the-source-index'); - expect(jobConfig?.analyzed_fields?.excludes).toStrictEqual([]); - expect(typeof jobConfig?.analyzed_fields?.includes).toBe('undefined'); + expect(jobConfig?.analyzed_fields?.includes).toStrictEqual([]); + expect(typeof jobConfig?.analyzed_fields?.excludes).toBe('undefined'); // test the conversion of comma-separated Kibana index patterns to ES array based index patterns state.form.sourceIndex = 'the-source-index-1,the-source-index-2'; @@ -65,11 +96,11 @@ describe('useCreateAnalyticsForm', () => { ]); }); - test('state: getCloneFormStateFromJobConfig()', () => { + test('state: getCloneFormStateFromJobConfig() regression', () => { const clonedState = getCloneFormStateFromJobConfig(regJobConfig); expect(clonedState?.sourceIndex).toBe('reg-test-index'); - expect(clonedState?.excludes).toStrictEqual([]); + expect(clonedState?.includes).toStrictEqual([]); expect(clonedState?.dependentVariable).toBe('price'); expect(clonedState?.numTopFeatureImportanceValues).toBe(2); expect(clonedState?.predictionFieldName).toBe('airbnb_test'); @@ -80,4 +111,19 @@ describe('useCreateAnalyticsForm', () => { expect(clonedState?.destinationIndex).toBe(undefined); expect(clonedState?.jobId).toBe(undefined); }); + + test('state: getCloneFormStateFromJobConfig() outlier detection', () => { + const clonedState = getCloneFormStateFromJobConfig(outlierJobConfig); + + expect(clonedState?.sourceIndex).toBe('outlier-test-index'); + expect(clonedState?.includes).toStrictEqual(['field', 'other_field']); + expect(clonedState?.featureInfluenceThreshold).toBe(0.01); + expect(clonedState?.outlierFraction).toBe(0.05); + expect(clonedState?.computeFeatureInfluence).toBe(false); + expect(clonedState?.method).toBe('lof'); + expect(clonedState?.modelMemoryLimit).toBe('22mb'); + // destination index and job id should be undefined + expect(clonedState?.destinationIndex).toBe(undefined); + expect(clonedState?.jobId).toBe(undefined); + }); }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index 241866b56c5c..da6e2e440a26 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -7,11 +7,8 @@ import { DeepPartial, DeepReadonly } from '../../../../../../../common/types/common'; import { checkPermission } from '../../../../../capabilities/check_capabilities'; import { mlNodesAvailable } from '../../../../../ml_nodes_check'; -import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; import { - isClassificationAnalysis, - isRegressionAnalysis, DataFrameAnalyticsId, DataFrameAnalyticsConfig, ANALYSIS_CONFIG_TYPE, @@ -57,10 +54,10 @@ export interface State { destinationIndexNameValid: boolean; destinationIndexPatternTitleExists: boolean; eta: undefined | number; - excludes: string[]; featureBagFraction: undefined | number; featureInfluenceThreshold: undefined | number; gamma: undefined | number; + includes: string[]; jobId: DataFrameAnalyticsId; jobIdExists: boolean; jobIdEmpty: boolean; @@ -122,10 +119,10 @@ export const getInitialState = (): State => ({ destinationIndexNameValid: false, destinationIndexPatternTitleExists: false, eta: undefined, - excludes: [], featureBagFraction: undefined, featureInfluenceThreshold: undefined, gamma: undefined, + includes: [], jobId: '', jobIdExists: false, jobIdEmpty: true, @@ -175,55 +172,6 @@ export const getInitialState = (): State => ({ estimatedModelMemoryLimit: '', }); -const getExcludesFields = (excluded: string[]) => { - const { fields } = newJobCapsService; - const updatedExcluded: string[] = []; - // Loop through excluded fields to check for multiple types of same field - for (let i = 0; i < excluded.length; i++) { - const fieldName = excluded[i]; - let mainField; - - // No dot in fieldName - it is the main field - if (fieldName.includes('.') === false) { - mainField = fieldName; - } else { - // Dot in fieldName - check if there's a field whose name equals the fieldName with the last dot suffix removed - const regex = /\.[^.]*$/; - const suffixRemovedField = fieldName.replace(regex, ''); - const fieldMatch = newJobCapsService.getFieldById(suffixRemovedField); - - // There's a match - set as the main field - if (fieldMatch !== null) { - mainField = suffixRemovedField; - } else { - // No main field to be found - add the fieldName to updatedExcluded array if it's not already there - if (updatedExcluded.includes(fieldName) === false) { - updatedExcluded.push(fieldName); - } - } - } - - if (mainField !== undefined) { - // Add the main field to the updatedExcluded array if it's not already there - if (updatedExcluded.includes(mainField) === false) { - updatedExcluded.push(mainField); - } - // Create regex to find all other fields whose names begin with main field followed by a dot - const regex = new RegExp(`${mainField}\\..+`); - - // Loop through fields and add fields matching the pattern to updatedExcluded array - for (let j = 0; j < fields.length; j++) { - const field = fields[j].name; - if (updatedExcluded.includes(field) === false && field.match(regex) !== null) { - updatedExcluded.push(field); - } - } - } - } - - return updatedExcluded; -}; - export const getJobConfigFromFormState = ( formState: State['form'] ): DeepPartial => { @@ -242,7 +190,7 @@ export const getJobConfigFromFormState = ( index: formState.destinationIndex, }, analyzed_fields: { - excludes: getExcludesFields(formState.excludes), + includes: formState.includes, }, analysis: { outlier_detection: {}, @@ -333,21 +281,16 @@ export function getCloneFormStateFromJobConfig( ? analyticsJobConfig.source.index.join(',') : analyticsJobConfig.source.index, modelMemoryLimit: analyticsJobConfig.model_memory_limit, - excludes: analyticsJobConfig.analyzed_fields.excludes, + includes: analyticsJobConfig.analyzed_fields.includes, }; - if ( - isRegressionAnalysis(analyticsJobConfig.analysis) || - isClassificationAnalysis(analyticsJobConfig.analysis) - ) { - const analysisConfig = analyticsJobConfig.analysis[jobType]; + const analysisConfig = analyticsJobConfig.analysis[jobType]; - for (const key in analysisConfig) { - if (analysisConfig.hasOwnProperty(key)) { - const camelCased = toCamelCase(key); - // @ts-ignore - resultState[camelCased] = analysisConfig[key]; - } + for (const key in analysisConfig) { + if (analysisConfig.hasOwnProperty(key)) { + const camelCased = toCamelCase(key); + // @ts-ignore + resultState[camelCased] = analysisConfig[key]; } } diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.ts index 7cdd5478e398..7de39d91047e 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/data_frame_analytics.ts @@ -8,7 +8,10 @@ import { http } from '../http_service'; import { basePath } from './index'; import { DataFrameAnalyticsStats } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/common'; -import { DataFrameAnalyticsConfig } from '../../data_frame_analytics/common'; +import { + DataFrameAnalyticsConfig, + UpdateDataFrameAnalyticsConfig, +} from '../../data_frame_analytics/common'; import { DeepPartial } from '../../../../common/types/common'; import { DeleteDataFrameAnalyticsWithIndexStatus } from '../../../../common/types/data_frame_analytics'; @@ -72,6 +75,14 @@ export const dataFrameAnalytics = { body, }); }, + updateDataFrameAnalytics(analyticsId: string, updateConfig: UpdateDataFrameAnalyticsConfig) { + const body = JSON.stringify(updateConfig); + return http({ + path: `${basePath()}/data_frame/analytics/${analyticsId}/_update`, + method: 'POST', + body, + }); + }, evaluateDataFrameAnalytics(evaluateConfig: any) { const body = JSON.stringify(evaluateConfig); return http({ diff --git a/x-pack/plugins/ml/server/client/elasticsearch_ml.ts b/x-pack/plugins/ml/server/client/elasticsearch_ml.ts index 07159534e1e2..24c80c450f61 100644 --- a/x-pack/plugins/ml/server/client/elasticsearch_ml.ts +++ b/x-pack/plugins/ml/server/client/elasticsearch_ml.ts @@ -223,6 +223,21 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) method: 'POST', }); + ml.updateDataFrameAnalytics = ca({ + urls: [ + { + fmt: '/_ml/data_frame/analytics/<%=analyticsId%>/_update', + req: { + analyticsId: { + type: 'string', + }, + }, + }, + ], + needBody: true, + method: 'POST', + }); + ml.deleteJob = ca({ urls: [ { diff --git a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts index e2601c7ad6a2..24be23332e4c 100644 --- a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -10,6 +10,7 @@ import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/a import { RouteInitialization } from '../types'; import { dataAnalyticsJobConfigSchema, + dataAnalyticsJobUpdateSchema, dataAnalyticsEvaluateSchema, dataAnalyticsExplainSchema, analyticsIdSchema, @@ -483,6 +484,45 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat }) ); + /** + * @apiGroup DataFrameAnalytics + * + * @api {post} /api/ml/data_frame/analytics/:analyticsId/_update Update specified analytics job + * @apiName UpdateDataFrameAnalyticsJob + * @apiDescription Updates a data frame analytics job. + * + * @apiSchema (params) analyticsIdSchema + */ + router.post( + { + path: '/api/ml/data_frame/analytics/{analyticsId}/_update', + validate: { + params: analyticsIdSchema, + body: dataAnalyticsJobUpdateSchema, + }, + options: { + tags: ['access:ml:canCreateDataFrameAnalytics'], + }, + }, + mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + try { + const { analyticsId } = request.params; + const results = await context.ml!.mlClient.callAsCurrentUser( + 'ml.updateDataFrameAnalytics', + { + body: request.body, + analyticsId, + } + ); + return response.ok({ + body: results, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + /** * @apiGroup DataFrameAnalytics * diff --git a/x-pack/plugins/ml/server/routes/schemas/data_analytics_schema.ts b/x-pack/plugins/ml/server/routes/schemas/data_analytics_schema.ts index e6b4e4ccf858..5469c2fefdf3 100644 --- a/x-pack/plugins/ml/server/routes/schemas/data_analytics_schema.ts +++ b/x-pack/plugins/ml/server/routes/schemas/data_analytics_schema.ts @@ -69,6 +69,12 @@ export const deleteDataFrameAnalyticsJobSchema = schema.object({ deleteDestIndexPattern: schema.maybe(schema.boolean()), }); +export const dataAnalyticsJobUpdateSchema = schema.object({ + description: schema.maybe(schema.string()), + model_memory_limit: schema.maybe(schema.string()), + allow_lazy_start: schema.maybe(schema.boolean()), +}); + export const stopsDataFrameAnalyticsJobQuerySchema = schema.object({ force: schema.maybe(schema.boolean()), }); diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index f547bc8185d0..d32d9f01d61a 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -35,6 +35,16 @@ export const DEFAULT_TIMEPICKER_QUICK_RANGES = 'timepicker:quickRanges'; export const NO_ALERT_INDEX = 'no-alert-index-049FC71A-4C2C-446F-9901-37XMC5024C51'; export const ENDPOINT_METADATA_INDEX = 'metrics-endpoint.metadata-*'; +export enum SecurityPageName { + alerts = 'alerts', + overview = 'overview', + hosts = 'hosts', + network = 'network', + timelines = 'timelines', + case = 'case', + management = 'management', +} + export const APP_OVERVIEW_PATH = `${APP_PATH}/overview`; export const APP_ALERTS_PATH = `${APP_PATH}/alerts`; export const APP_HOSTS_PATH = `${APP_PATH}/hosts`; diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index 2a1a2d2c8e19..51c29c15a809 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { newRule, totalNumberOfPrebuiltRulesInEsArchive } from '../objects/rule'; +import { newRule, totalNumberOfPrebuiltRulesInEsArchiveCustomRule } from '../objects/rule'; import { CUSTOM_RULES_BTN, @@ -64,8 +64,7 @@ import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { ALERTS_URL } from '../urls/navigation'; -// // Skipped as was causing failures on master -describe.skip('Detection rules, custom', () => { +describe('Detection rules, custom', () => { before(() => { esArchiverLoad('custom_rule_with_timeline'); }); @@ -90,7 +89,7 @@ describe.skip('Detection rules, custom', () => { changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); - const expectedNumberOfRules = totalNumberOfPrebuiltRulesInEsArchive + 1; + const expectedNumberOfRules = totalNumberOfPrebuiltRulesInEsArchiveCustomRule + 1; cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts index 06e9228de4f4..fdab3016de8d 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts @@ -17,10 +17,9 @@ import { ALERTS_URL } from '../urls/navigation'; const EXPECTED_EXPORTED_RULE_FILE_PATH = 'cypress/test_files/expected_rules_export.ndjson'; -// Skipped as was causing failures on master -describe.skip('Export rules', () => { +describe('Export rules', () => { before(() => { - esArchiverLoad('custom_rules'); + esArchiverLoad('export_rule'); cy.server(); cy.route( 'POST', @@ -29,7 +28,7 @@ describe.skip('Export rules', () => { }); after(() => { - esArchiverUnload('custom_rules'); + esArchiverUnload('export_rule'); }); it('Exports a custom rule', () => { diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index d750fe212002..c9d3af57e5e5 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -11,6 +11,8 @@ export const totalNumberOfPrebuiltRules = rawRules.length; export const totalNumberOfPrebuiltRulesInEsArchive = 127; +export const totalNumberOfPrebuiltRulesInEsArchiveCustomRule = 145; + interface Mitre { tactic: string; techniques: string[]; @@ -57,7 +59,7 @@ const mitre2: Mitre = { }; export const newRule: CustomRule = { - customQuery: 'host.name: *', + customQuery: 'host.name: * ', name: 'New Rule Test', description: 'The new rule description.', severity: 'High', @@ -67,7 +69,7 @@ export const newRule: CustomRule = { falsePositivesExamples: ['False1', 'False2'], mitre: [mitre1, mitre2], note: '# test markdown', - timelineId: '352c6110-9ffb-11ea-b3d8-857d6042d9bd', + timelineId: '3270f530-bc84-11ea-b73f-89980a6a1ce7', }; export const machineLearningRule: MachineLearningRule = { diff --git a/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson b/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson index dcbfa9d0dd16..7baa59fb3d8c 100644 --- a/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson +++ b/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson @@ -1,2 +1,2 @@ -{"actions":[],"created_at":"2020-03-26T10:09:07.569Z","updated_at":"2020-03-26T10:09:08.021Z","created_by":"elastic","description":"Rule 1","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","id":"49db5bd1-bdd5-4821-be26-bb70a815dedb","immutable":false,"index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"0cea4194-03f2-4072-b281-d31b72221d9d","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":50,"name":"Rule 1","query":"host.name:*","references":[],"meta":{"from":"1m","throttle":"no_actions"},"severity":"low","updated_by":"elastic","tags":["rule1"],"to":"now","type":"query","threat":[],"throttle":"no_actions","version":1,"exceptions_list":[]} +{"author":[],"actions":[],"created_at":"2020-07-03T10:44:10.567Z","updated_at":"2020-07-03T10:44:10.941Z","created_by":"elastic","description":"Export rule","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","id":"ad65b1b6-be18-4e41-9d0a-89d8576053d8","immutable":false,"index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"50a3776b-144d-4cff-9f1f-1173e0d5d4a4","language":"kuery","license":"","output_index":".siem-signals-default","max_signals":100,"risk_score":50,"risk_score_mapping":[],"rule_name_override":"","name":"Export rule","query":"host.name: * ","references":[],"meta":{"from":"1m","kibana_siem_app_url":"http://localhost:5620/app/security"},"severity":"low","severity_mapping":[],"updated_by":"elastic","tags":[],"to":"now","type":"query","threat":[],"throttle":"no_actions","timestamp_override":"","version":1,"exceptions_list":[]} {"exported_count":1,"missing_rules":[],"missing_rules_count":0} diff --git a/x-pack/plugins/security_solution/public/app/types.ts b/x-pack/plugins/security_solution/public/app/types.ts index 4bd888e87bbd..4590f05e1263 100644 --- a/x-pack/plugins/security_solution/public/app/types.ts +++ b/x-pack/plugins/security_solution/public/app/types.ts @@ -18,16 +18,8 @@ import { State, SubPluginsInitReducer } from '../common/store'; import { Immutable } from '../../common/endpoint/types'; import { AppAction } from '../common/store/actions'; import { TimelineState } from '../timelines/store/timeline/types'; +export { SecurityPageName } from '../../common/constants'; -export enum SecurityPageName { - alerts = 'alerts', - overview = 'overview', - hosts = 'hosts', - network = 'network', - timelines = 'timelines', - case = 'case', - management = 'management', -} export interface SecuritySubPluginStore { initialState: Record; reducer: Record>; diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/create_timelines_route.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/create_timelines_route.ts index 60ddaea367ae..5bc4bec45dfb 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/create_timelines_route.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/create_timelines_route.ts @@ -33,7 +33,7 @@ export const createTimelinesRoute = ( body: buildRouteValidation(createTimelineSchema), }, options: { - tags: ['access:siem'], + tags: ['access:securitySolution'], }, }, async (context, request, response) => { diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/update_timelines_route.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/update_timelines_route.ts index f59df151b695..a622ee9b1570 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/update_timelines_route.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/update_timelines_route.ts @@ -31,7 +31,7 @@ export const updateTimelinesRoute = ( body: buildRouteValidation(updateTimelineSchema), }, options: { - tags: ['access:siem'], + tags: ['access:securitySolution'], }, }, // eslint-disable-next-line complexity diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index a97f1eee5634..356b6fca7e8c 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -39,7 +39,7 @@ import { initSavedObjects, savedObjectTypes } from './saved_objects'; import { AppClientFactory } from './client'; import { createConfig$, ConfigType } from './config'; import { initUiSettings } from './ui_settings'; -import { APP_ID, APP_ICON, SERVER_APP_ID } from '../common/constants'; +import { APP_ID, APP_ICON, SERVER_APP_ID, SecurityPageName } from '../common/constants'; import { registerEndpointRoutes } from './endpoint/routes/metadata'; import { registerResolverRoutes } from './endpoint/routes/resolver'; import { registerPolicyRoutes } from './endpoint/routes/policy'; @@ -70,6 +70,17 @@ export interface PluginSetup {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PluginStart {} +const securitySubPlugins = [ + APP_ID, + `${APP_ID}:${SecurityPageName.overview}`, + `${APP_ID}:${SecurityPageName.alerts}`, + `${APP_ID}:${SecurityPageName.hosts}`, + `${APP_ID}:${SecurityPageName.network}`, + `${APP_ID}:${SecurityPageName.timelines}`, + `${APP_ID}:${SecurityPageName.case}`, + `${APP_ID}:${SecurityPageName.management}`, +]; + export class Plugin implements IPlugin { private readonly logger: Logger; private readonly config$: Observable; @@ -144,12 +155,12 @@ export class Plugin implements IPlugin { await ml.jobSourceSelection.selectSourceForAnalyticsJob(testData.source); + await ml.dataFrameAnalyticsCreation.assertConfigurationStepActive(); }); it('selects the job type', async () => { @@ -83,6 +84,14 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsCreation.setTrainingPercent(testData.trainingPercent); }); + it('displays the source data preview', async () => { + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); + }); + + it('displays the include fields selection', async () => { + await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); + }); + it('continues to the additional options step', async () => { await ml.dataFrameAnalyticsCreation.continueToAdditionalOptionsStep(); }); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts index 525e25d0158b..068ef48b095e 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts @@ -45,6 +45,7 @@ export default function ({ getService }: FtrProviderContext) { }, analysis: { classification: { + prediction_field_name: 'test', dependent_variable: 'y', training_percent: 20, }, @@ -107,6 +108,7 @@ export default function ({ getService }: FtrProviderContext) { }, analysis: { regression: { + prediction_field_name: 'test', dependent_variable: 'stab', training_percent: 20, }, @@ -157,9 +159,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('should open the wizard with a proper header', async () => { - expect(await ml.dataFrameAnalyticsCreation.getHeaderText()).to.match( - /Clone analytics job/ - ); + const headerText = await ml.dataFrameAnalyticsCreation.getHeaderText(); + expect(headerText).to.match(/Clone job/); + await ml.dataFrameAnalyticsCreation.assertConfigurationStepActive(); }); it('should have correct init form values for config step', async () => { @@ -174,7 +176,7 @@ export default function ({ getService }: FtrProviderContext) { it('should have correct init form values for additional options step', async () => { await ml.dataFrameAnalyticsCreation.assertInitialCloneJobAdditionalOptionsStep( - testData.job as DataFrameAnalyticsConfig + testData.job.analysis as DataFrameAnalyticsConfig['analysis'] ); }); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts index cff59fa42abb..0202c8431ce3 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts @@ -12,6 +12,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./outlier_detection_creation')); loadTestFile(require.resolve('./regression_creation')); loadTestFile(require.resolve('./classification_creation')); - // loadTestFile(require.resolve('./cloning')); + loadTestFile(require.resolve('./cloning')); }); } diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts index 582b19f5e18a..500825f7d9d3 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts @@ -64,6 +64,7 @@ export default function ({ getService }: FtrProviderContext) { it('selects the source data and loads the job wizard page', async () => { await ml.jobSourceSelection.selectSourceForAnalyticsJob(testData.source); + await ml.dataFrameAnalyticsCreation.assertConfigurationStepActive(); }); it('selects the job type', async () => { @@ -79,6 +80,14 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsCreation.assertTrainingPercentInputMissing(); }); + it('displays the source data preview', async () => { + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); + }); + + it('displays the include fields selection', async () => { + await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); + }); + it('continues to the additional options step', async () => { await ml.dataFrameAnalyticsCreation.continueToAdditionalOptionsStep(); }); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts index c8a6e1c96c21..33f0ee9cd99a 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts @@ -66,6 +66,7 @@ export default function ({ getService }: FtrProviderContext) { it('selects the source data and loads the job wizard page', async () => { await ml.jobSourceSelection.selectSourceForAnalyticsJob(testData.source); + await ml.dataFrameAnalyticsCreation.assertConfigurationStepActive(); }); it('selects the job type', async () => { @@ -83,6 +84,14 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsCreation.setTrainingPercent(testData.trainingPercent); }); + it('displays the source data preview', async () => { + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); + }); + + it('displays the include fields selection', async () => { + await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); + }); + it('continues to the additional options step', async () => { await ml.dataFrameAnalyticsCreation.continueToAdditionalOptionsStep(); }); diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts index f67ea583e25c..918c982de02e 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts @@ -124,13 +124,21 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( await this.assertJobDescriptionValue(jobDescription); }, - // async assertExcludedFieldsSelection(expectedSelection: string[]) { - // const actualSelection = await comboBox.getComboBoxSelectedOptions( - // 'mlAnalyticsCreateJobWizardExcludesSelect' - // ); + async assertSourceDataPreviewExists() { + await testSubjects.existOrFail('mlAnalyticsCreationDataGrid loaded', { timeout: 5000 }); + }, + + async assertIncludeFieldsSelectionExists() { + await testSubjects.existOrFail('mlAnalyticsCreateJobWizardIncludesSelect', { timeout: 5000 }); + }, + + // async assertIncludedFieldsSelection(expectedSelection: string[]) { + // const includesTable = await testSubjects.find('mlAnalyticsCreateJobWizardIncludesSelect'); + // const actualSelection = await includesTable.findByClassName('euiTableRow-isSelected'); + // expect(actualSelection).to.eql( // expectedSelection, - // `Excluded fields should be '${expectedSelection}' (got '${actualSelection}')` + // `Included fields should be '${expectedSelection}' (got '${actualSelection}')` // ); // }, @@ -252,19 +260,35 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( await this.assertTrainingPercentValue(trainingPercent); }, + async assertConfigurationStepActive() { + await testSubjects.existOrFail('mlAnalyticsCreateJobWizardConfigurationStep active'); + }, + + async assertAdditionalOptionsStepActive() { + await testSubjects.existOrFail('mlAnalyticsCreateJobWizardAdvancedStep active'); + }, + + async assertDetailsStepActive() { + await testSubjects.existOrFail('mlAnalyticsCreateJobWizardDetailsStep active'); + }, + + async assertCreateStepActive() { + await testSubjects.existOrFail('mlAnalyticsCreateJobWizardCreateStep active'); + }, + async continueToAdditionalOptionsStep() { - await testSubjects.click('mlAnalyticsCreateJobWizardContinueButton'); - await testSubjects.existOrFail('mlAnalyticsCreateJobWizardAdvancedStep'); + await testSubjects.clickWhenNotDisabled('mlAnalyticsCreateJobWizardContinueButton'); + await this.assertAdditionalOptionsStepActive(); }, async continueToDetailsStep() { - await testSubjects.click('mlAnalyticsCreateJobWizardContinueButton'); - await testSubjects.existOrFail('mlAnalyticsCreateJobWizardDetailsStep'); + await testSubjects.clickWhenNotDisabled('mlAnalyticsCreateJobWizardContinueButton'); + await this.assertDetailsStepActive(); }, async continueToCreateStep() { - await testSubjects.click('mlAnalyticsCreateJobWizardContinueButton'); - await testSubjects.existOrFail('mlAnalyticsCreateJobWizardCreateStep'); + await testSubjects.clickWhenNotDisabled('mlAnalyticsCreateJobWizardContinueButton'); + await this.assertCreateStepActive(); }, async assertModelMemoryInputExists() { @@ -282,6 +306,17 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( ); }, + async assertPredictionFieldNameValue(expectedValue: string) { + const actualPredictedFieldName = await testSubjects.getAttribute( + 'mlAnalyticsCreateJobWizardPredictionFieldNameInput', + 'value' + ); + expect(actualPredictedFieldName).to.eql( + expectedValue, + `Prediction field name should be '${expectedValue}' (got '${actualPredictedFieldName}')` + ); + }, + async setModelMemory(modelMemory: string) { await retry.tryForTime(15 * 1000, async () => { await mlCommon.setValueWithChecks( @@ -372,11 +407,19 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( await this.assertDependentVariableSelection([job.analysis[jobType].dependent_variable]); await this.assertTrainingPercentValue(String(job.analysis[jobType].training_percent)); } - // await this.assertExcludedFieldsSelection(job.analyzed_fields.excludes); + await this.assertSourceDataPreviewExists(); + await this.assertIncludeFieldsSelectionExists(); + // await this.assertIncludedFieldsSelection(job.analyzed_fields.includes); }, - async assertInitialCloneJobAdditionalOptionsStep(job: DataFrameAnalyticsConfig) { - await this.assertModelMemoryValue(job.model_memory_limit); + async assertInitialCloneJobAdditionalOptionsStep( + analysis: DataFrameAnalyticsConfig['analysis'] + ) { + const jobType = Object.keys(analysis)[0]; + if (isClassificationAnalysis(analysis) || isRegressionAnalysis(analysis)) { + // @ts-ignore + await this.assertPredictionFieldNameValue(analysis[jobType].prediction_field_name); + } }, async assertInitialCloneJobDetailsStep(job: DataFrameAnalyticsConfig) { diff --git a/x-pack/test/ingest_manager_api_integration/apis/file.ts b/x-pack/test/ingest_manager_api_integration/apis/file.ts index 33eeda1ee274..a7462ac51ecc 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/file.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/file.ts @@ -47,7 +47,7 @@ export default function ({ getService }: FtrProviderContext) { '/api/ingest_manager/epm/packages/filetest/0.1.0/kibana/visualization/sample_visualization.json' ) .set('kbn-xsrf', 'xxx') - .expect('Content-Type', 'application/json; charset=utf-8') + .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200); } else { warnAndSkipTest(this, log); @@ -61,7 +61,7 @@ export default function ({ getService }: FtrProviderContext) { '/api/ingest_manager/epm/packages/filetest/0.1.0/kibana/dashboard/sample_dashboard.json' ) .set('kbn-xsrf', 'xxx') - .expect('Content-Type', 'application/json; charset=utf-8') + .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200); } else { warnAndSkipTest(this, log); @@ -73,7 +73,7 @@ export default function ({ getService }: FtrProviderContext) { await supertest .get('/api/ingest_manager/epm/packages/filetest/0.1.0/kibana/search/sample_search.json') .set('kbn-xsrf', 'xxx') - .expect('Content-Type', 'application/json; charset=utf-8') + .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200); } else { warnAndSkipTest(this, log); diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/package_registry_config.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/package_registry_config.yml index 0060e247827d..5bfbf78e25ed 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/fixtures/package_registry_config.yml +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/package_registry_config.yml @@ -1,3 +1,3 @@ package_paths: - - /registry/packages/package-storage - - /registry/packages/test-packages \ No newline at end of file + - /packages/production + - /packages/test-packages \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/dataset/test/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/dataset/test/fields/fields.yml new file mode 100644 index 000000000000..12a9a03c1337 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/dataset/test/fields/fields.yml @@ -0,0 +1,16 @@ +- name: dataset.type + type: constant_keyword + description: > + Dataset type. +- name: dataset.name + type: constant_keyword + description: > + Dataset name. +- name: dataset.namespace + type: constant_keyword + description: > + Dataset namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/dataset/test/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/dataset/test/manifest.yml new file mode 100644 index 000000000000..9ac3c68a0be9 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/dataset/test/manifest.yml @@ -0,0 +1,9 @@ +title: Test Dataset + +type: logs + +elasticsearch: + index_template.mappings: + dynamic: false + index_template.settings: + index.lifecycle.name: reference diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/docs/README.md new file mode 100644 index 000000000000..17fb41ceae24 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing the that the settings and mappings section get used diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/img/logo_overrides_64_color.svg b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/img/logo_overrides_64_color.svg new file mode 100644 index 000000000000..b03007a76ffc --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/img/logo_overrides_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/manifest.yml new file mode 100644 index 000000000000..ba9fd0fada00 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/overrides/0.1.0/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: overrides +title: Mappings Settings Test +description: This is a test package for testing that the mappings and settings sections in the dataset manifest are applied. +version: 0.1.0 +categories: ['security'] +release: beta +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_overrides_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/ingest_manager_api_integration/apis/index.js b/x-pack/test/ingest_manager_api_integration/apis/index.js index ef8880f86078..3f8df8379e74 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/index.js +++ b/x-pack/test/ingest_manager_api_integration/apis/index.js @@ -11,5 +11,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./file')); //loadTestFile(require.resolve('./template')); loadTestFile(require.resolve('./ilm')); + loadTestFile(require.resolve('./install')); }); } diff --git a/x-pack/test/ingest_manager_api_integration/apis/install.ts b/x-pack/test/ingest_manager_api_integration/apis/install.ts new file mode 100644 index 000000000000..92078c25419d --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/install.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../api_integration/ftr_provider_context'; +import { warnAndSkipTest } from '../helpers'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + const dockerServers = getService('dockerServers'); + const log = getService('log'); + + const deletePackage = async (pkgkey: string) => { + await supertest.delete(`/api/ingest_manager/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx'); + }; + + const mappingsPackage = 'overrides-0.1.0'; + const server = dockerServers.get('registry'); + + describe('installs packages that include settings and mappings overrides', async () => { + after(async () => { + if (server.enabled) { + // remove the package just in case it being installed will affect other tests + await deletePackage(mappingsPackage); + } + }); + + it('should install the overrides package correctly', async function () { + if (server.enabled) { + let { body } = await supertest + .post(`/api/ingest_manager/epm/packages/${mappingsPackage}`) + .set('kbn-xsrf', 'xxxx') + .expect(200); + + const templateName = body.response[0].id; + + ({ body } = await es.transport.request({ + method: 'GET', + path: `/_index_template/${templateName}`, + })); + + // make sure it has the right composed_of array, the contents should be the component templates + // that were installed + expect(body.index_templates[0].index_template.composed_of).to.contain( + `${templateName}-mappings` + ); + expect(body.index_templates[0].index_template.composed_of).to.contain( + `${templateName}-settings` + ); + + ({ body } = await es.transport.request({ + method: 'GET', + path: `/_component_template/${templateName}-mappings`, + })); + + // Make sure that the `dynamic` field exists and is set to false (as it is in the package) + expect(body.component_templates[0].component_template.template.mappings.dynamic).to.be( + false + ); + // Make sure that the `@timestamp` field exists and is set to date + // this can be removed once https://github.com/elastic/elasticsearch/issues/58956 is resolved + expect( + body.component_templates[0].component_template.template.mappings.properties['@timestamp'] + .type + ).to.be('date'); + + ({ body } = await es.transport.request({ + method: 'GET', + path: `/_component_template/${templateName}-settings`, + })); + + // Make sure that the lifecycle name gets set correct in the settings + expect( + body.component_templates[0].component_template.template.settings.index.lifecycle.name + ).to.be('reference'); + } else { + warnAndSkipTest(this, log); + } + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/list.ts b/x-pack/test/ingest_manager_api_integration/apis/list.ts index 200358cb6f8f..abed9a7b8595 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/list.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/list.ts @@ -29,7 +29,7 @@ export default function ({ getService }: FtrProviderContext) { return response.body; }; const listResponse = await fetchPackageList(); - expect(listResponse.response.length).to.be(11); + expect(listResponse.response.length).to.be(12); } else { warnAndSkipTest(this, log); } diff --git a/x-pack/test/ingest_manager_api_integration/apis/template.ts b/x-pack/test/ingest_manager_api_integration/apis/template.ts index 8911dd28dc24..f7e5a894b83f 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/template.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/template.ts @@ -27,6 +27,7 @@ export default function ({ getService }: FtrProviderContext) { templateName, mappings, packageName: 'system', + composedOfTemplates: [], }); // This test is not an API integration test with Kibana diff --git a/x-pack/test/ingest_manager_api_integration/config.ts b/x-pack/test/ingest_manager_api_integration/config.ts index bbef12463ed0..88ec8d53c1cd 100644 --- a/x-pack/test/ingest_manager_api_integration/config.ts +++ b/x-pack/test/ingest_manager_api_integration/config.ts @@ -21,21 +21,25 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { `${path.join( path.dirname(__filename), './apis/fixtures/package_registry_config.yml' - )}:/registry/config.yml`, + )}:/package-registry/config.yml`, '-v', `${path.join( path.dirname(__filename), './apis/fixtures/test_packages' - )}:/registry/packages/test-packages`, + )}:/packages/test-packages`, ]; + // Docker image to use for Ingest Manager API integration tests. + const dockerImage = + 'docker.elastic.co/package-registry/distribution:184b85f19e8fd14363e36150173d338ff9659f01'; + return { testFiles: [require.resolve('./apis')], servers: xPackAPITestsConfig.get('servers'), dockerServers: defineDockerServersConfig({ registry: { enabled: !!registryPort, - image: 'docker.elastic.co/package-registry/package-registry:kibana-testing-1', + image: dockerImage, portInContainer: 8080, port: registryPort, args: dockerArgs, diff --git a/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/data.json.gz b/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/data.json.gz index 3d50451cee39..b3a94c77c118 100644 Binary files a/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/data.json.gz and b/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/data.json.gz differ diff --git a/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/mappings.json b/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/mappings.json index 693878a88f89..01a768351e48 100644 --- a/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/mappings.json +++ b/x-pack/test/security_solution_cypress/es_archives/custom_rule_with_timeline/mappings.json @@ -14,36 +14,39 @@ "alert": "7b44fba6773e37c806ce290ea9b7024e", "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", "apm-telemetry": "3525d7c22c42bc80f5e6e9cb3f2b26a2", - "application_usage_totals": "c897e4310c5f24b07caaff3db53ae2c1", - "application_usage_transactional": "965839e75f809fefe04f92dc4d99722a", + "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724", + "application_usage_transactional": "43b8830d5d0df85a6823d290885fc9fd", "canvas-element": "7390014e1091044523666d97247392fc", "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", + "canvas-workpad-template": "ae2673f678281e2c055d764b153e9715", "cases": "32aa96a6d3855ddda53010ae2048ac22", "cases-comments": "c2061fb929f585df57425102fa928b4b", "cases-configure": "42711cbb311976c0687853f4c1354572", "cases-user-actions": "32277330ec6b721abe3b846cfd939a71", - "config": "ae24d22d5986d04124cc6568f771066f", + "config": "c63748b75f39d0c54de12d12c1ccbc20", "dashboard": "d00f614b29a80360e1190193fd333bab", - "epm-packages": "92b4b1899b887b090d01c033f3118a85", + "endpoint:exceptions-artifact": "053713a6b91811c7de078ead17384914", + "endpoint:exceptions-manifest": "67c28185da541c1404e7852d30498cd6", + "epm-packages": "04696e7dba1b9597f7d6ed78a4a76658", "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", - "fleet-agent-actions": "e520c855577170c24481be05c3ae14ec", + "fleet-agent-actions": "00fe5651ed2da16b7f8159bbf0f7d910", "fleet-agent-events": "3231653fafe4ef3196fe3b32ab774bf2", - "fleet-agents": "864760267df6c970f629bd4458506c53", - "fleet-enrollment-api-keys": "28b91e20b105b6f928e2012600085d8f", + "fleet-agents": "578bbfa81650206927683ebde0c85409", + "fleet-enrollment-api-keys": "451e5c329b3ae9722dc7bc8f5921e05d", "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", "index-pattern": "66eccb05066c5a89924f48a9e9736499", - "infrastructure-ui-source": "ddc0ecb18383f6b26101a2fadb2dab0c", - "ingest-agent-configs": "d9a5cbdce8e937f674a7b376c47a34a1", - "ingest-package-configs": "c0fe6347b0eebcbf421841669e3acd31", - "ingest-outputs": "0e57221778a7153c8292edf154099036", + "infrastructure-ui-source": "2b2809653635caf490c93f090502d04c", + "ingest-agent-configs": "f1e09bc73462386a8c07e9d1997d0688", + "ingest-outputs": "87da6a0e27b3a61ad389fb7a7e2da293", + "ingest-package-configs": "48e8bd97e488008e21c0b5a2367b83ad", "ingest_manager_settings": "c5b0749b4ab03c582efd4c14cb8f132c", "inventory-view": "88fc7e12fd1b45b6f0787323ce4f18d2", "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", - "lens": "21c3ea0763beb1ecb0162529706b88c5", + "lens": "d33c68a69ff1e78c9888dedd2164ac22", "lens-ui-telemetry": "509bfa5978586998e05f9e303c07a327", - "map": "23d7aa4a720d4938ccde3983f87bd58d", - "maps-telemetry": "bfd39d88aadadb4be597ea984d433dbe", - "metrics-explorer-view": "428e319af3e822c80a84cf87123ca35c", + "map": "4a05b35c3a3a58fbc72dd0202dc3487f", + "maps-telemetry": "5ef305b18111b77789afefbd36b66171", + "metrics-explorer-view": "a8df1d270ee48c969d22d23812d08187", "migrationVersion": "4a1746014a75ade3a714e1db5763276f", "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", "namespace": "2f4316de49999235636386fe51dc06c1", @@ -67,7 +70,7 @@ "upgrade-assistant-reindex-operation": "296a89039fc4260292be36b1b005d8f2", "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", "uptime-dynamic-settings": "fcdb453a30092f022f2642db29523d80", - "url": "b675c3be8d76ecf029294d51dc7ec65d", + "url": "c7f66a0df8b1b52f17c28c4adb111105", "visualization": "52d7a13ad68a150c4525b292d23e12cc" } }, @@ -109,145 +112,6 @@ } } }, - "agent_actions": { - "properties": { - "agent_id": { - "type": "keyword" - }, - "created_at": { - "type": "date" - }, - "data": { - "type": "flattened" - }, - "sent_at": { - "type": "date" - }, - "type": { - "type": "keyword" - } - } - }, - "agent_configs": { - "properties": { - "datasources": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "id": { - "type": "keyword" - }, - "is_default": { - "type": "boolean" - }, - "name": { - "type": "text" - }, - "namespace": { - "type": "keyword" - }, - "revision": { - "type": "integer" - }, - "status": { - "type": "keyword" - }, - "updated_by": { - "type": "keyword" - }, - "updated_on": { - "type": "keyword" - } - } - }, - "agent_events": { - "properties": { - "action_id": { - "type": "keyword" - }, - "agent_id": { - "type": "keyword" - }, - "config_id": { - "type": "keyword" - }, - "data": { - "type": "text" - }, - "message": { - "type": "text" - }, - "payload": { - "type": "text" - }, - "stream_id": { - "type": "keyword" - }, - "subtype": { - "type": "keyword" - }, - "timestamp": { - "type": "date" - }, - "type": { - "type": "keyword" - } - } - }, - "agents": { - "properties": { - "access_api_key_id": { - "type": "keyword" - }, - "active": { - "type": "boolean" - }, - "config_id": { - "type": "keyword" - }, - "config_newest_revision": { - "type": "integer" - }, - "config_revision": { - "type": "integer" - }, - "current_error_events": { - "type": "text" - }, - "default_api_key": { - "type": "keyword" - }, - "enrolled_at": { - "type": "date" - }, - "last_checkin": { - "type": "date" - }, - "last_updated": { - "type": "date" - }, - "local_metadata": { - "type": "text" - }, - "shared_id": { - "type": "keyword" - }, - "type": { - "type": "keyword" - }, - "updated_at": { - "type": "date" - }, - "user_provided_metadata": { - "type": "text" - }, - "version": { - "type": "keyword" - } - } - }, "alert": { "properties": { "actions": { @@ -1264,29 +1128,12 @@ } }, "application_usage_totals": { - "properties": { - "appId": { - "type": "keyword" - }, - "minutesOnScreen": { - "type": "float" - }, - "numberOfClicks": { - "type": "long" - } - } + "dynamic": "false", + "type": "object" }, "application_usage_transactional": { + "dynamic": "false", "properties": { - "appId": { - "type": "keyword" - }, - "minutesOnScreen": { - "type": "float" - }, - "numberOfClicks": { - "type": "long" - }, "timestamp": { "type": "date" } @@ -1339,6 +1186,38 @@ } } }, + "canvas-workpad-template": { + "dynamic": "false", + "properties": { + "help": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "tags": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "template_key": { + "type": "keyword" + } + } + }, "cases": { "properties": { "closed_at": { @@ -1574,7 +1453,7 @@ } }, "config": { - "dynamic": "true", + "dynamic": "false", "properties": { "buildNum": { "type": "keyword" @@ -1635,132 +1514,39 @@ } } }, - "datasources": { + "endpoint:exceptions-artifact": { "properties": { - "config_id": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "enabled": { - "type": "boolean" - }, - "inputs": { - "properties": { - "config": { - "type": "flattened" - }, - "enabled": { - "type": "boolean" - }, - "processors": { - "type": "keyword" - }, - "streams": { - "properties": { - "config": { - "type": "flattened" - }, - "dataset": { - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "keyword" - }, - "processors": { - "type": "keyword" - } - }, - "type": "nested" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" - }, - "name": { - "type": "keyword" - }, - "namespace": { - "type": "keyword" - }, - "output_id": { - "type": "keyword" - }, - "package": { - "properties": { - "name": { - "type": "keyword" - }, - "title": { - "type": "keyword" - }, - "version": { - "type": "keyword" - } - } - }, - "revision": { - "type": "integer" - } - } - }, - "enrollment_api_keys": { - "properties": { - "active": { - "type": "boolean" - }, - "api_key": { + "body": { "type": "binary" }, - "api_key_id": { - "type": "keyword" - }, - "config_id": { - "type": "keyword" - }, - "created_at": { + "created": { + "index": false, "type": "date" }, - "expire_at": { - "type": "date" - }, - "name": { + "encoding": { + "index": false, "type": "keyword" }, - "type": { + "identifier": { "type": "keyword" }, - "updated_at": { - "type": "date" + "sha256": { + "type": "keyword" + }, + "size": { + "index": false, + "type": "long" } } }, - "epm-package": { + "endpoint:exceptions-manifest": { "properties": { - "installed": { - "properties": { - "id": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" + "created": { + "index": false, + "type": "date" }, - "internal": { - "type": "boolean" - }, - "name": { - "type": "keyword" - }, - "version": { + "ids": { + "index": false, "type": "keyword" } } @@ -1768,7 +1554,7 @@ "epm-packages": { "properties": { "es_index_patterns": { - "dynamic": "false", + "enabled": false, "type": "object" }, "installed": { @@ -1874,10 +1660,11 @@ "type": "integer" }, "current_error_events": { + "index": false, "type": "text" }, "default_api_key": { - "type": "keyword" + "type": "binary" }, "default_api_key_id": { "type": "keyword" @@ -1894,6 +1681,9 @@ "local_metadata": { "type": "flattened" }, + "packages": { + "type": "keyword" + }, "shared_id": { "type": "keyword" }, @@ -2026,6 +1816,9 @@ } } }, + "inventoryDefaultView": { + "type": "keyword" + }, "logAlias": { "type": "keyword" }, @@ -2061,6 +1854,9 @@ "metricAlias": { "type": "keyword" }, + "metricsExplorerDefaultView": { + "type": "keyword" + }, "name": { "type": "text" } @@ -2068,9 +1864,6 @@ }, "ingest-agent-configs": { "properties": { - "datasources": { - "type": "keyword" - }, "description": { "type": "text" }, @@ -2081,6 +1874,7 @@ "type": "boolean" }, "monitoring_enabled": { + "index": false, "type": "keyword" }, "name": { @@ -2089,6 +1883,9 @@ "namespace": { "type": "keyword" }, + "package_configs": { + "type": "keyword" + }, "revision": { "type": "integer" }, @@ -2103,6 +1900,35 @@ } } }, + "ingest-outputs": { + "properties": { + "ca_sha256": { + "index": false, + "type": "keyword" + }, + "config": { + "type": "flattened" + }, + "fleet_enroll_password": { + "type": "binary" + }, + "fleet_enroll_username": { + "type": "binary" + }, + "hosts": { + "type": "keyword" + }, + "is_default": { + "type": "boolean" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, "ingest-package-configs": { "properties": { "config_id": { @@ -2121,6 +1947,7 @@ "type": "boolean" }, "inputs": { + "enabled": false, "properties": { "config": { "type": "flattened" @@ -2128,19 +1955,23 @@ "enabled": { "type": "boolean" }, - "processors": { - "type": "keyword" - }, "streams": { "properties": { - "agent_stream": { + "compiled_stream": { "type": "flattened" }, "config": { "type": "flattened" }, "dataset": { - "type": "keyword" + "properties": { + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } }, "enabled": { "type": "boolean" @@ -2148,9 +1979,6 @@ "id": { "type": "keyword" }, - "processors": { - "type": "keyword" - }, "vars": { "type": "flattened" } @@ -2199,34 +2027,6 @@ } } }, - "ingest-outputs": { - "properties": { - "ca_sha256": { - "type": "keyword" - }, - "config": { - "type": "flattened" - }, - "fleet_enroll_password": { - "type": "binary" - }, - "fleet_enroll_username": { - "type": "binary" - }, - "hosts": { - "type": "keyword" - }, - "is_default": { - "type": "boolean" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - } - }, "ingest_manager_settings": { "properties": { "agent_auto_upgrade": { @@ -2387,6 +2187,9 @@ }, "lens": { "properties": { + "description": { + "type": "text" + }, "expression": { "index": false, "type": "keyword" @@ -2420,9 +2223,6 @@ }, "map": { "properties": { - "bounds": { - "type": "geo_shape" - }, "description": { "type": "text" }, @@ -2444,68 +2244,8 @@ } }, "maps-telemetry": { - "properties": { - "attributesPerMap": { - "properties": { - "dataSourcesCount": { - "properties": { - "avg": { - "type": "long" - }, - "max": { - "type": "long" - }, - "min": { - "type": "long" - } - } - }, - "emsVectorLayersCount": { - "dynamic": "true", - "type": "object" - }, - "layerTypesCount": { - "dynamic": "true", - "type": "object" - }, - "layersCount": { - "properties": { - "avg": { - "type": "long" - }, - "max": { - "type": "long" - }, - "min": { - "type": "long" - } - } - } - } - }, - "indexPatternsWithGeoFieldCount": { - "type": "long" - }, - "indexPatternsWithGeoPointFieldCount": { - "type": "long" - }, - "indexPatternsWithGeoShapeFieldCount": { - "type": "long" - }, - "mapsTotalCount": { - "type": "long" - }, - "settings": { - "properties": { - "showMapVisualizationTypes": { - "type": "boolean" - } - } - }, - "timeCaptured": { - "type": "date" - } - } + "enabled": false, + "type": "object" }, "metrics-explorer-view": { "properties": { @@ -2571,6 +2311,9 @@ } }, "type": "nested" + }, + "source": { + "type": "keyword" } } } @@ -2579,6 +2322,24 @@ "migrationVersion": { "dynamic": "true", "properties": { + "alert": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "config": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, "dashboard": { "fields": { "keyword": { @@ -2597,24 +2358,6 @@ }, "type": "text" }, - "ingest-agent-configs": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "ingest-package-configs": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, "map": { "fields": { "keyword": { @@ -2670,37 +2413,6 @@ "namespaces": { "type": "keyword" }, - "outputs": { - "properties": { - "api_key": { - "type": "keyword" - }, - "ca_sha256": { - "type": "keyword" - }, - "config": { - "type": "flattened" - }, - "fleet_enroll_password": { - "type": "binary" - }, - "fleet_enroll_username": { - "type": "binary" - }, - "hosts": { - "type": "keyword" - }, - "is_default": { - "type": "boolean" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - } - }, "query": { "properties": { "description": { @@ -2784,6 +2496,7 @@ } }, "server": { + "dynamic": "strict", "properties": { "uuid": { "type": "keyword" @@ -3208,6 +2921,9 @@ } } }, + "spaceId": { + "type": "keyword" + }, "telemetry": { "properties": { "allowChangingOptInStatus": { @@ -3424,6 +3140,7 @@ "url": { "fields": { "keyword": { + "ignore_above": 2048, "type": "keyword" } }, @@ -3489,14 +3206,6 @@ }, "agent": { "properties": { - "build": { - "properties": { - "original": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "ephemeral_id": { "ignore_above": 1024, "type": "keyword" @@ -3519,6 +3228,27 @@ } } }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, "client": { "properties": { "address": { @@ -3684,10 +3414,6 @@ "id": { "ignore_above": 1024, "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" } } }, @@ -3715,18 +3441,6 @@ } } }, - "project": { - "properties": { - "id": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "provider": { "ignore_above": 1024, "type": "keyword" @@ -3737,6 +3451,27 @@ } } }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, "container": { "properties": { "id": { @@ -3949,9 +3684,6 @@ } } }, - "compile_time": { - "type": "date" - }, "hash": { "properties": { "md5": { @@ -3972,53 +3704,6 @@ } } }, - "malware_classification": { - "properties": { - "features": { - "properties": { - "data": { - "properties": { - "buffer": { - "ignore_above": 1024, - "type": "keyword" - }, - "decompressed_size": { - "type": "integer" - }, - "encoding": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "identifier": { - "ignore_above": 1024, - "type": "keyword" - }, - "score": { - "type": "double" - }, - "threshold": { - "type": "double" - }, - "upx_packed": { - "type": "boolean" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "mapped_address": { - "ignore_above": 1024, - "type": "keyword" - }, - "mapped_size": { - "type": "long" - }, "name": { "ignore_above": 1024, "type": "keyword" @@ -4029,10 +3714,6 @@ }, "pe": { "properties": { - "architecture": { - "ignore_above": 1024, - "type": "keyword" - }, "company": { "ignore_above": 1024, "type": "keyword" @@ -4045,10 +3726,6 @@ "ignore_above": 1024, "type": "keyword" }, - "imphash": { - "ignore_above": 1024, - "type": "keyword" - }, "original_file_name": { "ignore_above": 1024, "type": "keyword" @@ -4147,46 +3824,6 @@ } } }, - "endpoint": { - "properties": { - "artifact": { - "properties": { - "hash": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "event": { - "properties": { - "process": { - "properties": { - "ancestry": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "policy": { - "properties": { - "id": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, "error": { "properties": { "code": { @@ -4360,9 +3997,6 @@ "ignore_above": 1, "type": "keyword" }, - "entry_modified": { - "type": "double" - }, "extension": { "ignore_above": 1024, "type": "keyword" @@ -4399,154 +4033,6 @@ "ignore_above": 1024, "type": "keyword" }, - "macro": { - "properties": { - "code_page": { - "type": "long" - }, - "collection": { - "properties": { - "hash": { - "properties": { - "md5": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha1": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha256": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha512": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "errors": { - "properties": { - "count": { - "type": "long" - }, - "error_type": { - "ignore_above": 1024, - "type": "keyword" - } - }, - "type": "nested" - }, - "file_extension": { - "ignore_above": 1024, - "type": "keyword" - }, - "project_file": { - "properties": { - "hash": { - "properties": { - "md5": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha1": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha256": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha512": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "stream": { - "properties": { - "hash": { - "properties": { - "md5": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha1": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha256": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha512": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "raw_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "raw_code_size": { - "ignore_above": 1024, - "type": "keyword" - } - }, - "type": "nested" - } - } - }, - "malware_classification": { - "properties": { - "features": { - "properties": { - "data": { - "properties": { - "buffer": { - "ignore_above": 1024, - "type": "keyword" - }, - "decompressed_size": { - "type": "integer" - }, - "encoding": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "identifier": { - "ignore_above": 1024, - "type": "keyword" - }, - "score": { - "type": "double" - }, - "threshold": { - "type": "double" - }, - "upx_packed": { - "type": "boolean" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "mime_type": { "ignore_above": 1024, "type": "keyword" @@ -4578,10 +4064,6 @@ }, "pe": { "properties": { - "architecture": { - "ignore_above": 1024, - "type": "keyword" - }, "company": { "ignore_above": 1024, "type": "keyword" @@ -4594,10 +4076,6 @@ "ignore_above": 1024, "type": "keyword" }, - "imphash": { - "ignore_above": 1024, - "type": "keyword" - }, "original_file_name": { "ignore_above": 1024, "type": "keyword" @@ -4608,13 +4086,6 @@ } } }, - "quarantine_path": { - "ignore_above": 1024, - "type": "keyword" - }, - "quarantine_result": { - "type": "boolean" - }, "size": { "type": "long" }, @@ -4628,10 +4099,6 @@ "ignore_above": 1024, "type": "keyword" }, - "temp_file_path": { - "ignore_above": 1024, - "type": "keyword" - }, "type": { "ignore_above": 1024, "type": "keyword" @@ -4639,112 +4106,41 @@ "uid": { "ignore_above": 1024, "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" }, - "x509": { - "properties": { - "alternative_names": { - "ignore_above": 1024, - "type": "keyword" - }, - "issuer": { - "properties": { - "common_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country": { - "ignore_above": 1024, - "type": "keyword" - }, - "distinguished_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "locality": { - "ignore_above": 1024, - "type": "keyword" - }, - "organization": { - "ignore_above": 1024, - "type": "keyword" - }, - "organizational_unit": { - "ignore_above": 1024, - "type": "keyword" - }, - "state_or_province": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "not_after": { - "type": "date" - }, - "not_before": { - "type": "date" - }, - "public_key_algorithm": { - "ignore_above": 1024, - "type": "keyword" - }, - "public_key_curve": { - "ignore_above": 1024, - "type": "keyword" - }, - "public_key_exponent": { - "doc_values": false, - "index": false, - "type": "long" - }, - "public_key_size": { - "type": "long" - }, - "serial_number": { - "ignore_above": 1024, - "type": "keyword" - }, - "signature_algorithm": { - "ignore_above": 1024, - "type": "keyword" - }, - "subject": { - "properties": { - "common_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country": { - "ignore_above": 1024, - "type": "keyword" - }, - "distinguished_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "locality": { - "ignore_above": 1024, - "type": "keyword" - }, - "organization": { - "ignore_above": 1024, - "type": "keyword" - }, - "organizational_unit": { - "ignore_above": 1024, - "type": "keyword" - }, - "state_or_province": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "version_number": { - "ignore_above": 1024, - "type": "keyword" - } - } + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" } } }, @@ -4764,6 +4160,26 @@ } } }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, "host": { "properties": { "architecture": { @@ -4862,10 +4278,6 @@ "ignore_above": 1024, "type": "keyword" }, - "variant": { - "ignore_above": 1024, - "type": "keyword" - }, "version": { "ignore_above": 1024, "type": "keyword" @@ -4995,10 +4407,6 @@ }, "status_code": { "type": "long" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" } } }, @@ -5008,19 +4416,27 @@ } } }, + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, "labels": { "type": "object" }, "log": { "properties": { - "file": { - "properties": { - "path": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "level": { "ignore_above": 1024, "type": "keyword" @@ -5320,10 +4736,6 @@ "ignore_above": 1024, "type": "keyword" }, - "variant": { - "ignore_above": 1024, - "type": "keyword" - }, "version": { "ignore_above": 1024, "type": "keyword" @@ -5370,6 +4782,46 @@ } } }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, "package": { "properties": { "architecture": { @@ -5424,6 +4876,30 @@ } } }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, "process": { "properties": { "args": { @@ -5501,46 +4977,6 @@ } } }, - "malware_classification": { - "properties": { - "features": { - "properties": { - "data": { - "properties": { - "buffer": { - "ignore_above": 1024, - "type": "keyword" - }, - "decompressed_size": { - "type": "integer" - }, - "encoding": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "identifier": { - "ignore_above": 1024, - "type": "keyword" - }, - "score": { - "type": "double" - }, - "threshold": { - "type": "double" - }, - "upx_packed": { - "type": "boolean" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "name": { "fields": { "text": { @@ -5688,10 +5124,6 @@ }, "pe": { "properties": { - "architecture": { - "ignore_above": 1024, - "type": "keyword" - }, "company": { "ignore_above": 1024, "type": "keyword" @@ -5704,10 +5136,6 @@ "ignore_above": 1024, "type": "keyword" }, - "imphash": { - "ignore_above": 1024, - "type": "keyword" - }, "original_file_name": { "ignore_above": 1024, "type": "keyword" @@ -5727,132 +5155,17 @@ "ppid": { "type": "long" }, - "services": { - "ignore_above": 1024, - "type": "keyword" - }, "start": { "type": "date" }, "thread": { "properties": { - "call_stack": { - "properties": { - "instruction_pointer": { - "ignore_above": 1024, - "type": "keyword" - }, - "memory_section": { - "properties": { - "address": { - "ignore_above": 1024, - "type": "keyword" - }, - "protection": { - "ignore_above": 1024, - "type": "keyword" - }, - "size": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "module_path": { - "ignore_above": 1024, - "type": "keyword" - }, - "rva": { - "ignore_above": 1024, - "type": "keyword" - }, - "symbol_info": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "id": { "type": "long" }, "name": { "ignore_above": 1024, "type": "keyword" - }, - "service": { - "ignore_above": 1024, - "type": "keyword" - }, - "start": { - "type": "date" - }, - "start_address": { - "ignore_above": 1024, - "type": "keyword" - }, - "start_address_module": { - "ignore_above": 1024, - "type": "keyword" - }, - "token": { - "properties": { - "domain": { - "ignore_above": 1024, - "type": "keyword" - }, - "elevation": { - "type": "boolean" - }, - "elevation_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "impersonation_level": { - "ignore_above": 1024, - "type": "keyword" - }, - "integrity_level": { - "type": "long" - }, - "integrity_level_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "is_appcontainer": { - "type": "boolean" - }, - "privileges": { - "properties": { - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - }, - "type": "nested" - }, - "sid": { - "ignore_above": 1024, - "type": "keyword" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "uptime": { - "type": "long" } } }, @@ -5866,70 +5179,9 @@ "ignore_above": 1024, "type": "keyword" }, - "token": { - "properties": { - "domain": { - "ignore_above": 1024, - "type": "keyword" - }, - "elevation": { - "type": "boolean" - }, - "elevation_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "impersonation_level": { - "ignore_above": 1024, - "type": "keyword" - }, - "integrity_level": { - "type": "long" - }, - "integrity_level_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "is_appcontainer": { - "type": "boolean" - }, - "privileges": { - "properties": { - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - }, - "type": "nested" - }, - "sid": { - "ignore_above": 1024, - "type": "keyword" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, "uptime": { "type": "long" }, - "user": { - "ignore_above": 1024, - "type": "keyword" - }, "working_directory": { "fields": { "text": { @@ -6342,6 +5594,12 @@ }, "rule": { "properties": { + "author": { + "type": "keyword" + }, + "building_block_type": { + "type": "keyword" + }, "created_at": { "type": "date" }, @@ -6378,6 +5636,9 @@ "language": { "type": "keyword" }, + "license": { + "type": "keyword" + }, "max_signals": { "type": "keyword" }, @@ -6399,15 +5660,47 @@ "risk_score": { "type": "keyword" }, + "risk_score_mapping": { + "properties": { + "field": { + "type": "keyword" + }, + "operator": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, "rule_id": { "type": "keyword" }, + "rule_name_override": { + "type": "keyword" + }, "saved_id": { "type": "keyword" }, "severity": { "type": "keyword" }, + "severity_mapping": { + "properties": { + "field": { + "type": "keyword" + }, + "operator": { + "type": "keyword" + }, + "severity": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, "size": { "type": "keyword" }, @@ -6453,6 +5746,9 @@ "timeline_title": { "type": "keyword" }, + "timestamp_override": { + "type": "keyword" + }, "to": { "type": "keyword" }, @@ -6637,663 +5933,6 @@ "ignore_above": 1024, "type": "keyword" }, - "target": { - "properties": { - "dll": { - "properties": { - "code_signature": { - "properties": { - "exists": { - "type": "boolean" - }, - "status": { - "ignore_above": 1024, - "type": "keyword" - }, - "subject_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "trusted": { - "type": "boolean" - }, - "valid": { - "type": "boolean" - } - } - }, - "compile_time": { - "type": "date" - }, - "hash": { - "properties": { - "md5": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha1": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha256": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha512": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "malware_classification": { - "properties": { - "features": { - "properties": { - "data": { - "properties": { - "buffer": { - "ignore_above": 1024, - "type": "keyword" - }, - "decompressed_size": { - "type": "integer" - }, - "encoding": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "identifier": { - "ignore_above": 1024, - "type": "keyword" - }, - "score": { - "type": "double" - }, - "threshold": { - "type": "double" - }, - "upx_packed": { - "type": "boolean" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "mapped_address": { - "ignore_above": 1024, - "type": "keyword" - }, - "mapped_size": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "path": { - "ignore_above": 1024, - "type": "keyword" - }, - "pe": { - "properties": { - "architecture": { - "ignore_above": 1024, - "type": "keyword" - }, - "company": { - "ignore_above": 1024, - "type": "keyword" - }, - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "file_version": { - "ignore_above": 1024, - "type": "keyword" - }, - "imphash": { - "ignore_above": 1024, - "type": "keyword" - }, - "original_file_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "product": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "process": { - "properties": { - "args": { - "ignore_above": 1024, - "type": "keyword" - }, - "args_count": { - "type": "long" - }, - "code_signature": { - "properties": { - "exists": { - "type": "boolean" - }, - "status": { - "ignore_above": 1024, - "type": "keyword" - }, - "subject_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "trusted": { - "type": "boolean" - }, - "valid": { - "type": "boolean" - } - } - }, - "command_line": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "entity_id": { - "ignore_above": 1024, - "type": "keyword" - }, - "executable": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "exit_code": { - "type": "long" - }, - "hash": { - "properties": { - "md5": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha1": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha256": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha512": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "malware_classification": { - "properties": { - "features": { - "properties": { - "data": { - "properties": { - "buffer": { - "ignore_above": 1024, - "type": "keyword" - }, - "decompressed_size": { - "type": "integer" - }, - "encoding": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, - "identifier": { - "ignore_above": 1024, - "type": "keyword" - }, - "score": { - "type": "double" - }, - "threshold": { - "type": "double" - }, - "upx_packed": { - "type": "boolean" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "name": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "parent": { - "properties": { - "args": { - "ignore_above": 1024, - "type": "keyword" - }, - "args_count": { - "type": "long" - }, - "code_signature": { - "properties": { - "exists": { - "type": "boolean" - }, - "status": { - "ignore_above": 1024, - "type": "keyword" - }, - "subject_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "trusted": { - "type": "boolean" - }, - "valid": { - "type": "boolean" - } - } - }, - "command_line": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "entity_id": { - "ignore_above": 1024, - "type": "keyword" - }, - "executable": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "exit_code": { - "type": "long" - }, - "hash": { - "properties": { - "md5": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha1": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha256": { - "ignore_above": 1024, - "type": "keyword" - }, - "sha512": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "name": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "pgid": { - "type": "long" - }, - "pid": { - "type": "long" - }, - "ppid": { - "type": "long" - }, - "start": { - "type": "date" - }, - "thread": { - "properties": { - "id": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "title": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "uptime": { - "type": "long" - }, - "working_directory": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "pe": { - "properties": { - "architecture": { - "ignore_above": 1024, - "type": "keyword" - }, - "company": { - "ignore_above": 1024, - "type": "keyword" - }, - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "file_version": { - "ignore_above": 1024, - "type": "keyword" - }, - "imphash": { - "ignore_above": 1024, - "type": "keyword" - }, - "original_file_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "product": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "pgid": { - "type": "long" - }, - "pid": { - "type": "long" - }, - "ppid": { - "type": "long" - }, - "services": { - "ignore_above": 1024, - "type": "keyword" - }, - "start": { - "type": "date" - }, - "thread": { - "properties": { - "call_stack": { - "properties": { - "instruction_pointer": { - "ignore_above": 1024, - "type": "keyword" - }, - "memory_section": { - "properties": { - "address": { - "ignore_above": 1024, - "type": "keyword" - }, - "protection": { - "ignore_above": 1024, - "type": "keyword" - }, - "size": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "module_path": { - "ignore_above": 1024, - "type": "keyword" - }, - "rva": { - "ignore_above": 1024, - "type": "keyword" - }, - "symbol_info": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "id": { - "type": "long" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "service": { - "ignore_above": 1024, - "type": "keyword" - }, - "start": { - "type": "date" - }, - "start_address": { - "ignore_above": 1024, - "type": "keyword" - }, - "start_address_module": { - "ignore_above": 1024, - "type": "keyword" - }, - "token": { - "properties": { - "domain": { - "ignore_above": 1024, - "type": "keyword" - }, - "elevation": { - "type": "boolean" - }, - "elevation_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "impersonation_level": { - "ignore_above": 1024, - "type": "keyword" - }, - "integrity_level": { - "type": "long" - }, - "integrity_level_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "is_appcontainer": { - "type": "boolean" - }, - "privileges": { - "properties": { - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - }, - "type": "nested" - }, - "sid": { - "ignore_above": 1024, - "type": "keyword" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "uptime": { - "type": "long" - } - } - }, - "title": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "token": { - "properties": { - "domain": { - "ignore_above": 1024, - "type": "keyword" - }, - "elevation": { - "type": "boolean" - }, - "elevation_type": { - "ignore_above": 1024, - "type": "keyword" - }, - "impersonation_level": { - "ignore_above": 1024, - "type": "keyword" - }, - "integrity_level": { - "type": "long" - }, - "integrity_level_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "is_appcontainer": { - "type": "boolean" - }, - "privileges": { - "properties": { - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - } - }, - "type": "nested" - }, - "sid": { - "ignore_above": 1024, - "type": "keyword" - }, - "type": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "uptime": { - "type": "long" - }, - "user": { - "ignore_above": 1024, - "type": "keyword" - }, - "working_directory": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - }, "threat": { "properties": { "framework": { @@ -7397,112 +6036,6 @@ "supported_ciphers": { "ignore_above": 1024, "type": "keyword" - }, - "x509": { - "properties": { - "alternative_names": { - "ignore_above": 1024, - "type": "keyword" - }, - "issuer": { - "properties": { - "common_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country": { - "ignore_above": 1024, - "type": "keyword" - }, - "distinguished_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "locality": { - "ignore_above": 1024, - "type": "keyword" - }, - "organization": { - "ignore_above": 1024, - "type": "keyword" - }, - "organizational_unit": { - "ignore_above": 1024, - "type": "keyword" - }, - "state_or_province": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "not_after": { - "type": "date" - }, - "not_before": { - "type": "date" - }, - "public_key_algorithm": { - "ignore_above": 1024, - "type": "keyword" - }, - "public_key_curve": { - "ignore_above": 1024, - "type": "keyword" - }, - "public_key_exponent": { - "doc_values": false, - "index": false, - "type": "long" - }, - "public_key_size": { - "type": "long" - }, - "serial_number": { - "ignore_above": 1024, - "type": "keyword" - }, - "signature_algorithm": { - "ignore_above": 1024, - "type": "keyword" - }, - "subject": { - "properties": { - "common_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country": { - "ignore_above": 1024, - "type": "keyword" - }, - "distinguished_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "locality": { - "ignore_above": 1024, - "type": "keyword" - }, - "organization": { - "ignore_above": 1024, - "type": "keyword" - }, - "organizational_unit": { - "ignore_above": 1024, - "type": "keyword" - }, - "state_or_province": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "version_number": { - "ignore_above": 1024, - "type": "keyword" - } - } } } }, @@ -7563,112 +6096,6 @@ "subject": { "ignore_above": 1024, "type": "keyword" - }, - "x509": { - "properties": { - "alternative_names": { - "ignore_above": 1024, - "type": "keyword" - }, - "issuer": { - "properties": { - "common_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country": { - "ignore_above": 1024, - "type": "keyword" - }, - "distinguished_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "locality": { - "ignore_above": 1024, - "type": "keyword" - }, - "organization": { - "ignore_above": 1024, - "type": "keyword" - }, - "organizational_unit": { - "ignore_above": 1024, - "type": "keyword" - }, - "state_or_province": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "not_after": { - "type": "date" - }, - "not_before": { - "type": "date" - }, - "public_key_algorithm": { - "ignore_above": 1024, - "type": "keyword" - }, - "public_key_curve": { - "ignore_above": 1024, - "type": "keyword" - }, - "public_key_exponent": { - "doc_values": false, - "index": false, - "type": "long" - }, - "public_key_size": { - "type": "long" - }, - "serial_number": { - "ignore_above": 1024, - "type": "keyword" - }, - "signature_algorithm": { - "ignore_above": 1024, - "type": "keyword" - }, - "subject": { - "properties": { - "common_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country": { - "ignore_above": 1024, - "type": "keyword" - }, - "distinguished_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "locality": { - "ignore_above": 1024, - "type": "keyword" - }, - "organization": { - "ignore_above": 1024, - "type": "keyword" - }, - "organizational_unit": { - "ignore_above": 1024, - "type": "keyword" - }, - "state_or_province": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "version_number": { - "ignore_above": 1024, - "type": "keyword" - } - } } } }, @@ -7879,10 +6306,6 @@ "ignore_above": 1024, "type": "keyword" }, - "variant": { - "ignore_above": 1024, - "type": "keyword" - }, "version": { "ignore_above": 1024, "type": "keyword" @@ -7895,6 +6318,18 @@ } } }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, "vulnerability": { "properties": { "category": { diff --git a/x-pack/test/security_solution_cypress/es_archives/export_rule/data.json.gz b/x-pack/test/security_solution_cypress/es_archives/export_rule/data.json.gz new file mode 100644 index 000000000000..9501cf5e0586 Binary files /dev/null and b/x-pack/test/security_solution_cypress/es_archives/export_rule/data.json.gz differ diff --git a/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json b/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json new file mode 100644 index 000000000000..6d7c1777d1e7 --- /dev/null +++ b/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json @@ -0,0 +1,6415 @@ +{ + "type": "index", + "value": { + "aliases": { + ".kibana": { + } + }, + "index": ".kibana_1", + "mappings": { + "_meta": { + "migrationMappingPropertyHashes": { + "action": "6e96ac5e648f57523879661ea72525b7", + "action_task_params": "a9d49f184ee89641044be0ca2950fa3a", + "alert": "7b44fba6773e37c806ce290ea9b7024e", + "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", + "apm-telemetry": "3525d7c22c42bc80f5e6e9cb3f2b26a2", + "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724", + "application_usage_transactional": "43b8830d5d0df85a6823d290885fc9fd", + "canvas-element": "7390014e1091044523666d97247392fc", + "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", + "canvas-workpad-template": "ae2673f678281e2c055d764b153e9715", + "cases": "32aa96a6d3855ddda53010ae2048ac22", + "cases-comments": "c2061fb929f585df57425102fa928b4b", + "cases-configure": "42711cbb311976c0687853f4c1354572", + "cases-user-actions": "32277330ec6b721abe3b846cfd939a71", + "config": "c63748b75f39d0c54de12d12c1ccbc20", + "dashboard": "d00f614b29a80360e1190193fd333bab", + "endpoint:exceptions-artifact": "053713a6b91811c7de078ead17384914", + "endpoint:exceptions-manifest": "67c28185da541c1404e7852d30498cd6", + "epm-packages": "04696e7dba1b9597f7d6ed78a4a76658", + "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", + "fleet-agent-actions": "00fe5651ed2da16b7f8159bbf0f7d910", + "fleet-agent-events": "3231653fafe4ef3196fe3b32ab774bf2", + "fleet-agents": "578bbfa81650206927683ebde0c85409", + "fleet-enrollment-api-keys": "451e5c329b3ae9722dc7bc8f5921e05d", + "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", + "index-pattern": "66eccb05066c5a89924f48a9e9736499", + "infrastructure-ui-source": "2b2809653635caf490c93f090502d04c", + "ingest-agent-configs": "9326f99c977fd2ef5ab24b6336a0675c", + "ingest-outputs": "87da6a0e27b3a61ad389fb7a7e2da293", + "ingest-package-configs": "48e8bd97e488008e21c0b5a2367b83ad", + "ingest_manager_settings": "c5b0749b4ab03c582efd4c14cb8f132c", + "inventory-view": "88fc7e12fd1b45b6f0787323ce4f18d2", + "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", + "lens": "d33c68a69ff1e78c9888dedd2164ac22", + "lens-ui-telemetry": "509bfa5978586998e05f9e303c07a327", + "map": "4a05b35c3a3a58fbc72dd0202dc3487f", + "maps-telemetry": "5ef305b18111b77789afefbd36b66171", + "metrics-explorer-view": "a8df1d270ee48c969d22d23812d08187", + "migrationVersion": "4a1746014a75ade3a714e1db5763276f", + "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", + "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", + "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", + "references": "7997cf5a56cc02bdc9c93361bde732b0", + "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", + "search": "181661168bbadd1eff5902361e2a0d5c", + "siem-detection-engine-rule-actions": "6569b288c169539db10cb262bf79de18", + "siem-detection-engine-rule-status": "ae783f41c6937db6b7a2ef5c93a9e9b0", + "siem-ui-timeline": "17ec409954864e592ceec0c5eae29ad9", + "siem-ui-timeline-note": "8874706eedc49059d4cf0f5094559084", + "siem-ui-timeline-pinned-event": "20638091112f0e14f0e443d512301c29", + "space": "c5ca8acafa0beaa4d08d014a97b6bc6b", + "telemetry": "36a616f7026dfa617d6655df850fe16d", + "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf", + "tsvb-validation-telemetry": "3a37ef6c8700ae6fc97d5c7da00e9215", + "type": "2f4316de49999235636386fe51dc06c1", + "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", + "updated_at": "00da57df13e94e9d98437d13ace4bfe0", + "upgrade-assistant-reindex-operation": "296a89039fc4260292be36b1b005d8f2", + "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", + "uptime-dynamic-settings": "fcdb453a30092f022f2642db29523d80", + "url": "c7f66a0df8b1b52f17c28c4adb111105", + "visualization": "52d7a13ad68a150c4525b292d23e12cc" + } + }, + "dynamic": "strict", + "properties": { + "action": { + "properties": { + "actionTypeId": { + "type": "keyword" + }, + "config": { + "enabled": false, + "type": "object" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "secrets": { + "type": "binary" + } + } + }, + "action_task_params": { + "properties": { + "actionId": { + "type": "keyword" + }, + "apiKey": { + "type": "binary" + }, + "params": { + "enabled": false, + "type": "object" + } + } + }, + "alert": { + "properties": { + "actions": { + "properties": { + "actionRef": { + "type": "keyword" + }, + "actionTypeId": { + "type": "keyword" + }, + "group": { + "type": "keyword" + }, + "params": { + "enabled": false, + "type": "object" + } + }, + "type": "nested" + }, + "alertTypeId": { + "type": "keyword" + }, + "apiKey": { + "type": "binary" + }, + "apiKeyOwner": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "createdAt": { + "type": "date" + }, + "createdBy": { + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "muteAll": { + "type": "boolean" + }, + "mutedInstanceIds": { + "type": "keyword" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "params": { + "enabled": false, + "type": "object" + }, + "schedule": { + "properties": { + "interval": { + "type": "keyword" + } + } + }, + "scheduledTaskId": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "throttle": { + "type": "keyword" + }, + "updatedBy": { + "type": "keyword" + } + } + }, + "apm-indices": { + "properties": { + "apm_oss": { + "properties": { + "errorIndices": { + "type": "keyword" + }, + "metricsIndices": { + "type": "keyword" + }, + "onboardingIndices": { + "type": "keyword" + }, + "sourcemapIndices": { + "type": "keyword" + }, + "spanIndices": { + "type": "keyword" + }, + "transactionIndices": { + "type": "keyword" + } + } + } + } + }, + "apm-telemetry": { + "properties": { + "agents": { + "properties": { + "dotnet": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "go": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "java": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "js-base": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "nodejs": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "python": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "ruby": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "rum-js": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + } + } + }, + "cardinality": { + "properties": { + "transaction": { + "properties": { + "name": { + "properties": { + "all_agents": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + }, + "user_agent": { + "properties": { + "original": { + "properties": { + "all_agents": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + } + } + }, + "counts": { + "properties": { + "agent_configuration": { + "properties": { + "all": { + "type": "long" + } + } + }, + "error": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "max_error_groups_per_service": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "max_transaction_groups_per_service": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "onboarding": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "services": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "sourcemap": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "span": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "traces": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "transaction": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + } + } + }, + "has_any_services": { + "type": "boolean" + }, + "indices": { + "properties": { + "all": { + "properties": { + "total": { + "properties": { + "docs": { + "properties": { + "count": { + "type": "long" + } + } + }, + "store": { + "properties": { + "size_in_bytes": { + "type": "long" + } + } + } + } + } + } + }, + "shards": { + "properties": { + "total": { + "type": "long" + } + } + } + } + }, + "integrations": { + "properties": { + "ml": { + "properties": { + "all_jobs_count": { + "type": "long" + } + } + } + } + }, + "retainment": { + "properties": { + "error": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "onboarding": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "span": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "transaction": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "services_per_agent": { + "properties": { + "dotnet": { + "null_value": 0, + "type": "long" + }, + "go": { + "null_value": 0, + "type": "long" + }, + "java": { + "null_value": 0, + "type": "long" + }, + "js-base": { + "null_value": 0, + "type": "long" + }, + "nodejs": { + "null_value": 0, + "type": "long" + }, + "python": { + "null_value": 0, + "type": "long" + }, + "ruby": { + "null_value": 0, + "type": "long" + }, + "rum-js": { + "null_value": 0, + "type": "long" + } + } + }, + "tasks": { + "properties": { + "agent_configuration": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "agents": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "cardinality": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "groupings": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "indices_stats": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "integrations": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "processor_events": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "services": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "versions": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + } + } + }, + "version": { + "properties": { + "apm_server": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + }, + "patch": { + "type": "long" + } + } + } + } + } + } + }, + "application_usage_totals": { + "dynamic": "false", + "type": "object" + }, + "application_usage_transactional": { + "dynamic": "false", + "properties": { + "timestamp": { + "type": "date" + } + } + }, + "canvas-element": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "content": { + "type": "text" + }, + "help": { + "type": "text" + }, + "image": { + "type": "text" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "canvas-workpad": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "canvas-workpad-template": { + "dynamic": "false", + "properties": { + "help": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "tags": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "template_key": { + "type": "keyword" + } + } + }, + "cases": { + "properties": { + "closed_at": { + "type": "date" + }, + "closed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "connector_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "description": { + "type": "text" + }, + "external_service": { + "properties": { + "connector_id": { + "type": "keyword" + }, + "connector_name": { + "type": "keyword" + }, + "external_id": { + "type": "keyword" + }, + "external_title": { + "type": "text" + }, + "external_url": { + "type": "text" + }, + "pushed_at": { + "type": "date" + }, + "pushed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "status": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-comments": { + "properties": { + "comment": { + "type": "text" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "pushed_at": { + "type": "date" + }, + "pushed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-configure": { + "properties": { + "closure_type": { + "type": "keyword" + }, + "connector_id": { + "type": "keyword" + }, + "connector_name": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-user-actions": { + "properties": { + "action": { + "type": "keyword" + }, + "action_at": { + "type": "date" + }, + "action_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "action_field": { + "type": "keyword" + }, + "new_value": { + "type": "text" + }, + "old_value": { + "type": "text" + } + } + }, + "config": { + "dynamic": "false", + "properties": { + "buildNum": { + "type": "keyword" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "endpoint:exceptions-artifact": { + "properties": { + "body": { + "type": "binary" + }, + "created": { + "index": false, + "type": "date" + }, + "encoding": { + "index": false, + "type": "keyword" + }, + "identifier": { + "type": "keyword" + }, + "sha256": { + "type": "keyword" + }, + "size": { + "index": false, + "type": "long" + } + } + }, + "endpoint:exceptions-manifest": { + "properties": { + "created": { + "index": false, + "type": "date" + }, + "ids": { + "index": false, + "type": "keyword" + } + } + }, + "epm-packages": { + "properties": { + "es_index_patterns": { + "enabled": false, + "type": "object" + }, + "installed": { + "properties": { + "id": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "internal": { + "type": "boolean" + }, + "name": { + "type": "keyword" + }, + "removable": { + "type": "boolean" + }, + "version": { + "type": "keyword" + } + } + }, + "file-upload-telemetry": { + "properties": { + "filesUploadedTotalCount": { + "type": "long" + } + } + }, + "fleet-agent-actions": { + "properties": { + "agent_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "data": { + "type": "binary" + }, + "sent_at": { + "type": "date" + }, + "type": { + "type": "keyword" + } + } + }, + "fleet-agent-events": { + "properties": { + "action_id": { + "type": "keyword" + }, + "agent_id": { + "type": "keyword" + }, + "config_id": { + "type": "keyword" + }, + "data": { + "type": "text" + }, + "message": { + "type": "text" + }, + "payload": { + "type": "text" + }, + "stream_id": { + "type": "keyword" + }, + "subtype": { + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + } + } + }, + "fleet-agents": { + "properties": { + "access_api_key_id": { + "type": "keyword" + }, + "active": { + "type": "boolean" + }, + "config_id": { + "type": "keyword" + }, + "config_newest_revision": { + "type": "integer" + }, + "config_revision": { + "type": "integer" + }, + "current_error_events": { + "index": false, + "type": "text" + }, + "default_api_key": { + "type": "binary" + }, + "default_api_key_id": { + "type": "keyword" + }, + "enrolled_at": { + "type": "date" + }, + "last_checkin": { + "type": "date" + }, + "last_updated": { + "type": "date" + }, + "local_metadata": { + "type": "flattened" + }, + "packages": { + "type": "keyword" + }, + "shared_id": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "user_provided_metadata": { + "type": "flattened" + }, + "version": { + "type": "keyword" + } + } + }, + "fleet-enrollment-api-keys": { + "properties": { + "active": { + "type": "boolean" + }, + "api_key": { + "type": "binary" + }, + "api_key_id": { + "type": "keyword" + }, + "config_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "expire_at": { + "type": "date" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + } + } + }, + "graph-workspace": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "numLinks": { + "type": "integer" + }, + "numVertices": { + "type": "integer" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "wsState": { + "type": "text" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "type": { + "type": "keyword" + }, + "typeMeta": { + "type": "keyword" + } + } + }, + "infrastructure-ui-source": { + "properties": { + "description": { + "type": "text" + }, + "fields": { + "properties": { + "container": { + "type": "keyword" + }, + "host": { + "type": "keyword" + }, + "pod": { + "type": "keyword" + }, + "tiebreaker": { + "type": "keyword" + }, + "timestamp": { + "type": "keyword" + } + } + }, + "inventoryDefaultView": { + "type": "keyword" + }, + "logAlias": { + "type": "keyword" + }, + "logColumns": { + "properties": { + "fieldColumn": { + "properties": { + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + } + } + }, + "messageColumn": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "timestampColumn": { + "properties": { + "id": { + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "metricAlias": { + "type": "keyword" + }, + "metricsExplorerDefaultView": { + "type": "keyword" + }, + "name": { + "type": "text" + } + } + }, + "ingest-agent-configs": { + "properties": { + "description": { + "type": "text" + }, + "is_default": { + "type": "boolean" + }, + "monitoring_enabled": { + "index": false, + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "namespace": { + "type": "keyword" + }, + "package_configs": { + "type": "keyword" + }, + "revision": { + "type": "integer" + }, + "status": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + } + } + }, + "ingest-outputs": { + "properties": { + "ca_sha256": { + "index": false, + "type": "keyword" + }, + "config": { + "type": "flattened" + }, + "fleet_enroll_password": { + "type": "binary" + }, + "fleet_enroll_username": { + "type": "binary" + }, + "hosts": { + "type": "keyword" + }, + "is_default": { + "type": "boolean" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "ingest-package-configs": { + "properties": { + "config_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "enabled": { + "type": "boolean" + }, + "inputs": { + "enabled": false, + "properties": { + "config": { + "type": "flattened" + }, + "enabled": { + "type": "boolean" + }, + "streams": { + "properties": { + "compiled_stream": { + "type": "flattened" + }, + "config": { + "type": "flattened" + }, + "dataset": { + "properties": { + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "enabled": { + "type": "boolean" + }, + "id": { + "type": "keyword" + }, + "vars": { + "type": "flattened" + } + }, + "type": "nested" + }, + "type": { + "type": "keyword" + }, + "vars": { + "type": "flattened" + } + }, + "type": "nested" + }, + "name": { + "type": "keyword" + }, + "namespace": { + "type": "keyword" + }, + "output_id": { + "type": "keyword" + }, + "package": { + "properties": { + "name": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "revision": { + "type": "integer" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + } + } + }, + "ingest_manager_settings": { + "properties": { + "agent_auto_upgrade": { + "type": "keyword" + }, + "kibana_ca_sha256": { + "type": "keyword" + }, + "kibana_url": { + "type": "keyword" + }, + "package_auto_upgrade": { + "type": "keyword" + } + } + }, + "inventory-view": { + "properties": { + "accountId": { + "type": "keyword" + }, + "autoBounds": { + "type": "boolean" + }, + "autoReload": { + "type": "boolean" + }, + "boundsOverride": { + "properties": { + "max": { + "type": "integer" + }, + "min": { + "type": "integer" + } + } + }, + "customMetrics": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "customOptions": { + "properties": { + "field": { + "type": "keyword" + }, + "text": { + "type": "keyword" + } + }, + "type": "nested" + }, + "filterQuery": { + "properties": { + "expression": { + "type": "keyword" + }, + "kind": { + "type": "keyword" + } + } + }, + "groupBy": { + "properties": { + "field": { + "type": "keyword" + }, + "label": { + "type": "keyword" + } + }, + "type": "nested" + }, + "legend": { + "properties": { + "palette": { + "type": "keyword" + }, + "reverseColors": { + "type": "boolean" + }, + "steps": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + }, + "nodeType": { + "type": "keyword" + }, + "region": { + "type": "keyword" + }, + "sort": { + "properties": { + "by": { + "type": "keyword" + }, + "direction": { + "type": "keyword" + } + } + }, + "time": { + "type": "long" + }, + "view": { + "type": "keyword" + } + } + }, + "kql-telemetry": { + "properties": { + "optInCount": { + "type": "long" + }, + "optOutCount": { + "type": "long" + } + } + }, + "lens": { + "properties": { + "description": { + "type": "text" + }, + "expression": { + "index": false, + "type": "keyword" + }, + "state": { + "type": "flattened" + }, + "title": { + "type": "text" + }, + "visualizationType": { + "type": "keyword" + } + } + }, + "lens-ui-telemetry": { + "properties": { + "count": { + "type": "integer" + }, + "date": { + "type": "date" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "map": { + "properties": { + "description": { + "type": "text" + }, + "layerListJSON": { + "type": "text" + }, + "mapStateJSON": { + "type": "text" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "maps-telemetry": { + "enabled": false, + "type": "object" + }, + "metrics-explorer-view": { + "properties": { + "chartOptions": { + "properties": { + "stack": { + "type": "boolean" + }, + "type": { + "type": "keyword" + }, + "yAxisMode": { + "type": "keyword" + } + } + }, + "currentTimerange": { + "properties": { + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "to": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + }, + "options": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "filterQuery": { + "type": "keyword" + }, + "forceInterval": { + "type": "boolean" + }, + "groupBy": { + "type": "keyword" + }, + "limit": { + "type": "integer" + }, + "metrics": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "color": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "label": { + "type": "keyword" + } + }, + "type": "nested" + }, + "source": { + "type": "keyword" + } + } + } + } + }, + "migrationVersion": { + "dynamic": "true", + "properties": { + "alert": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "config": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "dashboard": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "index-pattern": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "map": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "search": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "space": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "visualization": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "ml-telemetry": { + "properties": { + "file_data_visualizer": { + "properties": { + "index_creation_count": { + "type": "long" + } + } + } + } + }, + "namespace": { + "type": "keyword" + }, + "namespaces": { + "type": "keyword" + }, + "query": { + "properties": { + "description": { + "type": "text" + }, + "filters": { + "enabled": false, + "type": "object" + }, + "query": { + "properties": { + "language": { + "type": "keyword" + }, + "query": { + "index": false, + "type": "keyword" + } + } + }, + "timefilter": { + "enabled": false, + "type": "object" + }, + "title": { + "type": "text" + } + } + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "sample-data-telemetry": { + "properties": { + "installCount": { + "type": "long" + }, + "unInstallCount": { + "type": "long" + } + } + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "dynamic": "strict", + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "siem-detection-engine-rule-actions": { + "properties": { + "actions": { + "properties": { + "action_type_id": { + "type": "keyword" + }, + "group": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "params": { + "enabled": false, + "type": "object" + } + } + }, + "alertThrottle": { + "type": "keyword" + }, + "ruleAlertId": { + "type": "keyword" + }, + "ruleThrottle": { + "type": "keyword" + } + } + }, + "siem-detection-engine-rule-status": { + "properties": { + "alertId": { + "type": "keyword" + }, + "bulkCreateTimeDurations": { + "type": "float" + }, + "gap": { + "type": "text" + }, + "lastFailureAt": { + "type": "date" + }, + "lastFailureMessage": { + "type": "text" + }, + "lastLookBackDate": { + "type": "date" + }, + "lastSuccessAt": { + "type": "date" + }, + "lastSuccessMessage": { + "type": "text" + }, + "searchAfterTimeDurations": { + "type": "float" + }, + "status": { + "type": "keyword" + }, + "statusDate": { + "type": "date" + } + } + }, + "siem-ui-timeline": { + "properties": { + "columns": { + "properties": { + "aggregatable": { + "type": "boolean" + }, + "category": { + "type": "keyword" + }, + "columnHeaderType": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "example": { + "type": "text" + }, + "id": { + "type": "keyword" + }, + "indexes": { + "type": "keyword" + }, + "name": { + "type": "text" + }, + "placeholder": { + "type": "text" + }, + "searchable": { + "type": "boolean" + }, + "type": { + "type": "keyword" + } + } + }, + "created": { + "type": "date" + }, + "createdBy": { + "type": "text" + }, + "dataProviders": { + "properties": { + "and": { + "properties": { + "enabled": { + "type": "boolean" + }, + "excluded": { + "type": "boolean" + }, + "id": { + "type": "keyword" + }, + "kqlQuery": { + "type": "text" + }, + "name": { + "type": "text" + }, + "queryMatch": { + "properties": { + "displayField": { + "type": "text" + }, + "displayValue": { + "type": "text" + }, + "field": { + "type": "text" + }, + "operator": { + "type": "text" + }, + "value": { + "type": "text" + } + } + } + } + }, + "enabled": { + "type": "boolean" + }, + "excluded": { + "type": "boolean" + }, + "id": { + "type": "keyword" + }, + "kqlQuery": { + "type": "text" + }, + "name": { + "type": "text" + }, + "queryMatch": { + "properties": { + "displayField": { + "type": "text" + }, + "displayValue": { + "type": "text" + }, + "field": { + "type": "text" + }, + "operator": { + "type": "text" + }, + "value": { + "type": "text" + } + } + } + } + }, + "dateRange": { + "properties": { + "end": { + "type": "date" + }, + "start": { + "type": "date" + } + } + }, + "description": { + "type": "text" + }, + "eventType": { + "type": "keyword" + }, + "favorite": { + "properties": { + "favoriteDate": { + "type": "date" + }, + "fullName": { + "type": "text" + }, + "keySearch": { + "type": "text" + }, + "userName": { + "type": "text" + } + } + }, + "filters": { + "properties": { + "exists": { + "type": "text" + }, + "match_all": { + "type": "text" + }, + "meta": { + "properties": { + "alias": { + "type": "text" + }, + "controlledBy": { + "type": "text" + }, + "disabled": { + "type": "boolean" + }, + "field": { + "type": "text" + }, + "formattedValue": { + "type": "text" + }, + "index": { + "type": "keyword" + }, + "key": { + "type": "keyword" + }, + "negate": { + "type": "boolean" + }, + "params": { + "type": "text" + }, + "type": { + "type": "keyword" + }, + "value": { + "type": "text" + } + } + }, + "missing": { + "type": "text" + }, + "query": { + "type": "text" + }, + "range": { + "type": "text" + }, + "script": { + "type": "text" + } + } + }, + "kqlMode": { + "type": "keyword" + }, + "kqlQuery": { + "properties": { + "filterQuery": { + "properties": { + "kuery": { + "properties": { + "expression": { + "type": "text" + }, + "kind": { + "type": "keyword" + } + } + }, + "serializedQuery": { + "type": "text" + } + } + } + } + }, + "savedQueryId": { + "type": "keyword" + }, + "sort": { + "properties": { + "columnId": { + "type": "keyword" + }, + "sortDirection": { + "type": "keyword" + } + } + }, + "status": { + "type": "keyword" + }, + "templateTimelineId": { + "type": "text" + }, + "templateTimelineVersion": { + "type": "integer" + }, + "timelineType": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "updated": { + "type": "date" + }, + "updatedBy": { + "type": "text" + } + } + }, + "siem-ui-timeline-note": { + "properties": { + "created": { + "type": "date" + }, + "createdBy": { + "type": "text" + }, + "eventId": { + "type": "keyword" + }, + "note": { + "type": "text" + }, + "timelineId": { + "type": "keyword" + }, + "updated": { + "type": "date" + }, + "updatedBy": { + "type": "text" + } + } + }, + "siem-ui-timeline-pinned-event": { + "properties": { + "created": { + "type": "date" + }, + "createdBy": { + "type": "text" + }, + "eventId": { + "type": "keyword" + }, + "timelineId": { + "type": "keyword" + }, + "updated": { + "type": "date" + }, + "updatedBy": { + "type": "text" + } + } + }, + "space": { + "properties": { + "_reserved": { + "type": "boolean" + }, + "color": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "disabledFeatures": { + "type": "keyword" + }, + "imageUrl": { + "index": false, + "type": "text" + }, + "initials": { + "type": "keyword" + }, + "name": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "spaceId": { + "type": "keyword" + }, + "telemetry": { + "properties": { + "allowChangingOptInStatus": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "lastReported": { + "type": "date" + }, + "lastVersionChecked": { + "type": "keyword" + }, + "reportFailureCount": { + "type": "integer" + }, + "reportFailureVersion": { + "type": "keyword" + }, + "sendUsageFrom": { + "type": "keyword" + }, + "userHasSeenNotice": { + "type": "boolean" + } + } + }, + "timelion-sheet": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "tsvb-validation-telemetry": { + "properties": { + "failedRequests": { + "type": "long" + } + } + }, + "type": { + "type": "keyword" + }, + "ui-metric": { + "properties": { + "count": { + "type": "integer" + } + } + }, + "updated_at": { + "type": "date" + }, + "upgrade-assistant-reindex-operation": { + "properties": { + "errorMessage": { + "type": "keyword" + }, + "indexName": { + "type": "keyword" + }, + "lastCompletedStep": { + "type": "integer" + }, + "locked": { + "type": "date" + }, + "newIndexName": { + "type": "keyword" + }, + "reindexOptions": { + "properties": { + "openAndClose": { + "type": "boolean" + }, + "queueSettings": { + "properties": { + "queuedAt": { + "type": "long" + }, + "startedAt": { + "type": "long" + } + } + } + } + }, + "reindexTaskId": { + "type": "keyword" + }, + "reindexTaskPercComplete": { + "type": "float" + }, + "runningReindexCount": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "upgrade-assistant-telemetry": { + "properties": { + "features": { + "properties": { + "deprecation_logging": { + "properties": { + "enabled": { + "null_value": true, + "type": "boolean" + } + } + } + } + }, + "ui_open": { + "properties": { + "cluster": { + "null_value": 0, + "type": "long" + }, + "indices": { + "null_value": 0, + "type": "long" + }, + "overview": { + "null_value": 0, + "type": "long" + } + } + }, + "ui_reindex": { + "properties": { + "close": { + "null_value": 0, + "type": "long" + }, + "open": { + "null_value": 0, + "type": "long" + }, + "start": { + "null_value": 0, + "type": "long" + }, + "stop": { + "null_value": 0, + "type": "long" + } + } + } + } + }, + "uptime-dynamic-settings": { + "properties": { + "certAgeThreshold": { + "type": "long" + }, + "certExpirationThreshold": { + "type": "long" + }, + "heartbeatIndices": { + "type": "keyword" + } + } + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchRefName": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".siem-signals-default": { + "is_write_index": true + } + }, + "index": ".siem-signals-default-000001", + "mappings": { + "dynamic": "false", + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "client": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "container": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "image": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "tag": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "runtime": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "ttl": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "header_flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "op_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "question": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "norms": false, + "type": "text" + }, + "stack_trace": { + "doc_values": false, + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "index": false, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "doc_values": false, + "ignore_above": 1024, + "index": false, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "bytes": { + "type": "long" + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "bytes": { + "type": "long" + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "level": { + "ignore_above": 1024, + "type": "keyword" + }, + "logger": { + "ignore_above": 1024, + "type": "keyword" + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "integer" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "function": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "original": { + "doc_values": false, + "ignore_above": 1024, + "index": false, + "type": "keyword" + }, + "syslog": { + "properties": { + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "priority": { + "type": "long" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "message": { + "norms": false, + "type": "text" + }, + "network": { + "properties": { + "application": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vendor": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "organization": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "build_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "checksum": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "install_scope": { + "ignore_above": 1024, + "type": "keyword" + }, + "installed": { + "type": "date" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "related": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "service": { + "properties": { + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "signal": { + "properties": { + "ancestors": { + "properties": { + "depth": { + "type": "long" + }, + "id": { + "type": "keyword" + }, + "rule": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "original_event": { + "properties": { + "action": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "code": { + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "kind": { + "type": "keyword" + }, + "module": { + "type": "keyword" + }, + "original": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "outcome": { + "type": "keyword" + }, + "provider": { + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "original_time": { + "type": "date" + }, + "parent": { + "properties": { + "depth": { + "type": "long" + }, + "id": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "rule": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "building_block_type": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "false_positives": { + "type": "keyword" + }, + "filters": { + "type": "object" + }, + "from": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "immutable": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "max_signals": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "text" + }, + "output_index": { + "type": "keyword" + }, + "query": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "risk_score": { + "type": "keyword" + }, + "risk_score_mapping": { + "properties": { + "field": { + "type": "keyword" + }, + "operator": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "saved_id": { + "type": "keyword" + }, + "severity": { + "type": "keyword" + }, + "severity_mapping": { + "properties": { + "field": { + "type": "keyword" + }, + "operator": { + "type": "keyword" + }, + "severity": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "size": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "framework": { + "type": "keyword" + }, + "tactic": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + } + } + }, + "timeline_id": { + "type": "keyword" + }, + "timeline_title": { + "type": "keyword" + }, + "timestamp_override": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "status": { + "type": "keyword" + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "tags": { + "ignore_above": 1024, + "type": "keyword" + }, + "threat": { + "properties": { + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "ignore_above": 1024, + "type": "keyword" + }, + "client": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "supported_ciphers": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3s": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + }, + "version_protocol": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "trace": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "transaction": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vulnerability": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "classification": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "enumeration": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "report_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner": { + "properties": { + "vendor": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "severity": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "lifecycle": { + "name": ".siem-signals-default", + "rollover_alias": ".siem-signals-default" + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 7e4478038953..5efea82e84c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9550,20 +9550,10 @@ can-use-dom@^0.1.0: resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo= -caniuse-lite@^1.0.30000984, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001022: - version "1.0.30001022" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz#9eeffe580c3a8f110b7b1742dcf06a395885e4c6" - integrity sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A== - -caniuse-lite@^1.0.30001035: - version "1.0.30001036" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001036.tgz#930ea5272010d8bf190d859159d757c0b398caf0" - integrity sha512-jU8CIFIj2oR7r4W+5AKcsvWNVIb6Q6OZE3UsrXrZBHFtreT4YgTeOJtTucp+zSedEpTi3L5wASSP0LYIE3if6w== - -caniuse-lite@^1.0.30001043: - version "1.0.30001079" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001079.tgz#ed3e5225cd9a6850984fdd88bf24ce45d69b9c22" - integrity sha512-2KaYheg0iOY+CMmDuAB3DHehrXhhb4OZU4KBVGDr/YKyYAcpudaiUQ9PJ9rxrPlKEoJ3ATasQ5AN48MqpwS43Q== +caniuse-lite@^1.0.30000984, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001022, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001043: + version "1.0.30001094" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001094.tgz#0b11d02e1cdc201348dbd8e3e57bd9b6ce82b175" + integrity sha512-ufHZNtMaDEuRBpTbqD93tIQnngmJ+oBknjvr0IbFympSdtFpAUFmNv4mVKbb53qltxFx0nK3iy32S9AqkLzUNA== canvas@^2.6.1: version "2.6.1" @@ -10379,6 +10369,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-convert@~0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" + integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0= + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -11444,6 +11439,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssfontparser@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/cssfontparser/-/cssfontparser-1.2.1.tgz#f4022fc8f9700c68029d542084afbaf425a3f3e3" + integrity sha1-9AIvyPlwDGgCnVQghK+69CWj8+M= + csso@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" @@ -18922,6 +18922,14 @@ iterall@^1.2.2: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== +jest-canvas-mock@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.2.0.tgz#45fbc58589c6ce9df50dc90bd8adce747cbdada7" + integrity sha512-DcJdchb7eWFZkt6pvyceWWnu3lsp5QWbUeXiKgEMhwB3sMm5qHM1GQhDajvJgBeiYpgKcojbzZ53d/nz6tXvJw== + dependencies: + cssfontparser "^1.2.1" + parse-color "^1.0.0" + jest-changed-files@^25.5.0: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.5.0.tgz#141cc23567ceb3f534526f8614ba39421383634c" @@ -23755,6 +23763,13 @@ parse-bmfont-xml@^1.1.4: xml-parse-from-string "^1.0.0" xml2js "^0.4.5" +parse-color@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619" + integrity sha1-e3SLlag/A/FqlPU15S1/PZRlhhk= + dependencies: + color-convert "~0.5.0" + parse-entities@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890"