From 809ec9764929aca307e769c4fc31a8941cd33fef Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Mon, 6 Apr 2020 15:37:45 -0500 Subject: [PATCH 1/8] [DOCS] Removed references to left (#60807) * [DOCS] Removed references to left * Fixed broken build --- docs/apm/transactions.asciidoc | 4 +--- docs/canvas/canvas-elements.asciidoc | 4 +++- docs/canvas/canvas-present-workpad.asciidoc | 4 ++-- docs/canvas/canvas-share-workpad.asciidoc | 8 ++++---- .../searchprofiler/getting-started.asciidoc | 12 ++++++------ docs/discover/document-data.asciidoc | 2 +- docs/getting-started/tutorial-visualizing.asciidoc | 2 +- docs/infrastructure/view-metrics.asciidoc | 8 -------- docs/management/managing-licenses.asciidoc | 3 +-- docs/spaces/index.asciidoc | 4 ++-- docs/user/dashboard.asciidoc | 2 +- docs/user/discover.asciidoc | 4 ++-- docs/visualize/lens.asciidoc | 12 ++++-------- 13 files changed, 28 insertions(+), 41 deletions(-) diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index 536ab2ec29c80f..5c92afa55109d5 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -103,9 +103,7 @@ The number of requests per bucket is displayed when hovering over the graph, and [role="screenshot"] image::apm/images/apm-transaction-duration-dist.png[Example view of transactions duration distribution graph] -Most of the requests fall into buckets on the left side of the graph, -with a long tail of smaller buckets to the right. -This is a typical distribution, and indicates most of our requests were served quickly - awesome! +This graph shows a typical distribution, and indicates most of our requests were served quickly - awesome! It's the requests on the right, the ones taking longer than average, that we probably want to focus on. When you select one of these buckets, you're presented with up to ten trace samples. diff --git a/docs/canvas/canvas-elements.asciidoc b/docs/canvas/canvas-elements.asciidoc index 163579d5763b2e..a25460a20eb50c 100644 --- a/docs/canvas/canvas-elements.asciidoc +++ b/docs/canvas/canvas-elements.asciidoc @@ -138,7 +138,9 @@ To apply CSS overrides: . Next to *Element style*, click *+*, then select *CSS*. -. Enter the *CSS*. For example, to center the Markdown element, enter: +. Enter the *CSS*. ++ +For example, to center the Markdown element, enter: + [source,text] -------------------------------------------------- diff --git a/docs/canvas/canvas-present-workpad.asciidoc b/docs/canvas/canvas-present-workpad.asciidoc index 486686cd857b5e..9cd4ecc9519e15 100644 --- a/docs/canvas/canvas-present-workpad.asciidoc +++ b/docs/canvas/canvas-present-workpad.asciidoc @@ -8,7 +8,7 @@ When you are ready to present your workpad, use and enable the presentation opti [[view-fullscreen-mode]] ==== View your workpad in fullscreen mode -In the upper left corner, click the *Enter fullscreen mode* icon. +Click the *Enter fullscreen mode* icon. [role="screenshot"] image::images/canvas-fullscreen.png[Fullscreen mode] @@ -19,7 +19,7 @@ image::images/canvas-fullscreen.png[Fullscreen mode] Automatically cycle through your workpads pages in fullscreen mode. -. In the upper left corner, click the *Control settings* icon. +. Click the *Control settings* icon. . Under *Change cycling interval*, select the interval you want to use. + diff --git a/docs/canvas/canvas-share-workpad.asciidoc b/docs/canvas/canvas-share-workpad.asciidoc index dbba12865b8ca7..ee29926914ad61 100644 --- a/docs/canvas/canvas-share-workpad.asciidoc +++ b/docs/canvas/canvas-share-workpad.asciidoc @@ -10,7 +10,7 @@ When you've finished your workpad, you can share it outside of {kib}. Create a JSON file of your workpad that you can export outside of {kib}. -. From your workpad, click the *Share workpad* icon in the upper left corner. +. From your workpad, click the *Share workpad* icon. . Select *Download as JSON*. + @@ -27,7 +27,7 @@ If you have a license that supports the {report-features}, you can create a PDF For more information, refer to <>. -. From your workpad, click the *Share workpad* icon in the upper left corner, then select *PDF reports*. +. From your workpad, click the *Share workpad* icon, then select *PDF reports*. . Click *Generate PDF*. + @@ -42,7 +42,7 @@ If you have a license that supports the {report-features}, you can create a POST For more information, refer to <>. -. From your workpad, click the *Share workpad* icon in the upper left corner, then select *PDF reports*. +. From your workpad, click the *Share workpad* icon, then select *PDF reports*. . Click *Copy POST URL*. + @@ -55,7 +55,7 @@ image::images/canvas-create-URL.gif[Create POST URL] beta[] Canvas allows you to create _shareables_, which are workpads that you download and securely share on any website. To customize the behavior of the workpad on your website, you can choose to autoplay the pages or hide the workpad toolbar. -. From your workpad, click the *Share this workpad* icon in the upper left corner, then select *Share on a website*. +. From your workpad, click the *Share this workpad* icon, then select *Share on a website*. . On the *Share on a website* pane, follow the instructions. diff --git a/docs/dev-tools/searchprofiler/getting-started.asciidoc b/docs/dev-tools/searchprofiler/getting-started.asciidoc index 2360e4c28ff15a..4a87d4b84b7836 100644 --- a/docs/dev-tools/searchprofiler/getting-started.asciidoc +++ b/docs/dev-tools/searchprofiler/getting-started.asciidoc @@ -3,10 +3,10 @@ === Getting Started The {searchprofiler} is automatically enabled in {kib}. Go to *Dev Tools > Search Profiler* -to get started. +to get started. {searchprofiler} displays the names of the indices searched, the shards in each index, -and how long it took for the query to complete. To try it out, replace the default `match_all` query +and how long it took for the query to complete. To try it out, replace the default `match_all` query with the query you want to profile and click *Profile*. The following example shows the results of profiling the `match_all` query. @@ -29,8 +29,8 @@ While the Cumulative Time metric is useful for comparing the performance of your indices and shards, it doesn't necessarily represent the actual physical query times. ==== -You can select the name of the shard and then click *View details* to see more profiling information, -including details about the query component(s) that ran on the shard, as well as the timing +You can select the name of the shard and then click *View details* to see more profiling information, +including details about the query component(s) that ran on the shard, as well as the timing breakdown of low-level Lucene methods. For more information, see {ref}/search-profile.html#profiling-queries[Profiling queries]. [float] @@ -40,10 +40,10 @@ By default, all queries executed by the {searchprofiler} are sent to `GET /_search`. It searches across your entire cluster (all indices, all types). If you need to query a specific index or type (or several), you can use the Index -and Type filters at the top left. +and Type filters. In the following example, the query is executed against the indices `test` and `kibana_1` and the type `my_type`. This is equivalent making a request to `GET /test,kibana_1/my_type/_search`. [role="screenshot"] -image::dev-tools/searchprofiler/images/filter.png["Filtering by index and type"] \ No newline at end of file +image::dev-tools/searchprofiler/images/filter.png["Filtering by index and type"] diff --git a/docs/discover/document-data.asciidoc b/docs/discover/document-data.asciidoc index 6e9218d66c1154..477c2ec90e95cf 100644 --- a/docs/discover/document-data.asciidoc +++ b/docs/discover/document-data.asciidoc @@ -26,7 +26,7 @@ and click image:images/sort-icon.png[]. The first click sorts by ascending order, the second click sorts by descending order, and the third click removes the field from the sorted fields. -Move a field column:: Hover over the column header and click the move left (<<) or move right icon (>>). +Move a field column:: Hover over the column header and click the (<<) or (>>) icons. Remove a field column :: Hover over the list of *Specified fields* and then click *remove*. Or, use the (x) control in the column header. diff --git a/docs/getting-started/tutorial-visualizing.asciidoc b/docs/getting-started/tutorial-visualizing.asciidoc index a16343aa4850a2..acd4d6d908fd45 100644 --- a/docs/getting-started/tutorial-visualizing.asciidoc +++ b/docs/getting-started/tutorial-visualizing.asciidoc @@ -180,5 +180,5 @@ The map now looks like this: image::images/tutorial-visualize-map-2.png[] . Navigate the map by clicking and dragging. Use the controls -on the left to zoom the map and set filters. +to zoom the map and set filters. . *Save* this map with the name `Map Example`. diff --git a/docs/infrastructure/view-metrics.asciidoc b/docs/infrastructure/view-metrics.asciidoc index bbb981acc3ad6c..1bd64dde76ee13 100644 --- a/docs/infrastructure/view-metrics.asciidoc +++ b/docs/infrastructure/view-metrics.asciidoc @@ -30,11 +30,3 @@ For complete control over the start and end times, click the start time or end t === Refresh the metrics You can click *Refresh* to manually refresh the metrics. - -[float] -[[infra-view-go-to-chart]] -=== Go to a specific chart - -The charts available for this component are shown in a list on the left of the page. Click a chart in the list to quickly go to that chart. - - diff --git a/docs/management/managing-licenses.asciidoc b/docs/management/managing-licenses.asciidoc index 72accdb5fe2aab..a7ed4e942f3f60 100644 --- a/docs/management/managing-licenses.asciidoc +++ b/docs/management/managing-licenses.asciidoc @@ -15,8 +15,7 @@ already activated a trial for 6.0, you cannot start a new trial until 7.0. You can, however, contact `info@elastic.co` to request an extended trial license. -When you activate a new license level, new features appear in the left sidebar -of the *Management* page. +When you activate a new license level, new features appear in *Management*. [role="screenshot"] image::images/management-license.png[] diff --git a/docs/spaces/index.asciidoc b/docs/spaces/index.asciidoc index fb5ef670692dc8..990af3a018b1fb 100644 --- a/docs/spaces/index.asciidoc +++ b/docs/spaces/index.asciidoc @@ -9,10 +9,10 @@ the dashboards and saved objects that belong to that space. {kib} creates a default space for you. After you create your own spaces, you're asked to choose a space when you log in to Kibana. You can change your -current space at any time by using the menu in the upper left. +current space at any time by using the menu. [role="screenshot"] -image::spaces/images/change-space.png["Change current space"] +image::spaces/images/change-space.png["Change current space menu"] Kibana supports spaces in several ways. You can: diff --git a/docs/user/dashboard.asciidoc b/docs/user/dashboard.asciidoc index 490edb9d263381..a17e46c5b3542e 100644 --- a/docs/user/dashboard.asciidoc +++ b/docs/user/dashboard.asciidoc @@ -93,7 +93,7 @@ In *Edit* mode, you can move, resize, customize, and delete panels to suit your * To resize a panel, click the resize control on the lower right and drag to the new dimensions. -* To toggle the use of margins and panel titles, use the *Options* menu in the upper left. +* To toggle the use of margins and panel titles, use the *Options* menu. * To delete a panel, open the panel menu and select *Delete from dashboard.* Deleting a panel from a dashboard does *not* delete the saved visualization or search. diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc index 7de7d73bf16642..4222ba40debb75 100644 --- a/docs/user/discover.asciidoc +++ b/docs/user/discover.asciidoc @@ -24,7 +24,7 @@ image::images/Discover-Start.png[Discover] === Set up your index pattern The first thing to do in *Discover* is to select an <>, which -defines the data you want to explore and visualize. The current index pattern is in the upper left. +defines the data you want to explore and visualize. If you haven't yet created an index pattern, you can add a <>, which has a pre-built index pattern. @@ -69,7 +69,7 @@ image::images/filter-field.png[height=317] The sortable documents table lists the documents that match your search. By default, the table includes columns for the time field and the document `_source`. -To zero in on a specific field, click *add* next to the field name in the left sidebar. +To zero in on a specific field, click *add* next to the field name. For example, if you add the `currency`, `customer_last_name`, and `day_of_week` fields, the document table includes columns for those three fields. diff --git a/docs/visualize/lens.asciidoc b/docs/visualize/lens.asciidoc index e3f61565453b5e..35570ea7ca1dce 100644 --- a/docs/visualize/lens.asciidoc +++ b/docs/visualize/lens.asciidoc @@ -32,7 +32,7 @@ Lens supports the following aggregations: [[drag-drop]] === Drag and drop -The data panel in the left column shows the data fields for the selected time period. When +The panel shows the data fields for the selected time period. When you drag a field from the data panel, Lens highlights where you can drop that field. The first time you drag a data field, you'll see two places highlighted in green: @@ -57,7 +57,7 @@ Lens shows you fields based on the <> you have d {kib}, and the current time range. When you change the index pattern or time filter, the list of fields are updated. -To narrow the list of fields you see in the left panel, you can: +To narrow the list of fields, you can: * Enter the field name in *Search field names*. @@ -100,11 +100,7 @@ still allows you to make the change. Lens allows some customizations of the data for each visualization. -. Change the index pattern. - -.. In the left column, click the index pattern name. - -.. Select the new index pattern. +. Click the index pattern name, then select the new index pattern. + If there is a match, Lens displays the new data. All fields that do not match the index pattern are removed. @@ -147,7 +143,7 @@ Drag and drop your data onto the visualization builder pane. . On the *New Visualization* window, click *Lens*. -. In the left column, select the *kibana_sample_data_ecommerce* index. +. Select the *kibana_sample_data_ecommerce* index. . Click image:images/time-filter-calendar.png[], then click *Last 7 days*. The list of data fields are updated. From e16885c3ad2b3bf6aac3ba0a9dc0548dc5020741 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 7 Apr 2020 00:36:15 +0300 Subject: [PATCH 2/8] [Telemetry] update crypto packages (#62469) * update crypto packages * as type for return value * get default export * add if checks * wrap errors in i18n Co-authored-by: Elastic Machine --- package.json | 2 +- typings/elastic__node_crypto.d.ts | 20 ---------------- .../common/execute_job/decrypt_job_headers.ts | 13 ++++++++--- .../export_types/csv/server/execute_job.ts | 14 ++++++++--- .../server/execute_job.ts | 15 +++++++++++- .../plugins/reporting/server/lib/crypto.ts | 6 ++++- x-pack/legacy/plugins/reporting/types.d.ts | 4 ---- x-pack/package.json | 2 +- .../encrypted_saved_objects_service.test.ts | 7 +++--- .../crypto/encrypted_saved_objects_service.ts | 12 ++++------ x-pack/typings/elastic__node_crypto.d.ts | 7 ------ yarn.lock | 23 ++++++++----------- 12 files changed, 59 insertions(+), 66 deletions(-) delete mode 100644 typings/elastic__node_crypto.d.ts delete mode 100644 x-pack/typings/elastic__node_crypto.d.ts diff --git a/package.json b/package.json index e807cd4d951989..4c5db5321c2823 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.4.0", - "@elastic/request-crypto": "^1.0.2", + "@elastic/request-crypto": "1.1.2", "@elastic/ui-ace": "0.2.3", "@hapi/good-squeeze": "5.2.1", "@hapi/wreck": "^15.0.2", diff --git a/typings/elastic__node_crypto.d.ts b/typings/elastic__node_crypto.d.ts deleted file mode 100644 index 8d4b47da96b738..00000000000000 --- a/typings/elastic__node_crypto.d.ts +++ /dev/null @@ -1,20 +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. - */ - -declare module '@elastic/node-crypto'; diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts index 6f415d7ee5ea93..0436f5d5bc8436 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { cryptoFactory } from '../../../server/lib/crypto'; -import { CryptoFactory, Logger } from '../../../types'; +import { Logger } from '../../../types'; interface HasEncryptedHeaders { headers?: string; @@ -25,9 +25,16 @@ export const decryptJobHeaders = async < job: JobDocPayloadType; logger: Logger; }): Promise> => { - const crypto: CryptoFactory = cryptoFactory(encryptionKey); try { - const decryptedHeaders: Record = await crypto.decrypt(job.headers); + if (typeof job.headers !== 'string') { + throw new Error( + i18n.translate('xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage', { + defaultMessage: 'Job headers are missing', + }) + ); + } + const crypto = cryptoFactory(encryptionKey); + const decryptedHeaders = (await crypto.decrypt(job.headers)) as Record; return decryptedHeaders; } catch (err) { logger.error(err); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index d78d8a8a8010d8..3a282eb0b29746 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -43,9 +43,18 @@ export const executeJobFactory: ExecuteJobFactory { - let decryptedHeaders; try { - decryptedHeaders = await crypto.decrypt(headers); + if (typeof headers !== 'string') { + throw new Error( + i18n.translate( + 'xpack.reporting.exportTypes.csv.executeJob.missingJobHeadersErrorMessage', + { + defaultMessage: 'Job headers are missing', + } + ) + ); + } + return await crypto.decrypt(headers); } catch (err) { logger.error(err); throw new Error( @@ -58,7 +67,6 @@ export const executeJobFactory: ExecuteJobFactory; const serializedEncryptedHeaders = job.headers; try { - decryptedHeaders = await crypto.decrypt(serializedEncryptedHeaders); + if (typeof serializedEncryptedHeaders !== 'string') { + throw new Error( + i18n.translate( + 'xpack.reporting.exportTypes.csv_from_savedobject.executeJob.missingJobHeadersErrorMessage', + { + defaultMessage: 'Job headers are missing', + } + ) + ); + } + decryptedHeaders = (await crypto.decrypt(serializedEncryptedHeaders)) as Record< + string, + unknown + >; } catch (err) { jobLogger.error(err); throw new Error( diff --git a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts index 97876529ecfa71..0394c8ed1fbad7 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts @@ -6,6 +6,10 @@ import nodeCrypto from '@elastic/node-crypto'; -export function cryptoFactory(encryptionKey: string | undefined) { +export function cryptoFactory(encryptionKey?: string) { + if (typeof encryptionKey !== 'string') { + throw new Error('Encryption Key required.'); + } + return nodeCrypto({ encryptionKey }); } diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 09d53278941c91..7334a859005e0c 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -116,10 +116,6 @@ export interface ConditionalHeadersConditions { basePath: string; } -export interface CryptoFactory { - decrypt: (headers?: string) => any; -} - export interface IndexPatternSavedObject { attributes: { fieldFormatMap: string; diff --git a/x-pack/package.json b/x-pack/package.json index 24b23256bf18ea..b2ec4c3dc3f6f0 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -185,7 +185,7 @@ "@elastic/eui": "21.0.1", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.2.0", - "@elastic/node-crypto": "^1.0.0", + "@elastic/node-crypto": "1.1.1", "@elastic/numeral": "2.4.0", "@kbn/babel-preset": "1.0.0", "@kbn/config-schema": "1.0.0", diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts index e1e1a8224aa7b5..be33238a26ee70 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.test.ts @@ -19,9 +19,10 @@ beforeEach(() => { mockAuditLogger = encryptedSavedObjectsAuditLoggerMock.create(); // Call actual `@elastic/node-crypto` by default, but allow to override implementation in tests. - jest - .requireMock('@elastic/node-crypto') - .mockImplementation((...args: any[]) => jest.requireActual('@elastic/node-crypto')(...args)); + jest.requireMock('@elastic/node-crypto').mockImplementation((...args: any[]) => { + const { default: nodeCrypto } = jest.requireActual('@elastic/node-crypto'); + return nodeCrypto(...args); + }); service = new EncryptedSavedObjectsService( 'encryption-key-abc', diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts index 94c16845295774..eea2b12354d9b7 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encrypted_saved_objects_service.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore -import nodeCrypto from '@elastic/node-crypto'; +import nodeCrypto, { Crypto } from '@elastic/node-crypto'; import stringify from 'json-stable-stringify'; import typeDetect from 'type-detect'; import { Logger } from 'src/core/server'; @@ -49,10 +48,7 @@ export function descriptorToArray(descriptor: SavedObjectDescriptor) { * attributes. */ export class EncryptedSavedObjectsService { - private readonly crypto: Readonly<{ - encrypt(valueToEncrypt: T, aad?: string): Promise; - decrypt(valueToDecrypt: string, aad?: string): Promise; - }>; + private readonly crypto: Readonly; /** * Map of all registered saved object types where the `key` is saved object type and the `value` @@ -229,10 +225,10 @@ export class EncryptedSavedObjectsService { } try { - decryptedAttributes[attributeName] = await this.crypto.decrypt( + decryptedAttributes[attributeName] = (await this.crypto.decrypt( attributeValue, encryptionAAD - ); + )) as string; } catch (err) { this.logger.error(`Failed to decrypt "${attributeName}" attribute: ${err.message || err}`); this.audit.decryptAttributeFailure(attributeName, descriptor); diff --git a/x-pack/typings/elastic__node_crypto.d.ts b/x-pack/typings/elastic__node_crypto.d.ts deleted file mode 100644 index 463b662d5b207c..00000000000000 --- a/x-pack/typings/elastic__node_crypto.d.ts +++ /dev/null @@ -1,7 +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. - */ - -declare module '@elastic/node-crypto'; diff --git a/yarn.lock b/yarn.lock index d9edb55a320395..77ab69c715573c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1343,27 +1343,22 @@ resolved "https://registry.yarnpkg.com/@elastic/maki/-/maki-6.2.0.tgz#d0a85aa248bdc14dca44e1f9430c0b670f65e489" integrity sha512-QkmRNpEY4Dy6eqwDimR5X9leMgdPFjdANmpEIwEW1XVUG2U4YtB2BXhDxsnMmNTUrJUjtnjnwgwBUyg0pU0FTg== -"@elastic/node-crypto@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-0.1.2.tgz#c18ac282f635e88f041cc1555d806e492ca8f3b1" - integrity sha1-wYrCgvY16I8EHMFVXYBuSSyo87E= - -"@elastic/node-crypto@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-1.0.0.tgz#4d325df333fe1319556bb4d54214098ada1171d4" - integrity sha512-bbjbEyILPRTRt0xnda18OttLtlkJBPuXx3CjISUSn9jhWqHoFMzfOaZ73D5jxZE2SaFZUrJYfPpqXP6qqPufAQ== +"@elastic/node-crypto@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-1.1.1.tgz#619b70322c9cce4a7ee5fbf8f678b1baa7f06095" + integrity sha512-F6tIk8Txdqjg8Siv60iAvXzO9ZdQI87K3sS/fh5xd2XaWK+T5ZfqeTvsT7srwG6fr6uCBfuQEJV1KBBl+JpLZA== "@elastic/numeral@2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.4.0.tgz#883197b7f4bf3c2dd994f53b274769ddfa2bf79a" integrity sha512-uGBKGCNghTgUZPHClji/00v+AKt5nidPTGOIbcT+lbTPVxNB6QPpPLGWtXyrg3QZAxobPM/LAZB1mAqtJeq44Q== -"@elastic/request-crypto@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@elastic/request-crypto/-/request-crypto-1.0.2.tgz#bf27bf009227166f3eeb2b5193a108752335ebd3" - integrity sha512-8FtGYl7LebhmJmEDWiGn3MorvNiGWSYPqhvgRlKXjNakEuLoPBBe0DHxbwLkj08CMLWczXcO2ixqBPY7fEhJpA== +"@elastic/request-crypto@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@elastic/request-crypto/-/request-crypto-1.1.2.tgz#2e323550f546f6286994126d462a9ea480a3bfb1" + integrity sha512-i73wjj1Qi8dGJIy170Z8xyJ760mFNjTbdmcp/nEczqWD0miNW6I5wZ5MNrv7M6CXn2m1wMXiT6qzDYd93Hv1Dw== dependencies: - "@elastic/node-crypto" "^0.1.2" + "@elastic/node-crypto" "1.1.1" "@types/node-jose" "1.1.0" node-jose "1.1.0" From 29c1aad2bb878b58b61ad8b0c88f106cb2f6976d Mon Sep 17 00:00:00 2001 From: liza-mae Date: Mon, 6 Apr 2020 16:48:37 -0600 Subject: [PATCH 3/8] Fix visual tests (#62660) --- test/scripts/jenkins_visual_regression.sh | 2 +- test/scripts/jenkins_xpack_visual_regression.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/scripts/jenkins_visual_regression.sh b/test/scripts/jenkins_visual_regression.sh index 4fdd197147eac0..c6fefd45b005d1 100755 --- a/test/scripts/jenkins_visual_regression.sh +++ b/test/scripts/jenkins_visual_regression.sh @@ -12,7 +12,7 @@ tar -xzf "$linuxBuild" -C "$installDir" --strip=1 echo " -> running visual regression tests from kibana directory" checks-reporter-with-killswitch "X-Pack visual regression tests" \ - yarn percy exec -t 500 \ + yarn percy exec -t 500 -- -- \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$installDir" \ diff --git a/test/scripts/jenkins_xpack_visual_regression.sh b/test/scripts/jenkins_xpack_visual_regression.sh index 73e92da3bad635..96521ccc8f7873 100755 --- a/test/scripts/jenkins_xpack_visual_regression.sh +++ b/test/scripts/jenkins_xpack_visual_regression.sh @@ -14,7 +14,7 @@ tar -xzf "$linuxBuild" -C "$installDir" --strip=1 echo " -> running visual regression tests from x-pack directory" cd "$XPACK_DIR" checks-reporter-with-killswitch "X-Pack visual regression tests" \ - yarn percy exec -t 500 \ + yarn percy exec -t 500 -- -- \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$installDir" \ From f1bd3bdacb263b2754c04000070fe0f79ab5ed72 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 6 Apr 2020 17:05:09 -0700 Subject: [PATCH 4/8] Revert "[Monitoring] Cluster state watch to Kibana alerting (#61685)" This reverts commit ab0cc8894a924dda18fc8664cf903fdf7a2d9920. --- .../plugins/monitoring/common/constants.ts | 8 +- .../public/components/alerts/alerts.js | 44 +- .../public/components/alerts/status.test.tsx | 8 +- .../public/components/alerts/status.tsx | 2 +- .../cluster/overview/alerts_panel.js | 81 +-- .../monitoring/public/views/alerts/index.js | 30 +- x-pack/plugins/monitoring/common/constants.ts | 8 +- .../server/alerts/cluster_state.test.ts | 186 ------ .../monitoring/server/alerts/cluster_state.ts | 134 ---- .../plugins/monitoring/server/alerts/enums.ts | 16 - .../server/alerts/license_expiration.test.ts | 572 +++++++++++++----- .../server/alerts/license_expiration.ts | 127 ++-- .../monitoring/server/alerts/types.d.ts | 62 +- .../lib/alerts/cluster_state.lib.test.ts | 70 --- .../server/lib/alerts/cluster_state.lib.ts | 88 --- .../lib/alerts/fetch_cluster_state.test.ts | 39 -- .../server/lib/alerts/fetch_cluster_state.ts | 53 -- .../server/lib/alerts/fetch_clusters.test.ts | 46 +- .../server/lib/alerts/fetch_clusters.ts | 41 +- .../server/lib/alerts/fetch_licenses.test.ts | 67 +- .../server/lib/alerts/fetch_licenses.ts | 16 +- .../server/lib/alerts/fetch_status.test.ts | 122 ---- .../server/lib/alerts/fetch_status.ts | 100 +-- .../lib/alerts/get_prepared_alert.test.ts | 163 ----- .../server/lib/alerts/get_prepared_alert.ts | 87 --- .../lib/alerts/license_expiration.lib.test.ts | 23 +- .../lib/alerts/license_expiration.lib.ts | 56 +- .../lib/cluster/get_clusters_from_request.js | 12 +- x-pack/plugins/monitoring/server/plugin.ts | 12 - .../server/routes/api/v1/alerts/alerts.js | 53 +- 30 files changed, 756 insertions(+), 1570 deletions(-) delete mode 100644 x-pack/plugins/monitoring/server/alerts/cluster_state.test.ts delete mode 100644 x-pack/plugins/monitoring/server/alerts/cluster_state.ts delete mode 100644 x-pack/plugins/monitoring/server/alerts/enums.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.test.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.test.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.test.ts delete mode 100644 x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts diff --git a/x-pack/legacy/plugins/monitoring/common/constants.ts b/x-pack/legacy/plugins/monitoring/common/constants.ts index 3a4c7b71dcd03d..9a4030f3eb2147 100644 --- a/x-pack/legacy/plugins/monitoring/common/constants.ts +++ b/x-pack/legacy/plugins/monitoring/common/constants.ts @@ -239,15 +239,11 @@ export const ALERT_TYPE_PREFIX = 'monitoring_'; * This is the alert type id for the license expiration alert */ export const ALERT_TYPE_LICENSE_EXPIRATION = `${ALERT_TYPE_PREFIX}alert_type_license_expiration`; -/** - * This is the alert type id for the cluster state alert - */ -export const ALERT_TYPE_CLUSTER_STATE = `${ALERT_TYPE_PREFIX}alert_type_cluster_state`; /** * A listing of all alert types */ -export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION, ALERT_TYPE_CLUSTER_STATE]; +export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION]; /** * Matches the id for the built-in in email action type @@ -258,7 +254,7 @@ export const ALERT_ACTION_TYPE_EMAIL = '.email'; /** * The number of alerts that have been migrated */ -export const NUMBER_OF_MIGRATED_ALERTS = 2; +export const NUMBER_OF_MIGRATED_ALERTS = 1; /** * The advanced settings config name for the email address diff --git a/x-pack/legacy/plugins/monitoring/public/components/alerts/alerts.js b/x-pack/legacy/plugins/monitoring/public/components/alerts/alerts.js index 95c1af5549198f..11fcef73a4b976 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/alerts/alerts.js +++ b/x-pack/legacy/plugins/monitoring/public/components/alerts/alerts.js @@ -6,15 +6,10 @@ import React from 'react'; import chrome from '../../np_imports/ui/chrome'; -import { capitalize, get } from 'lodash'; +import { capitalize } from 'lodash'; import { formatDateTimeLocal } from '../../../common/formatting'; import { formatTimestampToDuration } from '../../../common'; -import { - CALCULATE_DURATION_SINCE, - EUI_SORT_DESCENDING, - ALERT_TYPE_LICENSE_EXPIRATION, - ALERT_TYPE_CLUSTER_STATE, -} from '../../../common/constants'; +import { CALCULATE_DURATION_SINCE, EUI_SORT_DESCENDING } from '../../../common/constants'; import { mapSeverity } from './map_severity'; import { FormattedAlert } from 'plugins/monitoring/components/alerts/formatted_alert'; import { EuiMonitoringTable } from 'plugins/monitoring/components/table'; @@ -26,8 +21,6 @@ const linkToCategories = { 'elasticsearch/indices': 'Elasticsearch Indices', 'kibana/instances': 'Kibana Instances', 'logstash/instances': 'Logstash Nodes', - [ALERT_TYPE_LICENSE_EXPIRATION]: 'License expiration', - [ALERT_TYPE_CLUSTER_STATE]: 'Cluster state', }; const getColumns = (kbnUrl, scope, timezone) => [ { @@ -101,22 +94,19 @@ const getColumns = (kbnUrl, scope, timezone) => [ }), field: 'message', sortable: true, - render: (_message, alert) => { - const message = get(alert, 'message.text', get(alert, 'message', '')); - return ( - { - scope.$evalAsync(() => { - kbnUrl.changePath(target); - }); - }} - /> - ); - }, + render: (message, alert) => ( + { + scope.$evalAsync(() => { + kbnUrl.changePath(target); + }); + }} + /> + ), }, { name: i18n.translate('xpack.monitoring.alerts.categoryColumnTitle', { @@ -158,8 +148,8 @@ const getColumns = (kbnUrl, scope, timezone) => [ export const Alerts = ({ alerts, angular, sorting, pagination, onTableChange }) => { const alertsFlattened = alerts.map(alert => ({ ...alert, - status: get(alert, 'metadata.severity', get(alert, 'severity', 0)), - category: get(alert, 'metadata.link', get(alert, 'type', null)), + status: alert.metadata.severity, + category: alert.metadata.link, })); const injector = chrome.dangerouslyGetActiveInjector(); diff --git a/x-pack/legacy/plugins/monitoring/public/components/alerts/status.test.tsx b/x-pack/legacy/plugins/monitoring/public/components/alerts/status.test.tsx index d3cf4b463a2cc5..258a5b68db372e 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/alerts/status.test.tsx +++ b/x-pack/legacy/plugins/monitoring/public/components/alerts/status.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { kfetch } from 'ui/kfetch'; import { AlertsStatus, AlertsStatusProps } from './status'; -import { ALERT_TYPES } from '../../../common/constants'; +import { ALERT_TYPE_PREFIX } from '../../../common/constants'; import { getSetupModeState } from '../../lib/setup_mode'; import { mockUseEffects } from '../../jest.helpers'; @@ -63,7 +63,11 @@ describe('Status', () => { it('should render a success message if all alerts have been migrated and in setup mode', async () => { (kfetch as jest.Mock).mockReturnValue({ - data: ALERT_TYPES.map(type => ({ alertTypeId: type })), + data: [ + { + alertTypeId: ALERT_TYPE_PREFIX, + }, + ], }); (getSetupModeState as jest.Mock).mockReturnValue({ diff --git a/x-pack/legacy/plugins/monitoring/public/components/alerts/status.tsx b/x-pack/legacy/plugins/monitoring/public/components/alerts/status.tsx index 5f5329bf7fff83..072a98b1234521 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/alerts/status.tsx +++ b/x-pack/legacy/plugins/monitoring/public/components/alerts/status.tsx @@ -142,7 +142,7 @@ export const AlertsStatus: React.FC = (props: AlertsStatusPro ); } - const allMigrated = kibanaAlerts.length >= NUMBER_OF_MIGRATED_ALERTS; + const allMigrated = kibanaAlerts.length === NUMBER_OF_MIGRATED_ALERTS; if (allMigrated) { if (setupModeEnabled) { return ( diff --git a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/alerts_panel.js b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/alerts_panel.js index d87ff98e79be00..8455fb8cf3088c 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/alerts_panel.js +++ b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/alerts_panel.js @@ -6,12 +6,14 @@ import React, { Fragment } from 'react'; import moment from 'moment-timezone'; +import chrome from '../../../np_imports/ui/chrome'; import { FormattedAlert } from 'plugins/monitoring/components/alerts/formatted_alert'; import { mapSeverity } from 'plugins/monitoring/components/alerts/map_severity'; import { formatTimestampToDuration } from '../../../../common/format_timestamp_to_duration'; import { CALCULATE_DURATION_SINCE, KIBANA_ALERTING_ENABLED, + ALERT_TYPE_LICENSE_EXPIRATION, CALCULATE_DURATION_UNTIL, } from '../../../../common/constants'; import { formatDateTimeLocal } from '../../../../common/formatting'; @@ -29,37 +31,6 @@ import { EuiLink, } from '@elastic/eui'; -function replaceTokens(alert) { - if (!alert.message.tokens) { - return alert.message.text; - } - - let text = alert.message.text; - - for (const token of alert.message.tokens) { - if (token.type === 'time') { - text = text.replace( - token.startToken, - token.isRelative - ? formatTimestampToDuration(alert.expirationTime, CALCULATE_DURATION_UNTIL) - : moment.tz(alert.expirationTime, moment.tz.guess()).format('LLL z') - ); - } else if (token.type === 'link') { - const linkPart = new RegExp(`${token.startToken}(.+?)${token.endToken}`).exec(text); - // TODO: we assume this is at the end, which works for now but will not always work - const nonLinkText = text.replace(linkPart[0], ''); - text = ( - - {nonLinkText} - {linkPart[1]} - - ); - } - } - - return text; -} - export function AlertsPanel({ alerts, changeUrl }) { const goToAlerts = () => changeUrl('/alerts'); @@ -87,6 +58,9 @@ export function AlertsPanel({ alerts, changeUrl }) { severityIcon.iconType = 'check'; } + const injector = chrome.dangerouslyGetActiveInjector(); + const timezone = injector.get('config').get('dateFormat:tz'); + return ( @@ -122,7 +96,14 @@ export function AlertsPanel({ alerts, changeUrl }) { const alertsList = KIBANA_ALERTING_ENABLED ? alerts.map((alert, idx) => { const callOutProps = mapSeverity(alert.severity); - const message = replaceTokens(alert); + let message = alert.message + // scan message prefix and replace relative times + // \w: Matches any alphanumeric character from the basic Latin alphabet, including the underscore. Equivalent to [A-Za-z0-9_]. + .replace( + '#relative', + formatTimestampToDuration(alert.expirationTime, CALCULATE_DURATION_UNTIL) + ) + .replace('#absolute', moment.tz(alert.expirationTime, moment.tz.guess()).format('LLL z')); if (!alert.isFiring) { callOutProps.title = i18n.translate( @@ -137,30 +118,22 @@ export function AlertsPanel({ alerts, changeUrl }) { ); callOutProps.color = 'success'; callOutProps.iconType = 'check'; + } else { + if (alert.type === ALERT_TYPE_LICENSE_EXPIRATION) { + message = ( + + {message} +   + Please update your license + + ); + } } return ( - - -

{message}

- -

- -

-
-
- -
+ +

{message}

+
); }) : alerts.map((item, index) => ( diff --git a/x-pack/legacy/plugins/monitoring/public/views/alerts/index.js b/x-pack/legacy/plugins/monitoring/public/views/alerts/index.js index 62cc985887e9f5..7c065a78a8af98 100644 --- a/x-pack/legacy/plugins/monitoring/public/views/alerts/index.js +++ b/x-pack/legacy/plugins/monitoring/public/views/alerts/index.js @@ -18,37 +18,25 @@ import { Alerts } from '../../components/alerts'; import { MonitoringViewBaseEuiTableController } from '../base_eui_table_controller'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLink } from '@elastic/eui'; -import { CODE_PATH_ALERTS, KIBANA_ALERTING_ENABLED } from '../../../common/constants'; +import { CODE_PATH_ALERTS } from '../../../common/constants'; function getPageData($injector) { const globalState = $injector.get('globalState'); const $http = $injector.get('$http'); const Private = $injector.get('Private'); - const url = KIBANA_ALERTING_ENABLED - ? `../api/monitoring/v1/alert_status` - : `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/legacy_alerts`; + const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/legacy_alerts`; const timeBounds = timefilter.getBounds(); - const data = { - timeRange: { - min: timeBounds.min.toISOString(), - max: timeBounds.max.toISOString(), - }, - }; - - if (!KIBANA_ALERTING_ENABLED) { - data.ccs = globalState.ccs; - } return $http - .post(url, data) - .then(response => { - const result = get(response, 'data', []); - if (KIBANA_ALERTING_ENABLED) { - return result.alerts; - } - return result; + .post(url, { + ccs: globalState.ccs, + timeRange: { + min: timeBounds.min.toISOString(), + max: timeBounds.max.toISOString(), + }, }) + .then(response => get(response, 'data', [])) .catch(err => { const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider); return ajaxErrorHandlers(err); diff --git a/x-pack/plugins/monitoring/common/constants.ts b/x-pack/plugins/monitoring/common/constants.ts index 3a4c7b71dcd03d..9a4030f3eb2147 100644 --- a/x-pack/plugins/monitoring/common/constants.ts +++ b/x-pack/plugins/monitoring/common/constants.ts @@ -239,15 +239,11 @@ export const ALERT_TYPE_PREFIX = 'monitoring_'; * This is the alert type id for the license expiration alert */ export const ALERT_TYPE_LICENSE_EXPIRATION = `${ALERT_TYPE_PREFIX}alert_type_license_expiration`; -/** - * This is the alert type id for the cluster state alert - */ -export const ALERT_TYPE_CLUSTER_STATE = `${ALERT_TYPE_PREFIX}alert_type_cluster_state`; /** * A listing of all alert types */ -export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION, ALERT_TYPE_CLUSTER_STATE]; +export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION]; /** * Matches the id for the built-in in email action type @@ -258,7 +254,7 @@ export const ALERT_ACTION_TYPE_EMAIL = '.email'; /** * The number of alerts that have been migrated */ -export const NUMBER_OF_MIGRATED_ALERTS = 2; +export const NUMBER_OF_MIGRATED_ALERTS = 1; /** * The advanced settings config name for the email address diff --git a/x-pack/plugins/monitoring/server/alerts/cluster_state.test.ts b/x-pack/plugins/monitoring/server/alerts/cluster_state.test.ts deleted file mode 100644 index 6a9ca884373471..00000000000000 --- a/x-pack/plugins/monitoring/server/alerts/cluster_state.test.ts +++ /dev/null @@ -1,186 +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 { Logger } from 'src/core/server'; -import { savedObjectsClientMock } from 'src/core/server/mocks'; -import { getClusterState } from './cluster_state'; -import { AlertServices } from '../../../alerting/server'; -import { ALERT_TYPE_CLUSTER_STATE } from '../../common/constants'; -import { AlertCommonParams, AlertCommonState, AlertClusterStatePerClusterState } from './types'; -import { getPreparedAlert } from '../lib/alerts/get_prepared_alert'; -import { executeActions } from '../lib/alerts/cluster_state.lib'; -import { AlertClusterStateState } from './enums'; - -jest.mock('../lib/alerts/cluster_state.lib', () => ({ - executeActions: jest.fn(), - getUiMessage: jest.fn(), -})); - -jest.mock('../lib/alerts/get_prepared_alert', () => ({ - getPreparedAlert: jest.fn(() => { - return { - emailAddress: 'foo@foo.com', - }; - }), -})); - -interface MockServices { - callCluster: jest.Mock; - alertInstanceFactory: jest.Mock; - savedObjectsClient: jest.Mock; -} - -describe('getClusterState', () => { - const services: MockServices | AlertServices = { - callCluster: jest.fn(), - alertInstanceFactory: jest.fn(), - savedObjectsClient: savedObjectsClientMock.create(), - }; - - const params: AlertCommonParams = { - dateFormat: 'YYYY', - timezone: 'UTC', - }; - - const emailAddress = 'foo@foo.com'; - const clusterUuid = 'kdksdfj434'; - const clusterName = 'monitoring_test'; - const cluster = { clusterUuid, clusterName }; - - async function setupAlert( - previousState: AlertClusterStateState, - newState: AlertClusterStateState - ): Promise { - const logger: Logger = { - warn: jest.fn(), - log: jest.fn(), - debug: jest.fn(), - trace: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - info: jest.fn(), - get: jest.fn(), - }; - const getLogger = (): Logger => logger; - const ccrEnabled = false; - (getPreparedAlert as jest.Mock).mockImplementation(() => ({ - emailAddress, - data: [ - { - state: newState, - clusterUuid, - }, - ], - clusters: [cluster], - })); - - const alert = getClusterState(null as any, null as any, getLogger, ccrEnabled); - const state: AlertCommonState = { - [clusterUuid]: { - state: previousState, - ui: { - isFiring: false, - severity: 0, - message: null, - resolvedMS: 0, - lastCheckedMS: 0, - triggeredMS: 0, - }, - } as AlertClusterStatePerClusterState, - }; - - return (await alert.executor({ services, params, state } as any)) as AlertCommonState; - } - - afterEach(() => { - (executeActions as jest.Mock).mockClear(); - }); - - it('should configure the alert properly', () => { - const alert = getClusterState(null as any, null as any, jest.fn(), false); - expect(alert.id).toBe(ALERT_TYPE_CLUSTER_STATE); - expect(alert.actionGroups).toEqual([{ id: 'default', name: 'Default' }]); - }); - - it('should alert if green -> yellow', async () => { - const result = await setupAlert(AlertClusterStateState.Green, AlertClusterStateState.Yellow); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - AlertClusterStateState.Yellow, - emailAddress - ); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Yellow); - expect(clusterResult.ui.isFiring).toBe(true); - expect(clusterResult.ui.resolvedMS).toBe(0); - }); - - it('should alert if yellow -> green', async () => { - const result = await setupAlert(AlertClusterStateState.Yellow, AlertClusterStateState.Green); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - AlertClusterStateState.Green, - emailAddress, - true - ); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Green); - expect(clusterResult.ui.resolvedMS).toBeGreaterThan(0); - }); - - it('should alert if green -> red', async () => { - const result = await setupAlert(AlertClusterStateState.Green, AlertClusterStateState.Red); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - AlertClusterStateState.Red, - emailAddress - ); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Red); - expect(clusterResult.ui.isFiring).toBe(true); - expect(clusterResult.ui.resolvedMS).toBe(0); - }); - - it('should alert if red -> green', async () => { - const result = await setupAlert(AlertClusterStateState.Red, AlertClusterStateState.Green); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - AlertClusterStateState.Green, - emailAddress, - true - ); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Green); - expect(clusterResult.ui.resolvedMS).toBeGreaterThan(0); - }); - - it('should not alert if red -> yellow', async () => { - const result = await setupAlert(AlertClusterStateState.Red, AlertClusterStateState.Yellow); - expect(executeActions).not.toHaveBeenCalled(); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Red); - expect(clusterResult.ui.resolvedMS).toBe(0); - }); - - it('should not alert if yellow -> red', async () => { - const result = await setupAlert(AlertClusterStateState.Yellow, AlertClusterStateState.Red); - expect(executeActions).not.toHaveBeenCalled(); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Yellow); - expect(clusterResult.ui.resolvedMS).toBe(0); - }); - - it('should not alert if green -> green', async () => { - const result = await setupAlert(AlertClusterStateState.Green, AlertClusterStateState.Green); - expect(executeActions).not.toHaveBeenCalled(); - const clusterResult = result[clusterUuid] as AlertClusterStatePerClusterState; - expect(clusterResult.state).toBe(AlertClusterStateState.Green); - expect(clusterResult.ui.resolvedMS).toBe(0); - }); -}); diff --git a/x-pack/plugins/monitoring/server/alerts/cluster_state.ts b/x-pack/plugins/monitoring/server/alerts/cluster_state.ts deleted file mode 100644 index 9a5805b8af7ced..00000000000000 --- a/x-pack/plugins/monitoring/server/alerts/cluster_state.ts +++ /dev/null @@ -1,134 +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 moment from 'moment-timezone'; -import { i18n } from '@kbn/i18n'; -import { Logger, ICustomClusterClient, UiSettingsServiceStart } from 'src/core/server'; -import { ALERT_TYPE_CLUSTER_STATE } from '../../common/constants'; -import { AlertType } from '../../../alerting/server'; -import { executeActions, getUiMessage } from '../lib/alerts/cluster_state.lib'; -import { - AlertCommonExecutorOptions, - AlertCommonState, - AlertClusterStatePerClusterState, - AlertCommonCluster, -} from './types'; -import { AlertClusterStateState } from './enums'; -import { getPreparedAlert } from '../lib/alerts/get_prepared_alert'; -import { fetchClusterState } from '../lib/alerts/fetch_cluster_state'; - -export const getClusterState = ( - getUiSettingsService: () => Promise, - monitoringCluster: ICustomClusterClient, - getLogger: (...scopes: string[]) => Logger, - ccsEnabled: boolean -): AlertType => { - const logger = getLogger(ALERT_TYPE_CLUSTER_STATE); - return { - id: ALERT_TYPE_CLUSTER_STATE, - name: 'Monitoring Alert - Cluster Status', - actionGroups: [ - { - id: 'default', - name: i18n.translate('xpack.monitoring.alerts.clusterState.actionGroups.default', { - defaultMessage: 'Default', - }), - }, - ], - defaultActionGroupId: 'default', - async executor({ - services, - params, - state, - }: AlertCommonExecutorOptions): Promise { - logger.debug( - `Firing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}` - ); - - const preparedAlert = await getPreparedAlert( - ALERT_TYPE_CLUSTER_STATE, - getUiSettingsService, - monitoringCluster, - logger, - ccsEnabled, - services, - fetchClusterState - ); - - if (!preparedAlert) { - return state; - } - - const { emailAddress, data: states, clusters } = preparedAlert; - - const result: AlertCommonState = { ...state }; - const defaultAlertState: AlertClusterStatePerClusterState = { - state: AlertClusterStateState.Green, - ui: { - isFiring: false, - message: null, - severity: 0, - resolvedMS: 0, - triggeredMS: 0, - lastCheckedMS: 0, - }, - }; - - for (const clusterState of states) { - const alertState: AlertClusterStatePerClusterState = - (state[clusterState.clusterUuid] as AlertClusterStatePerClusterState) || - defaultAlertState; - const cluster = clusters.find( - (c: AlertCommonCluster) => c.clusterUuid === clusterState.clusterUuid - ); - if (!cluster) { - logger.warn(`Unable to find cluster for clusterUuid='${clusterState.clusterUuid}'`); - continue; - } - const isNonGreen = clusterState.state !== AlertClusterStateState.Green; - const severity = clusterState.state === AlertClusterStateState.Red ? 2100 : 1100; - - const ui = alertState.ui; - let triggered = ui.triggeredMS; - let resolved = ui.resolvedMS; - let message = ui.message || {}; - let lastState = alertState.state; - const instance = services.alertInstanceFactory(ALERT_TYPE_CLUSTER_STATE); - - if (isNonGreen) { - if (lastState === AlertClusterStateState.Green) { - logger.debug(`Cluster state changed from green to ${clusterState.state}`); - executeActions(instance, cluster, clusterState.state, emailAddress); - lastState = clusterState.state; - triggered = moment().valueOf(); - } - message = getUiMessage(clusterState.state); - resolved = 0; - } else if (!isNonGreen && lastState !== AlertClusterStateState.Green) { - logger.debug(`Cluster state changed from ${lastState} to green`); - executeActions(instance, cluster, clusterState.state, emailAddress, true); - lastState = clusterState.state; - message = getUiMessage(clusterState.state, true); - resolved = moment().valueOf(); - } - - result[clusterState.clusterUuid] = { - state: lastState, - ui: { - message, - isFiring: isNonGreen, - severity, - resolvedMS: resolved, - triggeredMS: triggered, - lastCheckedMS: moment().valueOf(), - }, - } as AlertClusterStatePerClusterState; - } - - return result; - }, - }; -}; diff --git a/x-pack/plugins/monitoring/server/alerts/enums.ts b/x-pack/plugins/monitoring/server/alerts/enums.ts deleted file mode 100644 index ccff588743af1b..00000000000000 --- a/x-pack/plugins/monitoring/server/alerts/enums.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export enum AlertClusterStateState { - Green = 'green', - Red = 'red', - Yellow = 'yellow', -} - -export enum AlertCommonPerClusterMessageTokenType { - Time = 'time', - Link = 'link', -} diff --git a/x-pack/plugins/monitoring/server/alerts/license_expiration.test.ts b/x-pack/plugins/monitoring/server/alerts/license_expiration.test.ts index 92047e300bc1ff..0773af6e7f070d 100644 --- a/x-pack/plugins/monitoring/server/alerts/license_expiration.test.ts +++ b/x-pack/plugins/monitoring/server/alerts/license_expiration.test.ts @@ -6,31 +6,42 @@ import moment from 'moment-timezone'; import { getLicenseExpiration } from './license_expiration'; -import { ALERT_TYPE_LICENSE_EXPIRATION } from '../../common/constants'; +import { + ALERT_TYPE_LICENSE_EXPIRATION, + MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS, +} from '../../common/constants'; import { Logger } from 'src/core/server'; -import { AlertServices } from '../../../alerting/server'; +import { AlertServices, AlertInstance } from '../../../alerting/server'; import { savedObjectsClientMock } from 'src/core/server/mocks'; import { - AlertCommonParams, - AlertCommonState, - AlertLicensePerClusterState, - AlertLicense, + AlertState, + AlertClusterState, + AlertParams, + LicenseExpirationAlertExecutorOptions, } from './types'; -import { executeActions } from '../lib/alerts/license_expiration.lib'; -import { PreparedAlert, getPreparedAlert } from '../lib/alerts/get_prepared_alert'; - -jest.mock('../lib/alerts/license_expiration.lib', () => ({ - executeActions: jest.fn(), - getUiMessage: jest.fn(), -})); - -jest.mock('../lib/alerts/get_prepared_alert', () => ({ - getPreparedAlert: jest.fn(() => { - return { - emailAddress: 'foo@foo.com', - }; - }), -})); +import { SavedObject, SavedObjectAttributes } from 'src/core/server'; +import { SavedObjectsClientContract } from 'src/core/server'; + +function fillLicense(license: any, clusterUuid?: string) { + return { + hits: { + hits: [ + { + _source: { + license, + cluster_uuid: clusterUuid, + }, + }, + ], + }, + }; +} + +const clusterUuid = 'a4545jhjb'; +const params: AlertParams = { + dateFormat: 'YYYY', + timezone: 'UTC', +}; interface MockServices { callCluster: jest.Mock; @@ -38,169 +49,428 @@ interface MockServices { savedObjectsClient: jest.Mock; } -describe('getLicenseExpiration', () => { - const services: MockServices | AlertServices = { - callCluster: jest.fn(), - alertInstanceFactory: jest.fn(), - savedObjectsClient: savedObjectsClientMock.create(), - }; - - const params: AlertCommonParams = { - dateFormat: 'YYYY', - timezone: 'UTC', - }; +const alertExecutorOptions: LicenseExpirationAlertExecutorOptions = { + alertId: '', + startedAt: new Date(), + services: { + callCluster: (path: string, opts: any) => new Promise(resolve => resolve()), + alertInstanceFactory: (id: string) => new AlertInstance(), + savedObjectsClient: {} as jest.Mocked, + }, + params: {}, + state: {}, + spaceId: '', + name: '', + tags: [], + previousStartedAt: null, + createdBy: null, + updatedBy: null, +}; +describe('getLicenseExpiration', () => { const emailAddress = 'foo@foo.com'; - const clusterUuid = 'kdksdfj434'; - const clusterName = 'monitoring_test'; - const dateFormat = 'YYYY-MM-DD'; - const cluster = { clusterUuid, clusterName }; - const defaultUiState = { - isFiring: false, - severity: 0, - message: null, - resolvedMS: 0, - lastCheckedMS: 0, - triggeredMS: 0, + const getUiSettingsService: any = () => ({ + asScopedToClient: (): any => ({ + get: () => new Promise(resolve => resolve(emailAddress)), + }), + }); + const monitoringCluster: any = null; + const logger: Logger = { + warn: jest.fn(), + log: jest.fn(), + debug: jest.fn(), + trace: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + info: jest.fn(), + get: jest.fn(), }; - - async function setupAlert( - license: AlertLicense | null, - expiredCheckDateMS: number, - preparedAlertResponse: PreparedAlert | null | undefined = undefined - ): Promise { - const logger: Logger = { - warn: jest.fn(), - log: jest.fn(), - debug: jest.fn(), - trace: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - info: jest.fn(), - get: jest.fn(), - }; - const getLogger = (): Logger => logger; - const ccrEnabled = false; - (getPreparedAlert as jest.Mock).mockImplementation(() => { - if (preparedAlertResponse !== undefined) { - return preparedAlertResponse; - } - - return { - emailAddress, - data: [license], - clusters: [cluster], - dateFormat, - }; - }); - - const alert = getLicenseExpiration(null as any, null as any, getLogger, ccrEnabled); - const state: AlertCommonState = { - [clusterUuid]: { - expiredCheckDateMS, - ui: { ...defaultUiState }, - } as AlertLicensePerClusterState, - }; - - return (await alert.executor({ services, params, state } as any)) as AlertCommonState; - } + const getLogger = (): Logger => logger; + const ccrEnabled = false; afterEach(() => { - (executeActions as jest.Mock).mockClear(); - (getPreparedAlert as jest.Mock).mockClear(); + (logger.warn as jest.Mock).mockClear(); }); it('should have the right id and actionGroups', () => { - const alert = getLicenseExpiration(null as any, null as any, jest.fn(), false); + const alert = getLicenseExpiration( + getUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); expect(alert.id).toBe(ALERT_TYPE_LICENSE_EXPIRATION); expect(alert.actionGroups).toEqual([{ id: 'default', name: 'Default' }]); }); it('should return the state if no license is provided', async () => { - const result = await setupAlert(null, 0, null); - expect(result[clusterUuid].ui).toEqual(defaultUiState); + const alert = getLicenseExpiration( + getUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); + + const services: MockServices | AlertServices = { + callCluster: jest.fn(), + alertInstanceFactory: jest.fn(), + savedObjectsClient: savedObjectsClientMock.create(), + }; + const state = { foo: 1 }; + + const result = await alert.executor({ + ...alertExecutorOptions, + services, + params, + state, + }); + + expect(result).toEqual(state); + }); + + it('should log a warning if no email is provided', async () => { + const customGetUiSettingsService: any = () => ({ + asScopedToClient: () => ({ + get: () => null, + }), + }); + const alert = getLicenseExpiration( + customGetUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); + + const services = { + callCluster: jest.fn( + (method: string, { filterPath }): Promise => { + return new Promise(resolve => { + if (filterPath.includes('hits.hits._source.license.*')) { + resolve( + fillLicense({ + status: 'good', + type: 'basic', + expiry_date_in_millis: moment() + .add(7, 'days') + .valueOf(), + }) + ); + } + resolve({}); + }); + } + ), + alertInstanceFactory: jest.fn(), + savedObjectsClient: savedObjectsClientMock.create(), + }; + + const state = {}; + + await alert.executor({ + ...alertExecutorOptions, + services, + params, + state, + }); + + expect((logger.warn as jest.Mock).mock.calls.length).toBe(1); + expect(logger.warn).toHaveBeenCalledWith( + `Unable to send email for ${ALERT_TYPE_LICENSE_EXPIRATION} because there is no email configured.` + ); }); it('should fire actions if going to expire', async () => { - const expiryDateMS = moment() - .add(7, 'days') - .valueOf(); - const license = { - status: 'active', - type: 'gold', - expiryDateMS, - clusterUuid, + const scheduleActions = jest.fn(); + const alertInstanceFactory = jest.fn( + (id: string): AlertInstance => { + const instance = new AlertInstance(); + instance.scheduleActions = scheduleActions; + return instance; + } + ); + + const alert = getLicenseExpiration( + getUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); + + const savedObjectsClient = savedObjectsClientMock.create(); + savedObjectsClient.get.mockReturnValue( + new Promise(resolve => { + const savedObject: SavedObject = { + id: '', + type: '', + references: [], + attributes: { + [MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS]: emailAddress, + }, + }; + resolve(savedObject); + }) + ); + const services = { + callCluster: jest.fn( + (method: string, { filterPath }): Promise => { + return new Promise(resolve => { + if (filterPath.includes('hits.hits._source.license.*')) { + resolve( + fillLicense( + { + status: 'active', + type: 'gold', + expiry_date_in_millis: moment() + .add(7, 'days') + .valueOf(), + }, + clusterUuid + ) + ); + } + resolve({}); + }); + } + ), + alertInstanceFactory, + savedObjectsClient, }; - const result = await setupAlert(license, 0); - const newState = result[clusterUuid] as AlertLicensePerClusterState; + + const state = {}; + + const result: AlertState = (await alert.executor({ + ...alertExecutorOptions, + services, + params, + state, + })) as AlertState; + + const newState: AlertClusterState = result[clusterUuid] as AlertClusterState; + expect(newState.expiredCheckDateMS > 0).toBe(true); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - moment.utc(expiryDateMS), - dateFormat, - emailAddress + expect(scheduleActions.mock.calls.length).toBe(1); + expect(scheduleActions.mock.calls[0][1].subject).toBe( + 'NEW X-Pack Monitoring: License Expiration' ); + expect(scheduleActions.mock.calls[0][1].to).toBe(emailAddress); }); it('should fire actions if the user fixed their license', async () => { - const expiryDateMS = moment() - .add(365, 'days') - .valueOf(); - const license = { - status: 'active', - type: 'gold', - expiryDateMS, - clusterUuid, + const scheduleActions = jest.fn(); + const alertInstanceFactory = jest.fn( + (id: string): AlertInstance => { + const instance = new AlertInstance(); + instance.scheduleActions = scheduleActions; + return instance; + } + ); + const alert = getLicenseExpiration( + getUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); + + const savedObjectsClient = savedObjectsClientMock.create(); + savedObjectsClient.get.mockReturnValue( + new Promise(resolve => { + const savedObject: SavedObject = { + id: '', + type: '', + references: [], + attributes: { + [MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS]: emailAddress, + }, + }; + resolve(savedObject); + }) + ); + const services = { + callCluster: jest.fn( + (method: string, { filterPath }): Promise => { + return new Promise(resolve => { + if (filterPath.includes('hits.hits._source.license.*')) { + resolve( + fillLicense( + { + status: 'active', + type: 'gold', + expiry_date_in_millis: moment() + .add(120, 'days') + .valueOf(), + }, + clusterUuid + ) + ); + } + resolve({}); + }); + } + ), + alertInstanceFactory, + savedObjectsClient, + }; + + const state: AlertState = { + [clusterUuid]: { + expiredCheckDateMS: moment() + .subtract(1, 'day') + .valueOf(), + ui: { isFiring: true, severity: 0, message: null, resolvedMS: 0, expirationTime: 0 }, + }, }; - const result = await setupAlert(license, 100); - const newState = result[clusterUuid] as AlertLicensePerClusterState; + + const result: AlertState = (await alert.executor({ + ...alertExecutorOptions, + services, + params, + state, + })) as AlertState; + + const newState: AlertClusterState = result[clusterUuid] as AlertClusterState; expect(newState.expiredCheckDateMS).toBe(0); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - moment.utc(expiryDateMS), - dateFormat, - emailAddress, - true + expect(scheduleActions.mock.calls.length).toBe(1); + expect(scheduleActions.mock.calls[0][1].subject).toBe( + 'RESOLVED X-Pack Monitoring: License Expiration' ); + expect(scheduleActions.mock.calls[0][1].to).toBe(emailAddress); }); it('should not fire actions for trial license that expire in more than 14 days', async () => { - const expiryDateMS = moment() - .add(20, 'days') - .valueOf(); - const license = { - status: 'active', - type: 'trial', - expiryDateMS, - clusterUuid, + const scheduleActions = jest.fn(); + const alertInstanceFactory = jest.fn( + (id: string): AlertInstance => { + const instance = new AlertInstance(); + instance.scheduleActions = scheduleActions; + return instance; + } + ); + const alert = getLicenseExpiration( + getUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); + + const savedObjectsClient = savedObjectsClientMock.create(); + savedObjectsClient.get.mockReturnValue( + new Promise(resolve => { + const savedObject: SavedObject = { + id: '', + type: '', + references: [], + attributes: { + [MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS]: emailAddress, + }, + }; + resolve(savedObject); + }) + ); + const services = { + callCluster: jest.fn( + (method: string, { filterPath }): Promise => { + return new Promise(resolve => { + if (filterPath.includes('hits.hits._source.license.*')) { + resolve( + fillLicense( + { + status: 'active', + type: 'trial', + expiry_date_in_millis: moment() + .add(15, 'days') + .valueOf(), + }, + clusterUuid + ) + ); + } + resolve({}); + }); + } + ), + alertInstanceFactory, + savedObjectsClient, }; - const result = await setupAlert(license, 0); - const newState = result[clusterUuid] as AlertLicensePerClusterState; - expect(newState.expiredCheckDateMS).toBe(0); - expect(executeActions).not.toHaveBeenCalled(); + + const state = {}; + const result: AlertState = (await alert.executor({ + ...alertExecutorOptions, + services, + params, + state, + })) as AlertState; + + const newState: AlertClusterState = result[clusterUuid] as AlertClusterState; + expect(newState.expiredCheckDateMS).toBe(undefined); + expect(scheduleActions).not.toHaveBeenCalled(); }); it('should fire actions for trial license that in 14 days or less', async () => { - const expiryDateMS = moment() - .add(7, 'days') - .valueOf(); - const license = { - status: 'active', - type: 'trial', - expiryDateMS, - clusterUuid, + const scheduleActions = jest.fn(); + const alertInstanceFactory = jest.fn( + (id: string): AlertInstance => { + const instance = new AlertInstance(); + instance.scheduleActions = scheduleActions; + return instance; + } + ); + const alert = getLicenseExpiration( + getUiSettingsService, + monitoringCluster, + getLogger, + ccrEnabled + ); + + const savedObjectsClient = savedObjectsClientMock.create(); + savedObjectsClient.get.mockReturnValue( + new Promise(resolve => { + const savedObject: SavedObject = { + id: '', + type: '', + references: [], + attributes: { + [MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS]: emailAddress, + }, + }; + resolve(savedObject); + }) + ); + const services = { + callCluster: jest.fn( + (method: string, { filterPath }): Promise => { + return new Promise(resolve => { + if (filterPath.includes('hits.hits._source.license.*')) { + resolve( + fillLicense( + { + status: 'active', + type: 'trial', + expiry_date_in_millis: moment() + .add(13, 'days') + .valueOf(), + }, + clusterUuid + ) + ); + } + resolve({}); + }); + } + ), + alertInstanceFactory, + savedObjectsClient, }; - const result = await setupAlert(license, 0); - const newState = result[clusterUuid] as AlertLicensePerClusterState; + + const state = {}; + const result: AlertState = (await alert.executor({ + ...alertExecutorOptions, + services, + params, + state, + })) as AlertState; + + const newState: AlertClusterState = result[clusterUuid] as AlertClusterState; expect(newState.expiredCheckDateMS > 0).toBe(true); - expect(executeActions).toHaveBeenCalledWith( - undefined, - cluster, - moment.utc(expiryDateMS), - dateFormat, - emailAddress - ); + expect(scheduleActions.mock.calls.length).toBe(1); }); }); diff --git a/x-pack/plugins/monitoring/server/alerts/license_expiration.ts b/x-pack/plugins/monitoring/server/alerts/license_expiration.ts index 2e5356150086b4..93397ff3641ae1 100644 --- a/x-pack/plugins/monitoring/server/alerts/license_expiration.ts +++ b/x-pack/plugins/monitoring/server/alerts/license_expiration.ts @@ -5,20 +5,24 @@ */ import moment from 'moment-timezone'; +import { get } from 'lodash'; import { Logger, ICustomClusterClient, UiSettingsServiceStart } from 'src/core/server'; import { i18n } from '@kbn/i18n'; -import { ALERT_TYPE_LICENSE_EXPIRATION } from '../../common/constants'; +import { ALERT_TYPE_LICENSE_EXPIRATION, INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; import { AlertType } from '../../../../plugins/alerting/server'; import { fetchLicenses } from '../lib/alerts/fetch_licenses'; +import { fetchDefaultEmailAddress } from '../lib/alerts/fetch_default_email_address'; +import { fetchClusters } from '../lib/alerts/fetch_clusters'; +import { fetchAvailableCcs } from '../lib/alerts/fetch_available_ccs'; import { - AlertCommonState, - AlertLicensePerClusterState, - AlertCommonExecutorOptions, - AlertCommonCluster, - AlertLicensePerClusterUiState, + AlertLicense, + AlertState, + AlertClusterState, + AlertClusterUiState, + LicenseExpirationAlertExecutorOptions, } from './types'; +import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { executeActions, getUiMessage } from '../lib/alerts/license_expiration.lib'; -import { getPreparedAlert } from '../lib/alerts/get_prepared_alert'; const EXPIRES_DAYS = [60, 30, 14, 7]; @@ -28,6 +32,14 @@ export const getLicenseExpiration = ( getLogger: (...scopes: string[]) => Logger, ccsEnabled: boolean ): AlertType => { + async function getCallCluster(services: any): Promise { + if (!monitoringCluster) { + return services.callCluster; + } + + return monitoringCluster.callAsInternalUser; + } + const logger = getLogger(ALERT_TYPE_LICENSE_EXPIRATION); return { id: ALERT_TYPE_LICENSE_EXPIRATION, @@ -41,50 +53,54 @@ export const getLicenseExpiration = ( }, ], defaultActionGroupId: 'default', - async executor({ services, params, state }: AlertCommonExecutorOptions): Promise { + async executor({ + services, + params, + state, + }: LicenseExpirationAlertExecutorOptions): Promise { logger.debug( `Firing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}` ); - const preparedAlert = await getPreparedAlert( - ALERT_TYPE_LICENSE_EXPIRATION, - getUiSettingsService, - monitoringCluster, - logger, - ccsEnabled, - services, - fetchLicenses - ); + const callCluster = await getCallCluster(services); + + // Support CCS use cases by querying to find available remote clusters + // and then adding those to the index pattern we are searching against + let esIndexPattern = INDEX_PATTERN_ELASTICSEARCH; + if (ccsEnabled) { + const availableCcs = await fetchAvailableCcs(callCluster); + if (availableCcs.length > 0) { + esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs); + } + } + + const clusters = await fetchClusters(callCluster, esIndexPattern); - if (!preparedAlert) { + // Fetch licensing information from cluster_stats documents + const licenses: AlertLicense[] = await fetchLicenses(callCluster, clusters, esIndexPattern); + if (licenses.length === 0) { + logger.warn(`No license found for ${ALERT_TYPE_LICENSE_EXPIRATION}.`); return state; } - const { emailAddress, data: licenses, clusters, dateFormat } = preparedAlert; + const uiSettings = (await getUiSettingsService()).asScopedToClient( + services.savedObjectsClient + ); + const dateFormat: string = await uiSettings.get('dateFormat'); + const timezone: string = await uiSettings.get('dateFormat:tz'); + const emailAddress = await fetchDefaultEmailAddress(uiSettings); + if (!emailAddress) { + // TODO: we can do more here + logger.warn( + `Unable to send email for ${ALERT_TYPE_LICENSE_EXPIRATION} because there is no email configured.` + ); + return; + } - const result: AlertCommonState = { ...state }; - const defaultAlertState: AlertLicensePerClusterState = { - expiredCheckDateMS: 0, - ui: { - isFiring: false, - message: null, - severity: 0, - resolvedMS: 0, - lastCheckedMS: 0, - triggeredMS: 0, - }, - }; + const result: AlertState = { ...state }; for (const license of licenses) { - const alertState: AlertLicensePerClusterState = - (state[license.clusterUuid] as AlertLicensePerClusterState) || defaultAlertState; - const cluster = clusters.find( - (c: AlertCommonCluster) => c.clusterUuid === license.clusterUuid - ); - if (!cluster) { - logger.warn(`Unable to find cluster for clusterUuid='${license.clusterUuid}'`); - continue; - } + const licenseState: AlertClusterState = state[license.clusterUuid] || {}; const $expiry = moment.utc(license.expiryDateMS); let isExpired = false; let severity = 0; @@ -107,26 +123,31 @@ export const getLicenseExpiration = ( } } - const ui = alertState.ui; - let triggered = ui.triggeredMS; + const ui: AlertClusterUiState = get(licenseState, 'ui', { + isFiring: false, + message: null, + severity: 0, + resolvedMS: 0, + expirationTime: 0, + }); let resolved = ui.resolvedMS; let message = ui.message; - let expiredCheckDate = alertState.expiredCheckDateMS; + let expiredCheckDate = licenseState.expiredCheckDateMS; const instance = services.alertInstanceFactory(ALERT_TYPE_LICENSE_EXPIRATION); if (isExpired) { - if (!alertState.expiredCheckDateMS) { + if (!licenseState.expiredCheckDateMS) { logger.debug(`License will expire soon, sending email`); - executeActions(instance, cluster, $expiry, dateFormat, emailAddress); - expiredCheckDate = triggered = moment().valueOf(); + executeActions(instance, license, $expiry, dateFormat, emailAddress); + expiredCheckDate = moment().valueOf(); } - message = getUiMessage(); + message = getUiMessage(license, timezone); resolved = 0; - } else if (!isExpired && alertState.expiredCheckDateMS) { + } else if (!isExpired && licenseState.expiredCheckDateMS) { logger.debug(`License expiration has been resolved, sending email`); - executeActions(instance, cluster, $expiry, dateFormat, emailAddress, true); + executeActions(instance, license, $expiry, dateFormat, emailAddress, true); expiredCheckDate = 0; - message = getUiMessage(true); + message = getUiMessage(license, timezone, true); resolved = moment().valueOf(); } @@ -138,10 +159,8 @@ export const getLicenseExpiration = ( isFiring: expiredCheckDate > 0, severity, resolvedMS: resolved, - triggeredMS: triggered, - lastCheckedMS: moment().valueOf(), - } as AlertLicensePerClusterUiState, - } as AlertLicensePerClusterState; + }, + }; } return result; diff --git a/x-pack/plugins/monitoring/server/alerts/types.d.ts b/x-pack/plugins/monitoring/server/alerts/types.d.ts index b689d008b51a78..ff47d6f2ad4dca 100644 --- a/x-pack/plugins/monitoring/server/alerts/types.d.ts +++ b/x-pack/plugins/monitoring/server/alerts/types.d.ts @@ -5,79 +5,41 @@ */ import { Moment } from 'moment'; import { AlertExecutorOptions } from '../../../alerting/server'; -import { AlertClusterStateState, AlertCommonPerClusterMessageTokenType } from './enums'; export interface AlertLicense { status: string; type: string; expiryDateMS: number; clusterUuid: string; + clusterName: string; } -export interface AlertClusterState { - state: AlertClusterStateState; - clusterUuid: string; -} - -export interface AlertCommonState { - [clusterUuid: string]: AlertCommonPerClusterState; -} - -export interface AlertCommonPerClusterState { - ui: AlertCommonPerClusterUiState; -} - -export interface AlertClusterStatePerClusterState extends AlertCommonPerClusterState { - state: AlertClusterStateState; +export interface AlertState { + [clusterUuid: string]: AlertClusterState; } -export interface AlertLicensePerClusterState extends AlertCommonPerClusterState { - expiredCheckDateMS: number; +export interface AlertClusterState { + expiredCheckDateMS: number | Moment; + ui: AlertClusterUiState; } -export interface AlertCommonPerClusterUiState { +export interface AlertClusterUiState { isFiring: boolean; severity: number; - message: AlertCommonPerClusterMessage | null; + message: string | null; resolvedMS: number; - lastCheckedMS: number; - triggeredMS: number; -} - -export interface AlertCommonPerClusterMessage { - text: string; // Do this. #link this is a link #link - tokens?: AlertCommonPerClusterMessageToken[]; -} - -export interface AlertCommonPerClusterMessageToken { - startToken: string; - endToken?: string; - type: AlertCommonPerClusterMessageTokenType; -} - -export interface AlertCommonPerClusterMessageLinkToken extends AlertCommonPerClusterMessageToken { - url?: string; -} - -export interface AlertCommonPerClusterMessageTimeToken extends AlertCommonPerClusterMessageToken { - isRelative: boolean; - isAbsolute: boolean; -} - -export interface AlertLicensePerClusterUiState extends AlertCommonPerClusterUiState { expirationTime: number; } -export interface AlertCommonCluster { +export interface AlertCluster { clusterUuid: string; - clusterName: string; } -export interface AlertCommonExecutorOptions extends AlertExecutorOptions { - state: AlertCommonState; +export interface LicenseExpirationAlertExecutorOptions extends AlertExecutorOptions { + state: AlertState; } -export interface AlertCommonParams { +export interface AlertParams { dateFormat: string; timezone: string; } diff --git a/x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.test.ts deleted file mode 100644 index 81e375734cc507..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.test.ts +++ /dev/null @@ -1,70 +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 { executeActions, getUiMessage } from './cluster_state.lib'; -import { AlertClusterStateState } from '../../alerts/enums'; -import { AlertCommonPerClusterMessageLinkToken } from '../../alerts/types'; - -describe('clusterState lib', () => { - describe('executeActions', () => { - const clusterName = 'clusterA'; - const instance: any = { scheduleActions: jest.fn() }; - const license: any = { clusterName }; - const status = AlertClusterStateState.Green; - const emailAddress = 'test@test.com'; - - beforeEach(() => { - instance.scheduleActions.mockClear(); - }); - - it('should schedule actions when firing', () => { - executeActions(instance, license, status, emailAddress, false); - expect(instance.scheduleActions).toHaveBeenCalledWith('default', { - subject: 'NEW X-Pack Monitoring: Cluster Status', - message: `Allocate missing replica shards for cluster '${clusterName}'`, - to: emailAddress, - }); - }); - - it('should have a different message for red state', () => { - executeActions(instance, license, AlertClusterStateState.Red, emailAddress, false); - expect(instance.scheduleActions).toHaveBeenCalledWith('default', { - subject: 'NEW X-Pack Monitoring: Cluster Status', - message: `Allocate missing primary and replica shards for cluster '${clusterName}'`, - to: emailAddress, - }); - }); - - it('should schedule actions when resolved', () => { - executeActions(instance, license, status, emailAddress, true); - expect(instance.scheduleActions).toHaveBeenCalledWith('default', { - subject: 'RESOLVED X-Pack Monitoring: Cluster Status', - message: `This cluster alert has been resolved: Allocate missing replica shards for cluster '${clusterName}'`, - to: emailAddress, - }); - }); - }); - - describe('getUiMessage', () => { - it('should return a message when firing', () => { - const message = getUiMessage(AlertClusterStateState.Red, false); - expect(message.text).toBe( - `Elasticsearch cluster status is red. #start_linkAllocate missing primary and replica shards#end_link` - ); - expect(message.tokens && message.tokens.length).toBe(1); - expect(message.tokens && message.tokens[0].startToken).toBe('#start_link'); - expect(message.tokens && message.tokens[0].endToken).toBe('#end_link'); - expect( - message.tokens && (message.tokens[0] as AlertCommonPerClusterMessageLinkToken).url - ).toBe('elasticsearch/indices'); - }); - - it('should return a message when resolved', () => { - const message = getUiMessage(AlertClusterStateState.Green, true); - expect(message.text).toBe(`Elasticsearch cluster status is green.`); - expect(message.tokens).not.toBeDefined(); - }); - }); -}); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.ts b/x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.ts deleted file mode 100644 index ae66d603507ca6..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/cluster_state.lib.ts +++ /dev/null @@ -1,88 +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 { i18n } from '@kbn/i18n'; -import { AlertInstance } from '../../../../alerting/server'; -import { - AlertCommonCluster, - AlertCommonPerClusterMessage, - AlertCommonPerClusterMessageLinkToken, -} from '../../alerts/types'; -import { AlertClusterStateState, AlertCommonPerClusterMessageTokenType } from '../../alerts/enums'; - -const RESOLVED_SUBJECT = i18n.translate('xpack.monitoring.alerts.clusterStatus.resolvedSubject', { - defaultMessage: 'RESOLVED X-Pack Monitoring: Cluster Status', -}); - -const NEW_SUBJECT = i18n.translate('xpack.monitoring.alerts.clusterStatus.newSubject', { - defaultMessage: 'NEW X-Pack Monitoring: Cluster Status', -}); - -const RED_STATUS_MESSAGE = i18n.translate('xpack.monitoring.alerts.clusterStatus.redMessage', { - defaultMessage: 'Allocate missing primary and replica shards', -}); - -const YELLOW_STATUS_MESSAGE = i18n.translate( - 'xpack.monitoring.alerts.clusterStatus.yellowMessage', - { - defaultMessage: 'Allocate missing replica shards', - } -); - -export function executeActions( - instance: AlertInstance, - cluster: AlertCommonCluster, - status: AlertClusterStateState, - emailAddress: string, - resolved: boolean = false -) { - const message = - status === AlertClusterStateState.Red ? RED_STATUS_MESSAGE : YELLOW_STATUS_MESSAGE; - if (resolved) { - instance.scheduleActions('default', { - subject: RESOLVED_SUBJECT, - message: `This cluster alert has been resolved: ${message} for cluster '${cluster.clusterName}'`, - to: emailAddress, - }); - } else { - instance.scheduleActions('default', { - subject: NEW_SUBJECT, - message: `${message} for cluster '${cluster.clusterName}'`, - to: emailAddress, - }); - } -} - -export function getUiMessage( - status: AlertClusterStateState, - resolved: boolean = false -): AlertCommonPerClusterMessage { - if (resolved) { - return { - text: i18n.translate('xpack.monitoring.alerts.clusterStatus.ui.resolvedMessage', { - defaultMessage: `Elasticsearch cluster status is green.`, - }), - }; - } - const message = - status === AlertClusterStateState.Red ? RED_STATUS_MESSAGE : YELLOW_STATUS_MESSAGE; - return { - text: i18n.translate('xpack.monitoring.alerts.clusterStatus.ui.firingMessage', { - defaultMessage: `Elasticsearch cluster status is {status}. #start_link{message}#end_link`, - values: { - status, - message, - }, - }), - tokens: [ - { - startToken: '#start_link', - endToken: '#end_link', - type: AlertCommonPerClusterMessageTokenType.Link, - url: 'elasticsearch/indices', - } as AlertCommonPerClusterMessageLinkToken, - ], - }; -} diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.test.ts deleted file mode 100644 index 642ae3c39a0275..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { fetchClusterState } from './fetch_cluster_state'; - -describe('fetchClusterState', () => { - it('should return the cluster state', async () => { - const status = 'green'; - const clusterUuid = 'sdfdsaj34434'; - const callCluster = jest.fn(() => ({ - hits: { - hits: [ - { - _source: { - cluster_state: { - status, - }, - cluster_uuid: clusterUuid, - }, - }, - ], - }, - })); - - const clusters = [{ clusterUuid, clusterName: 'foo' }]; - const index = '.monitoring-es-*'; - - const state = await fetchClusterState(callCluster, clusters, index); - expect(state).toEqual([ - { - state: status, - clusterUuid, - }, - ]); - }); -}); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.ts deleted file mode 100644 index 66ea30d5f2e96a..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_state.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { get } from 'lodash'; -import { AlertCommonCluster, AlertClusterState } from '../../alerts/types'; - -export async function fetchClusterState( - callCluster: any, - clusters: AlertCommonCluster[], - index: string -): Promise { - const params = { - index, - filterPath: ['hits.hits._source.cluster_state.status', 'hits.hits._source.cluster_uuid'], - body: { - size: 1, - sort: [{ timestamp: { order: 'desc' } }], - query: { - bool: { - filter: [ - { - terms: { - cluster_uuid: clusters.map(cluster => cluster.clusterUuid), - }, - }, - { - term: { - type: 'cluster_stats', - }, - }, - { - range: { - timestamp: { - gte: 'now-2m', - }, - }, - }, - ], - }, - }, - }, - }; - - const response = await callCluster('search', params); - return get(response, 'hits.hits', []).map((hit: any) => { - return { - state: get(hit, '_source.cluster_state.status'), - clusterUuid: get(hit, '_source.cluster_uuid'), - }; - }); -} diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts index 7a9b61f37707ba..78eb9773df15fb 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts @@ -6,51 +6,21 @@ import { fetchClusters } from './fetch_clusters'; describe('fetchClusters', () => { - const clusterUuid = '1sdfds734'; - const clusterName = 'monitoring'; - it('return a list of clusters', async () => { const callCluster = jest.fn().mockImplementation(() => ({ - hits: { - hits: [ - { - _source: { - cluster_uuid: clusterUuid, - cluster_name: clusterName, - }, - }, - ], - }, - })); - const index = '.monitoring-es-*'; - const result = await fetchClusters(callCluster, index); - expect(result).toEqual([{ clusterUuid, clusterName }]); - }); - - it('return the metadata name if available', async () => { - const metadataName = 'custom-monitoring'; - const callCluster = jest.fn().mockImplementation(() => ({ - hits: { - hits: [ - { - _source: { - cluster_uuid: clusterUuid, - cluster_name: clusterName, - cluster_settings: { - cluster: { - metadata: { - display_name: metadataName, - }, - }, - }, + aggregations: { + clusters: { + buckets: [ + { + key: 'clusterA', }, - }, - ], + ], + }, }, })); const index = '.monitoring-es-*'; const result = await fetchClusters(callCluster, index); - expect(result).toEqual([{ clusterUuid, clusterName: metadataName }]); + expect(result).toEqual([{ clusterUuid: 'clusterA' }]); }); it('should limit the time period in the query', async () => { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts index d1513ac16fb158..8ef7339618a2c0 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts @@ -4,21 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { AlertCommonCluster } from '../../alerts/types'; +import { AlertCluster } from '../../alerts/types'; -export async function fetchClusters( - callCluster: any, - index: string -): Promise { +interface AggregationResult { + key: string; +} + +export async function fetchClusters(callCluster: any, index: string): Promise { const params = { index, - filterPath: [ - 'hits.hits._source.cluster_settings.cluster.metadata.display_name', - 'hits.hits._source.cluster_uuid', - 'hits.hits._source.cluster_name', - ], + filterPath: 'aggregations.clusters.buckets', body: { - size: 1000, + size: 0, query: { bool: { filter: [ @@ -37,21 +34,19 @@ export async function fetchClusters( ], }, }, - collapse: { - field: 'cluster_uuid', + aggs: { + clusters: { + terms: { + field: 'cluster_uuid', + size: 1000, + }, + }, }, }, }; const response = await callCluster('search', params); - return get(response, 'hits.hits', []).map((hit: any) => { - const clusterName: string = - get(hit, '_source.cluster_settings.cluster.metadata.display_name') || - get(hit, '_source.cluster_name') || - get(hit, '_source.cluster_uuid'); - return { - clusterUuid: get(hit, '_source.cluster_uuid'), - clusterName, - }; - }); + return get(response, 'aggregations.clusters.buckets', []).map((bucket: AggregationResult) => ({ + clusterUuid: bucket.key, + })); } diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts index 9dcb4ffb82a5fc..dd6c074e68b1f9 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts @@ -6,28 +6,28 @@ import { fetchLicenses } from './fetch_licenses'; describe('fetchLicenses', () => { - const clusterName = 'MyCluster'; - const clusterUuid = 'clusterA'; - const license = { - status: 'active', - expiry_date_in_millis: 1579532493876, - type: 'basic', - }; - it('return a list of licenses', async () => { + const clusterName = 'MyCluster'; + const clusterUuid = 'clusterA'; + const license = { + status: 'active', + expiry_date_in_millis: 1579532493876, + type: 'basic', + }; const callCluster = jest.fn().mockImplementation(() => ({ hits: { hits: [ { _source: { license, + cluster_name: clusterName, cluster_uuid: clusterUuid, }, }, ], }, })); - const clusters = [{ clusterUuid, clusterName }]; + const clusters = [{ clusterUuid }]; const index = '.monitoring-es-*'; const result = await fetchLicenses(callCluster, clusters, index); expect(result).toEqual([ @@ -36,13 +36,15 @@ describe('fetchLicenses', () => { type: license.type, expiryDateMS: license.expiry_date_in_millis, clusterUuid, + clusterName, }, ]); }); it('should only search for the clusters provided', async () => { + const clusterUuid = 'clusterA'; const callCluster = jest.fn(); - const clusters = [{ clusterUuid, clusterName }]; + const clusters = [{ clusterUuid }]; const index = '.monitoring-es-*'; await fetchLicenses(callCluster, clusters, index); const params = callCluster.mock.calls[0][1]; @@ -50,11 +52,54 @@ describe('fetchLicenses', () => { }); it('should limit the time period in the query', async () => { + const clusterUuid = 'clusterA'; const callCluster = jest.fn(); - const clusters = [{ clusterUuid, clusterName }]; + const clusters = [{ clusterUuid }]; const index = '.monitoring-es-*'; await fetchLicenses(callCluster, clusters, index); const params = callCluster.mock.calls[0][1]; expect(params.body.query.bool.filter[2].range.timestamp.gte).toBe('now-2m'); }); + + it('should give priority to the metadata name', async () => { + const clusterName = 'MyCluster'; + const clusterUuid = 'clusterA'; + const license = { + status: 'active', + expiry_date_in_millis: 1579532493876, + type: 'basic', + }; + const callCluster = jest.fn().mockImplementation(() => ({ + hits: { + hits: [ + { + _source: { + license, + cluster_name: 'fakeName', + cluster_uuid: clusterUuid, + cluster_settings: { + cluster: { + metadata: { + display_name: clusterName, + }, + }, + }, + }, + }, + ], + }, + })); + const clusters = [{ clusterUuid }]; + const index = '.monitoring-es-*'; + const result = await fetchLicenses(callCluster, clusters, index); + expect(result).toEqual([ + { + status: license.status, + type: license.type, + expiryDateMS: license.expiry_date_in_millis, + clusterUuid, + clusterName, + }, + ]); + }); }); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.ts index 5b05c907e796e8..31a68e8aa9c3ee 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.ts @@ -4,16 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { AlertLicense, AlertCommonCluster } from '../../alerts/types'; +import { AlertLicense, AlertCluster } from '../../alerts/types'; export async function fetchLicenses( callCluster: any, - clusters: AlertCommonCluster[], + clusters: AlertCluster[], index: string ): Promise { const params = { index, - filterPath: ['hits.hits._source.license.*', 'hits.hits._source.cluster_uuid'], + filterPath: [ + 'hits.hits._source.license.*', + 'hits.hits._source.cluster_settings.cluster.metadata.display_name', + 'hits.hits._source.cluster_uuid', + 'hits.hits._source.cluster_name', + ], body: { size: 1, sort: [{ timestamp: { order: 'desc' } }], @@ -45,12 +50,17 @@ export async function fetchLicenses( const response = await callCluster('search', params); return get(response, 'hits.hits', []).map((hit: any) => { + const clusterName: string = + get(hit, '_source.cluster_settings.cluster.metadata.display_name') || + get(hit, '_source.cluster_name') || + get(hit, '_source.cluster_uuid'); const rawLicense: any = get(hit, '_source.license', {}); const license: AlertLicense = { status: rawLicense.status, type: rawLicense.type, expiryDateMS: rawLicense.expiry_date_in_millis, clusterUuid: get(hit, '_source.cluster_uuid'), + clusterName, }; return license; }); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts deleted file mode 100644 index a3bcb61afacd61..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts +++ /dev/null @@ -1,122 +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 { fetchStatus } from './fetch_status'; -import { AlertCommonPerClusterState } from '../../alerts/types'; - -describe('fetchStatus', () => { - const alertType = 'monitoringTest'; - const log = { warn: jest.fn() }; - const start = 0; - const end = 0; - const id = 1; - const defaultUiState = { - isFiring: false, - severity: 0, - message: null, - resolvedMS: 0, - lastCheckedMS: 0, - triggeredMS: 0, - }; - const alertsClient = { - find: jest.fn(() => ({ - total: 1, - data: [ - { - id, - }, - ], - })), - getAlertState: jest.fn(() => ({ - alertTypeState: { - state: { - ui: defaultUiState, - } as AlertCommonPerClusterState, - }, - })), - }; - - afterEach(() => { - (alertsClient.find as jest.Mock).mockClear(); - (alertsClient.getAlertState as jest.Mock).mockClear(); - }); - - it('should fetch from the alerts client', async () => { - const status = await fetchStatus(alertsClient as any, [alertType], start, end, log as any); - expect(status).toEqual([]); - }); - - it('should return alerts that are firing', async () => { - alertsClient.getAlertState = jest.fn(() => ({ - alertTypeState: { - state: { - ui: { - ...defaultUiState, - isFiring: true, - }, - } as AlertCommonPerClusterState, - }, - })); - - const status = await fetchStatus(alertsClient as any, [alertType], start, end, log as any); - expect(status.length).toBe(1); - expect(status[0].type).toBe(alertType); - expect(status[0].isFiring).toBe(true); - }); - - it('should return alerts that have been resolved in the time period', async () => { - alertsClient.getAlertState = jest.fn(() => ({ - alertTypeState: { - state: { - ui: { - ...defaultUiState, - resolvedMS: 1500, - }, - } as AlertCommonPerClusterState, - }, - })); - - const customStart = 1000; - const customEnd = 2000; - - const status = await fetchStatus( - alertsClient as any, - [alertType], - customStart, - customEnd, - log as any - ); - expect(status.length).toBe(1); - expect(status[0].type).toBe(alertType); - expect(status[0].isFiring).toBe(false); - }); - - it('should pass in the right filter to the alerts client', async () => { - await fetchStatus(alertsClient as any, [alertType], start, end, log as any); - expect((alertsClient.find as jest.Mock).mock.calls[0][0].options.filter).toBe( - `alert.attributes.alertTypeId:${alertType}` - ); - }); - - it('should return nothing if no alert state is found', async () => { - alertsClient.getAlertState = jest.fn(() => ({ - alertTypeState: null, - })) as any; - - const status = await fetchStatus(alertsClient as any, [alertType], start, end, log as any); - expect(status).toEqual([]); - }); - - it('should return nothing if no alerts are found', async () => { - alertsClient.find = jest.fn(() => ({ - total: 0, - data: [], - })) as any; - - const status = await fetchStatus(alertsClient as any, [alertType], start, end, log as any); - expect(status).toEqual([]); - }); -}); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts index bf6ee965d3b2fb..9f7c1d5a994d27 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts @@ -4,53 +4,81 @@ * you may not use this file except in compliance with the Elastic License. */ import moment from 'moment'; -import { Logger } from '../../../../../../src/core/server'; -import { AlertCommonPerClusterState } from '../../alerts/types'; -import { AlertsClient } from '../../../../alerting/server'; +import { get } from 'lodash'; +import { AlertClusterState } from '../../alerts/types'; +import { ALERT_TYPES, LOGGING_TAG } from '../../../common/constants'; export async function fetchStatus( - alertsClient: AlertsClient, - alertTypes: string[], + callCluster: any, start: number, end: number, - log: Logger + clusterUuid: string, + server: any ): Promise { + // TODO: this shouldn't query task manager directly but rather + // use an api exposed by the alerting/actions plugin + // See https://github.com/elastic/kibana/issues/48442 const statuses = await Promise.all( - alertTypes.map( + ALERT_TYPES.map( type => new Promise(async (resolve, reject) => { - // We need to get the id from the alertTypeId - const alerts = await alertsClient.find({ - options: { - filter: `alert.attributes.alertTypeId:${type}`, - }, - }); - if (alerts.total === 0) { - return resolve(false); - } - - if (alerts.total !== 1) { - log.warn(`Found more than one alert for type ${type} which is unexpected.`); - } + try { + const params = { + index: '.kibana_task_manager', + filterPath: ['hits.hits._source.task.state'], + body: { + size: 1, + sort: [{ updated_at: { order: 'desc' } }], + query: { + bool: { + filter: [ + { + term: { + 'task.taskType': `alerting:${type}`, + }, + }, + ], + }, + }, + }, + }; - const id = alerts.data[0].id; - - // Now that we have the id, we can get the state - const states = await alertsClient.getAlertState({ id }); - if (!states || !states.alertTypeState) { - log.warn(`No alert states found for type ${type} which is unexpected.`); + const response = await callCluster('search', params); + const state = get(response, 'hits.hits[0]._source.task.state', '{}'); + const clusterState: AlertClusterState = get( + JSON.parse(state), + `alertTypeState.${clusterUuid}`, + { + expiredCheckDateMS: 0, + ui: { + isFiring: false, + message: null, + severity: 0, + resolvedMS: 0, + expirationTime: 0, + }, + } + ); + const isInBetween = moment(clusterState.ui.resolvedMS).isBetween(start, end); + if (clusterState.ui.isFiring || isInBetween) { + return resolve({ + type, + ...clusterState.ui, + }); + } + return resolve(false); + } catch (err) { + const reason = get(err, 'body.error.type'); + if (reason === 'index_not_found_exception') { + server.log( + ['error', LOGGING_TAG], + `Unable to fetch alerts. Alerts depends on task manager, which has not been started yet.` + ); + } else { + server.log(['error', LOGGING_TAG], err.message); + } return resolve(false); } - - const state = Object.values(states.alertTypeState)[0] as AlertCommonPerClusterState; - const isInBetween = moment(state.ui.resolvedMS).isBetween(start, end); - if (state.ui.isFiring || isInBetween) { - return resolve({ - type, - ...state.ui, - }); - } - return resolve(false); }) ) ); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.test.ts deleted file mode 100644 index 1840a2026a7534..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.test.ts +++ /dev/null @@ -1,163 +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 { getPreparedAlert } from './get_prepared_alert'; -import { fetchClusters } from './fetch_clusters'; -import { fetchDefaultEmailAddress } from './fetch_default_email_address'; - -jest.mock('./fetch_clusters', () => ({ - fetchClusters: jest.fn(), -})); - -jest.mock('./fetch_default_email_address', () => ({ - fetchDefaultEmailAddress: jest.fn(), -})); - -describe('getPreparedAlert', () => { - const uiSettings = { get: jest.fn() }; - const alertType = 'test'; - const getUiSettingsService = async () => ({ - asScopedToClient: () => uiSettings, - }); - const monitoringCluster = null; - const logger = { warn: jest.fn() }; - const ccsEnabled = false; - const services = { - callCluster: jest.fn(), - savedObjectsClient: null, - }; - const emailAddress = 'foo@foo.com'; - const data = [{ foo: 1 }]; - const dataFetcher = () => data; - const clusterName = 'MonitoringCluster'; - const clusterUuid = 'sdf34sdf'; - const clusters = [{ clusterName, clusterUuid }]; - - afterEach(() => { - (uiSettings.get as jest.Mock).mockClear(); - (services.callCluster as jest.Mock).mockClear(); - (fetchClusters as jest.Mock).mockClear(); - (fetchDefaultEmailAddress as jest.Mock).mockClear(); - }); - - beforeEach(() => { - (fetchClusters as jest.Mock).mockImplementation(() => clusters); - (fetchDefaultEmailAddress as jest.Mock).mockImplementation(() => emailAddress); - }); - - it('should return fields as expected', async () => { - (uiSettings.get as jest.Mock).mockImplementation(() => { - return emailAddress; - }); - - const alert = await getPreparedAlert( - alertType, - getUiSettingsService as any, - monitoringCluster as any, - logger as any, - ccsEnabled, - services as any, - dataFetcher as any - ); - - expect(alert && alert.emailAddress).toBe(emailAddress); - expect(alert && alert.data).toBe(data); - }); - - it('should add ccs if specified', async () => { - const ccsClusterName = 'remoteCluster'; - (services.callCluster as jest.Mock).mockImplementation(() => { - return { - [ccsClusterName]: { - connected: true, - }, - }; - }); - - await getPreparedAlert( - alertType, - getUiSettingsService as any, - monitoringCluster as any, - logger as any, - true, - services as any, - dataFetcher as any - ); - - expect((fetchClusters as jest.Mock).mock.calls[0][1].includes(ccsClusterName)).toBe(true); - }); - - it('should ignore ccs if no remote clusters are available', async () => { - const ccsClusterName = 'remoteCluster'; - (services.callCluster as jest.Mock).mockImplementation(() => { - return { - [ccsClusterName]: { - connected: false, - }, - }; - }); - - await getPreparedAlert( - alertType, - getUiSettingsService as any, - monitoringCluster as any, - logger as any, - true, - services as any, - dataFetcher as any - ); - - expect((fetchClusters as jest.Mock).mock.calls[0][1].includes(ccsClusterName)).toBe(false); - }); - - it('should pass in the clusters into the data fetcher', async () => { - const customDataFetcher = jest.fn(() => data); - - await getPreparedAlert( - alertType, - getUiSettingsService as any, - monitoringCluster as any, - logger as any, - true, - services as any, - customDataFetcher as any - ); - - expect((customDataFetcher as jest.Mock).mock.calls[0][1]).toBe(clusters); - }); - - it('should return nothing if the data fetcher returns nothing', async () => { - const customDataFetcher = jest.fn(() => []); - - const result = await getPreparedAlert( - alertType, - getUiSettingsService as any, - monitoringCluster as any, - logger as any, - true, - services as any, - customDataFetcher as any - ); - - expect(result).toBe(null); - }); - - it('should return nothing if there is no email address', async () => { - (fetchDefaultEmailAddress as jest.Mock).mockImplementation(() => null); - - const result = await getPreparedAlert( - alertType, - getUiSettingsService as any, - monitoringCluster as any, - logger as any, - true, - services as any, - dataFetcher as any - ); - - expect(result).toBe(null); - }); -}); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts b/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts deleted file mode 100644 index 83a9e26e4c5890..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts +++ /dev/null @@ -1,87 +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 { Logger, ICustomClusterClient, UiSettingsServiceStart } from 'kibana/server'; -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { AlertServices } from '../../../../alerting/server'; -import { AlertCommonCluster } from '../../alerts/types'; -import { INDEX_PATTERN_ELASTICSEARCH } from '../../../common/constants'; -import { fetchAvailableCcs } from './fetch_available_ccs'; -import { getCcsIndexPattern } from './get_ccs_index_pattern'; -import { fetchClusters } from './fetch_clusters'; -import { fetchDefaultEmailAddress } from './fetch_default_email_address'; - -export interface PreparedAlert { - emailAddress: string; - clusters: AlertCommonCluster[]; - data: any[]; - timezone: string; - dateFormat: string; -} - -async function getCallCluster( - monitoringCluster: ICustomClusterClient, - services: Pick -): Promise { - if (!monitoringCluster) { - return services.callCluster; - } - - return monitoringCluster.callAsInternalUser; -} - -export async function getPreparedAlert( - alertType: string, - getUiSettingsService: () => Promise, - monitoringCluster: ICustomClusterClient, - logger: Logger, - ccsEnabled: boolean, - services: Pick, - dataFetcher: ( - callCluster: CallCluster, - clusters: AlertCommonCluster[], - esIndexPattern: string - ) => Promise -): Promise { - const callCluster = await getCallCluster(monitoringCluster, services); - - // Support CCS use cases by querying to find available remote clusters - // and then adding those to the index pattern we are searching against - let esIndexPattern = INDEX_PATTERN_ELASTICSEARCH; - if (ccsEnabled) { - const availableCcs = await fetchAvailableCcs(callCluster); - if (availableCcs.length > 0) { - esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs); - } - } - - const clusters = await fetchClusters(callCluster, esIndexPattern); - - // Fetch the specific data - const data = await dataFetcher(callCluster, clusters, esIndexPattern); - if (data.length === 0) { - logger.warn(`No data found for ${alertType}.`); - return null; - } - - const uiSettings = (await getUiSettingsService()).asScopedToClient(services.savedObjectsClient); - const dateFormat: string = await uiSettings.get('dateFormat'); - const timezone: string = await uiSettings.get('dateFormat:tz'); - const emailAddress = await fetchDefaultEmailAddress(uiSettings); - if (!emailAddress) { - // TODO: we can do more here - logger.warn(`Unable to send email for ${alertType} because there is no email configured.`); - return null; - } - - return { - emailAddress, - data, - clusters, - dateFormat, - timezone, - }; -} diff --git a/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.test.ts index 6c0301b6cc347d..1a2eb1e44be843 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.test.ts @@ -39,26 +39,17 @@ describe('licenseExpiration lib', () => { }); describe('getUiMessage', () => { + const timezone = 'Europe/London'; + const license: any = { expiryDateMS: moment.tz('2020-01-20 08:00:00', timezone).utc() }; + it('should return a message when firing', () => { - const message = getUiMessage(false); - expect(message.text).toBe( - `This cluster's license is going to expire in #relative at #absolute. #start_linkPlease update your license#end_link` - ); - // LOL How do I avoid this in TS???? - if (!message.tokens) { - return expect(false).toBe(true); - } - expect(message.tokens.length).toBe(3); - expect(message.tokens[0].startToken).toBe('#relative'); - expect(message.tokens[1].startToken).toBe('#absolute'); - expect(message.tokens[2].startToken).toBe('#start_link'); - expect(message.tokens[2].endToken).toBe('#end_link'); + const message = getUiMessage(license, timezone, false); + expect(message).toBe(`This cluster's license is going to expire in #relative at #absolute.`); }); it('should return a message when resolved', () => { - const message = getUiMessage(true); - expect(message.text).toBe(`This cluster's license is active.`); - expect(message.tokens).not.toBeDefined(); + const message = getUiMessage(license, timezone, true); + expect(message).toBe(`This cluster's license is active.`); }); }); }); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.ts b/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.ts index a590021a2f29b1..41b68d69bbd25f 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/license_expiration.lib.ts @@ -6,13 +6,7 @@ import { Moment } from 'moment-timezone'; import { i18n } from '@kbn/i18n'; import { AlertInstance } from '../../../../alerting/server'; -import { - AlertCommonPerClusterMessageLinkToken, - AlertCommonPerClusterMessageTimeToken, - AlertCommonCluster, - AlertCommonPerClusterMessage, -} from '../../alerts/types'; -import { AlertCommonPerClusterMessageTokenType } from '../../alerts/enums'; +import { AlertLicense } from '../../alerts/types'; const RESOLVED_SUBJECT = i18n.translate( 'xpack.monitoring.alerts.licenseExpiration.resolvedSubject', @@ -27,7 +21,7 @@ const NEW_SUBJECT = i18n.translate('xpack.monitoring.alerts.licenseExpiration.ne export function executeActions( instance: AlertInstance, - cluster: AlertCommonCluster, + license: AlertLicense, $expiry: Moment, dateFormat: string, emailAddress: string, @@ -37,14 +31,14 @@ export function executeActions( instance.scheduleActions('default', { subject: RESOLVED_SUBJECT, message: `This cluster alert has been resolved: Cluster '${ - cluster.clusterName + license.clusterName }' license was going to expire on ${$expiry.format(dateFormat)}.`, to: emailAddress, }); } else { instance.scheduleActions('default', { subject: NEW_SUBJECT, - message: `Cluster '${cluster.clusterName}' license is going to expire on ${$expiry.format( + message: `Cluster '${license.clusterName}' license is going to expire on ${$expiry.format( dateFormat )}. Please update your license.`, to: emailAddress, @@ -52,43 +46,13 @@ export function executeActions( } } -export function getUiMessage(resolved: boolean = false): AlertCommonPerClusterMessage { +export function getUiMessage(license: AlertLicense, timezone: string, resolved: boolean = false) { if (resolved) { - return { - text: i18n.translate('xpack.monitoring.alerts.licenseExpiration.ui.resolvedMessage', { - defaultMessage: `This cluster's license is active.`, - }), - }; + return i18n.translate('xpack.monitoring.alerts.licenseExpiration.ui.resolvedMessage', { + defaultMessage: `This cluster's license is active.`, + }); } - const linkText = i18n.translate('xpack.monitoring.alerts.licenseExpiration.linkText', { - defaultMessage: 'Please update your license', + return i18n.translate('xpack.monitoring.alerts.licenseExpiration.ui.firingMessage', { + defaultMessage: `This cluster's license is going to expire in #relative at #absolute.`, }); - return { - text: i18n.translate('xpack.monitoring.alerts.licenseExpiration.ui.firingMessage', { - defaultMessage: `This cluster's license is going to expire in #relative at #absolute. #start_link{linkText}#end_link`, - values: { - linkText, - }, - }), - tokens: [ - { - startToken: '#relative', - type: AlertCommonPerClusterMessageTokenType.Time, - isRelative: true, - isAbsolute: false, - } as AlertCommonPerClusterMessageTimeToken, - { - startToken: '#absolute', - type: AlertCommonPerClusterMessageTokenType.Time, - isAbsolute: true, - isRelative: false, - } as AlertCommonPerClusterMessageTimeToken, - { - startToken: '#start_link', - endToken: '#end_link', - type: AlertCommonPerClusterMessageTokenType.Link, - url: 'license', - } as AlertCommonPerClusterMessageLinkToken, - ], - }; } diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js index 1bddede52207b2..c5091c36c3bbeb 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js @@ -29,7 +29,6 @@ import { CODE_PATH_BEATS, CODE_PATH_APM, KIBANA_ALERTING_ENABLED, - ALERT_TYPES, } from '../../../common/constants'; import { getApmsForClusters } from '../apm/get_apms_for_clusters'; import { i18n } from '@kbn/i18n'; @@ -103,8 +102,15 @@ export async function getClustersFromRequest( if (isInCodePath(codePaths, [CODE_PATH_ALERTS])) { if (KIBANA_ALERTING_ENABLED) { - const alertsClient = req.getAlertsClient ? req.getAlertsClient() : null; - cluster.alerts = await fetchStatus(alertsClient, ALERT_TYPES, start, end, req.logger); + const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); + const callCluster = (...args) => callWithRequest(req, ...args); + cluster.alerts = await fetchStatus( + callCluster, + start, + end, + cluster.cluster_uuid, + req.server + ); } else { cluster.alerts = await alertsClusterSearch( req, diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 784226dca66fee..24d8bcaa4397cf 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -47,7 +47,6 @@ import { PluginSetupContract as AlertingPluginSetupContract, } from '../../alerting/server'; import { getLicenseExpiration } from './alerts/license_expiration'; -import { getClusterState } from './alerts/cluster_state'; import { InfraPluginSetup } from '../../infra/server'; export interface LegacyAPI { @@ -155,17 +154,6 @@ export class Plugin { config.ui.ccs.enabled ) ); - plugins.alerting.registerType( - getClusterState( - async () => { - const coreStart = (await core.getStartServices())[0]; - return coreStart.uiSettings; - }, - cluster, - this.getLogger, - config.ui.ccs.enabled - ) - ); } // Initialize telemetry diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/alerts.js b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/alerts.js index d5a43d32f600a9..56922bd8e87e21 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/alerts.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/alerts.js @@ -8,12 +8,8 @@ import { schema } from '@kbn/config-schema'; import { isFunction } from 'lodash'; import { ALERT_TYPE_LICENSE_EXPIRATION, - ALERT_TYPE_CLUSTER_STATE, MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS, - ALERT_TYPES, } from '../../../../../common/constants'; -import { handleError } from '../../../../lib/errors'; -import { fetchStatus } from '../../../../lib/alerts/fetch_status'; async function createAlerts(req, alertsClient, { selectedEmailActionId }) { const createdAlerts = []; @@ -21,21 +17,7 @@ async function createAlerts(req, alertsClient, { selectedEmailActionId }) { // Create alerts const ALERT_TYPES = { [ALERT_TYPE_LICENSE_EXPIRATION]: { - schedule: { interval: '1m' }, - actions: [ - { - group: 'default', - id: selectedEmailActionId, - params: { - subject: '{{context.subject}}', - message: `{{context.message}}`, - to: ['{{context.to}}'], - }, - }, - ], - }, - [ALERT_TYPE_CLUSTER_STATE]: { - schedule: { interval: '1m' }, + schedule: { interval: '10s' }, actions: [ { group: 'default', @@ -104,37 +86,4 @@ export function createKibanaAlertsRoute(server) { return { alerts, emailResponse }; }, }); - - server.route({ - method: 'POST', - path: '/api/monitoring/v1/alert_status', - config: { - validate: { - payload: schema.object({ - timeRange: schema.object({ - min: schema.string(), - max: schema.string(), - }), - }), - }, - }, - async handler(req, headers) { - const alertsClient = isFunction(req.getAlertsClient) ? req.getAlertsClient() : null; - if (!alertsClient) { - return headers.response().code(404); - } - - const start = req.payload.timeRange.min; - const end = req.payload.timeRange.max; - let alerts; - - try { - alerts = await fetchStatus(alertsClient, ALERT_TYPES, start, end, req.logger); - } catch (err) { - throw handleError(err, req); - } - - return { alerts }; - }, - }); } From b65de274580e01314d63700ce06c9c3779dad8f3 Mon Sep 17 00:00:00 2001 From: The SpaceCake Project Date: Mon, 6 Apr 2020 22:45:39 -0400 Subject: [PATCH 5/8] bc5 siem rules merge (#62679) * bc5 rule merge version changes field changes to endpoint rules removed max_signals from 7 rules * Fixing monitoring i18n (#62715) * Updates esarchiver test data with the latest rules (#62723) * Remove CR, only CRLF for rules * delete two files for Garrett * deletes delete 2 files (for Garrett) * Revert "deletes" This reverts commit cc2ac1e05fdfbaa72dd57e8dbfb21811cee5e1bc. * Revert "Fixing monitoring i18n (#62715)" This reverts commit 028574037aca6be5286f5a7c8738c81035a1c327. Co-authored-by: Elastic Machine Co-authored-by: Garrett Spong Co-authored-by: Ross Wolf <31489089+rw-access@users.noreply.github.com> --- .../403_response_to_a_post.json | 2 +- .../405_response_method_not_allowed.json | 2 +- ..._security_adversary_behavior_detected.json | 4 +- ...dpoint_security_cred_dumping_detected.json | 4 +- ...point_security_cred_dumping_prevented.json | 4 +- ...t_security_cred_manipulation_detected.json | 4 +- ..._security_cred_manipulation_prevented.json | 4 +- ...ic_endpoint_security_exploit_detected.json | 4 +- ...c_endpoint_security_exploit_prevented.json | 4 +- ...ic_endpoint_security_malware_detected.json | 4 +- ...c_endpoint_security_malware_prevented.json | 4 +- ...nt_security_permission_theft_detected.json | 4 +- ...t_security_permission_theft_prevented.json | 4 +- ...t_security_process_injection_detected.json | 4 +- ..._security_process_injection_prevented.json | 4 +- ...endpoint_security_ransomware_detected.json | 4 +- ...ndpoint_security_ransomware_prevented.json | 4 +- ...den_file_attribute_with_via_attribexe.json | 2 +- .../eql_clearing_windows_event_logs.json | 2 +- ...delete_volume_usn_journal_with_fsutil.json | 2 +- ...deleting_backup_catalogs_with_wbadmin.json | 2 +- .../eql_direct_outbound_smb_connection.json | 2 +- ...ble_windows_firewall_rules_with_netsh.json | 2 +- ...coding_or_decoding_files_via_certutil.json | 2 +- .../eql_local_scheduled_task_commands.json | 2 +- .../eql_local_service_commands.json | 2 +- ...ql_msbuild_making_network_connections.json | 2 +- .../eql_mshta_making_network_connections.json | 2 +- .../eql_psexec_lateral_movement_command.json | 2 +- .../eql_system_shells_via_services.json | 2 +- ...usual_network_connection_via_rundll32.json | 2 +- .../eql_unusual_parentchild_relationship.json | 2 +- ...ql_unusual_process_network_connection.json | 2 +- .../eql_user_account_creation.json | 2 +- ...ume_shadow_copy_deletion_via_vssadmin.json | 2 +- ..._volume_shadow_copy_deletion_via_wmic.json | 2 +- ...l_windows_script_executing_powershell.json | 2 +- .../linux_hping_activity.json | 2 +- .../linux_iodine_activity.json | 2 +- .../linux_kernel_module_activity.json | 2 +- .../linux_mknod_activity.json | 2 +- .../linux_netcat_network_connection.json | 2 +- .../linux_nmap_activity.json | 2 +- .../linux_nping_activity.json | 2 +- ...nux_process_started_in_temp_directory.json | 2 +- .../linux_shell_activity_by_web_server.json | 2 +- .../linux_socat_activity.json | 2 +- .../linux_strace_activity.json | 2 +- .../linux_tcpdump_activity.json | 2 +- .../linux_whoami_commmand.json | 2 +- .../prepackaged_rules/null_user_agent.json | 2 +- .../prepackaged_rules/sqlmap_user_agent.json | 2 +- .../windows_certutil_network_connection.json | 1 - ...and_prompt_connecting_to_the_internet.json | 2 +- ...s_command_shell_started_by_powershell.json | 2 +- ...dows_command_shell_started_by_svchost.json | 2 +- .../windows_credential_dumping_msbuild.json | 2 +- .../windows_cve_2020_0601.json | 1 - ...ws_defense_evasion_via_filter_manager.json | 2 +- ...dows_execution_via_compiled_html_file.json | 2 +- ...dows_execution_via_net_com_assemblies.json | 1 - ...ution_via_trusted_developer_utilities.json | 2 +- ...le_program_connecting_to_the_internet.json | 2 +- ...isc_lolbin_connecting_to_the_internet.json | 2 +- .../windows_modification_of_boot_config.json | 1 - .../windows_msxsl_network.json | 1 - .../windows_net_command_system_account.json | 1 - ..._persistence_via_application_shimming.json | 2 +- ...escalation_via_accessibility_features.json | 2 +- ...rocess_discovery_via_tasklist_command.json | 2 +- ...er_program_connecting_to_the_internet.json | 2 +- .../windows_uac_bypass_event_viewer.json | 1 - .../windows_whoami_command_activity.json | 2 +- .../prebuilt_rules_loaded/data.json.gz | Bin 40255 -> 41865 bytes .../prebuilt_rules_loaded/mappings.json | 3026 +---------------- 75 files changed, 224 insertions(+), 2971 deletions(-) diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json index 3b043439759c10..d4118d0686b111 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json @@ -20,5 +20,5 @@ "Elastic" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json index 12c6a5feabebbf..da27f0a71d281b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json @@ -20,5 +20,5 @@ "Elastic" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json index a3302896b7e988..cfc322788d4be9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Adversary Behavior - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:rules_engine_event", + "query": "event.kind:alert and event.module:endgame and (event.action:rules_engine_event or endgame.event_subtype_full:rules_engine_event)", "risk_score": 47, "rule_id": "77a3c3df-8ec4-4da4-b758-878f551dee69", "severity": "medium", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json index 8c2c5f32feab70..0647fe9c9ce109 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Credential Dumping - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:cred_theft_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:cred_theft_event or endgame.event_subtype_full:cred_theft_event)", "risk_score": 73, "rule_id": "571afc56-5ed9-465d-a2a9-045f099f6e7e", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json index 6a96da3218bf25..036c88688d9bdd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Credential Dumping - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:cred_theft_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:cred_theft_event or endgame.event_subtype_full:cred_theft_event)", "risk_score": 47, "rule_id": "db8c33a8-03cd-4988-9e2c-d0a4863adb13", "severity": "medium", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json index 954e35ccd644ae..0fe610d5511527 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Credential Manipulation - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:token_manipulation_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:token_manipulation_event or endgame.event_subtype_full:token_manipulation_event)", "risk_score": 73, "rule_id": "c0be5f31-e180-48ed-aa08-96b36899d48f", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json index 0de35891a3e818..a317c77bcd90aa 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Credential Manipulation - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:token_manipulation_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:token_manipulation_event or endgame.event_subtype_full:token_manipulation_event)", "risk_score": 47, "rule_id": "c9e38e64-3f4c-4bf3-ad48-0e61a60ea1fa", "severity": "medium", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json index 3652b7068ecd23..97640c0cea9b22 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Exploit - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:exploit_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:exploit_event or endgame.event_subtype_full:exploit_event)", "risk_score": 73, "rule_id": "2003cdc8-8d83-4aa5-b132-1f9a8eb48514", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json index dbc910c3002a73..069687a5af00fd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Exploit - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:exploit_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:exploit_event or endgame.event_subtype_full:exploit_event)", "risk_score": 47, "rule_id": "2863ffeb-bf77-44dd-b7a5-93ef94b72036", "severity": "medium", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json index efe2806532be08..a7d3371190cedd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Malware - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:file_classification_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:file_classification_event or endgame.event_subtype_full:file_classification_event)", "risk_score": 99, "rule_id": "0a97b20f-4144-49ea-be32-b540ecc445de", "severity": "critical", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json index 51028b9dbeeb34..dd7bf72c34f900 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Malware - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:file_classification_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:file_classification_event or endgame.event_subtype_full:file_classification_event)", "risk_score": 73, "rule_id": "3b382770-efbb-44f4-beed-f5e0a051b895", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json index c30ca0632f410f..a8e102cc4619d1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Permission Theft - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:token_protection_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:token_protection_event or endgame.event_subtype_full:token_protection_event)", "risk_score": 73, "rule_id": "c3167e1b-f73c-41be-b60b-87f4df707fe3", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json index ed0c714254743e..c97330f2349eb6 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Permission Theft - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:token_protection_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:token_protection_event or endgame.event_subtype_full:token_protection_event)", "risk_score": 47, "rule_id": "453f659e-0429-40b1-bfdb-b6957286e04b", "severity": "medium", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json index 63b008849487ab..e644c0e8d66eb4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Process Injection - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:kernel_shellcode_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:kernel_shellcode_event or endgame.event_subtype_full:kernel_shellcode_event)", "risk_score": 73, "rule_id": "80c52164-c82a-402c-9964-852533d58be1", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json index 135b4a95e8005e..61cbe267f9a465 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Process Injection - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:kernel_shellcode_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:kernel_shellcode_event or endgame.event_subtype_full:kernel_shellcode_event)", "risk_score": 47, "rule_id": "990838aa-a953-4f3e-b3cb-6ddf7584de9e", "severity": "medium", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json index d4042a5e6b9e18..0e88b26cb2c758 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Ransomware - Detected - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:ransomware_event and endgame.metadata.type:detection", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:ransomware_event or endgame.event_subtype_full:ransomware_event)", "risk_score": 99, "rule_id": "8cb4f625-7743-4dfb-ae1b-ad92be9df7bd", "severity": "critical", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json index befdf611da223e..ba341f059f26d5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json @@ -7,7 +7,7 @@ "interval": "10m", "language": "kuery", "name": "Ransomware - Prevented - Elastic Endpoint", - "query": "event.kind:alert and event.module:endgame and event.action:ransomware_event and endgame.metadata.type:prevention", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:ransomware_event or endgame.event_subtype_full:ransomware_event)", "risk_score": 73, "rule_id": "e3c5d5cb-41d5-4206-805c-f30561eae3ac", "severity": "high", @@ -16,5 +16,5 @@ "Endpoint" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json index 6c9b54b8ddb02b..25d2232d3f6dc5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json @@ -46,5 +46,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json index 244d329cc4bb74..1c73d6c276ce6c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json index 40875428165889..0bfa18398eada2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json index eca06723e68b8d..e7293eda6390fd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json index e37c877c62889b..2896d27e19112f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json index f6b4bc67ed9b13..42fe51f4e03737 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json index 38162889737ff7..eef112503da5bc 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json index 42007f153bd55d..dbacb2537e60f3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json @@ -34,5 +34,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json index 9559baabe0e40c..648e83b4a5267f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json index 3e34aacf605c7d..5e8b260d44b55c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json index 769614e8faf53a..88bd248e258d88 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json @@ -34,5 +34,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json index ac170665042f66..f763d2aa033630 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json @@ -49,5 +49,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json index 1c001caa1539c3..f1b1879fc2652c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json index 0165f4d7512e43..2a7960c939d01b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json index 0b4bf9ff32945e..9a28c87c77089c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json index 2c88a2061844c1..43a3d6f6af0b25 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json index 240df34419132e..7054e7f67c3582 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json index e12c2e70138c92..24f1cb72504f38 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json index 94b8846741e3e8..bad3c65024e42c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json index b0a754a662c0e0..52323b169cb223 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json index bb8e8983661e6f..04a56241ea6f66 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json index 4e49702855a764..80358cc775e3b4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json index cf8cd72b7aa6f5..b50fcc4c9980bb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json @@ -37,5 +37,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json index 3bd3848c07581c..d65440e95ff17a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json index cd523b6594ccd3..df8e46be7a1c3e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json @@ -22,5 +22,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json index 604cfa172fd84d..2e5c899ebc6255 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json index 8e71b5b9067114..168b30121c4bb3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json index c50026d7736ae2..0865ac6c70cb26 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json @@ -17,5 +17,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json index 01f117e0a225bf..e9c4c95bb92849 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json @@ -37,5 +37,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json index a16b164e9ee4a3..404fea63aff946 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json index 9b18039b63fd0e..fbdfa9e66682d7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json @@ -20,5 +20,5 @@ "Linux" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json index 5ae48c8db9984c..82771074e7c29d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json @@ -49,5 +49,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json index 7fef4e813da98f..7e7f041581eb07 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json @@ -34,5 +34,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json index afbbb2a34d545d..01246de5595e93 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json @@ -38,5 +38,5 @@ "Elastic" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json index fd240262d021f0..10412c19da1b1e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json @@ -20,5 +20,5 @@ "Elastic" ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json index 2cda21cf7d5efc..52a373e3aeb77e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Network Connection via Certutil", "query": "process.name:certutil.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json index 2427ab4d7cc559..2bee265a74e11c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json @@ -49,5 +49,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json index f8e5bd22576a40..d8f91dba7dd890 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json @@ -46,5 +46,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json index 71aafa9984ecb1..6fd194ee2fa22b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json index 4ff78914385543..43050e2769a241 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 1 -} +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json index c08bb7b3315f5d..f5eb37c70d268a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Windows CryptoAPI Spoofing Vulnerability (CVE-2020-0601 - CurveBall)", "query": "event.provider:\"Microsoft-Windows-Audit-CVE\" and message:\"[CVE-2020-0601]\"", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json index 3f97f7aca74f60..0e8c5a5f2f631a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json index 2b6e1fb3daaec1..7755ff0233f7ce 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json @@ -49,5 +49,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json index c397c955fe64f0..d6acb81c10e3fa 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Execution via Regsvcs/Regasm", "query": "process.name:(RegAsm.exe or RegSvcs.exe) and event.action:\"Process Create (rule: ProcessCreate)\"", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json index f60a986996d6ff..87e38febb07433 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json @@ -49,5 +49,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json index 4b3efead776d27..6c8cd0673256ac 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json @@ -46,5 +46,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json index 0cd68ba5c1ed88..a0e311d8eb1543 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json @@ -46,5 +46,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json index d7612262764966..045a9789b12609 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Modification of Boot Configuration", "query": "event.action:\"Process Create (rule: ProcessCreate)\" and process.name:bcdedit.exe and process.args:(/set and (bootstatuspolicy and ignoreallfailures or no and recoveryenabled))", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json index 9b45d03aae375c..e80dcde1e398db 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Network Connection via MsXsl", "query": "process.name:msxsl.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json index 390c9c278905c9..c2379142df002a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Net command via SYSTEM account", "query": "(process.name:net.exe or process.name:net1.exe and not process.parent.name:net.exe) and user.name:SYSTEM and event.action:\"Process Create (rule: ProcessCreate)\"", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json index 0488667d06c821..2f44727f9e6f05 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json @@ -46,5 +46,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json index 26f0a0bcc245c8..aeff071ed4514e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json @@ -46,5 +46,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json index 28ebdb44fddd28..3a883fa51b763b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json @@ -34,5 +34,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json index 920ff28a9a9cdd..1e061f2ef9463c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json @@ -49,5 +49,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json index 0d4168640bc604..df7a6fe1285d1c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json @@ -4,7 +4,6 @@ "winlogbeat-*" ], "language": "kuery", - "max_signals": 33, "name": "Bypass UAC via Event Viewer", "query": "process.parent.name:eventvwr.exe and event.action:\"Process Create (rule: ProcessCreate)\" and not process.executable:(\"C:\\Windows\\SysWOW64\\mmc.exe\" or \"C:\\Windows\\System32\\mmc.exe\")", "risk_score": 21, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json index 46af0c5b586a50..93ce1f83dd64ec 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json @@ -34,5 +34,5 @@ } ], "type": "query", - "version": 1 + "version": 2 } \ No newline at end of file diff --git a/x-pack/test/siem_cypress/es_archives/prebuilt_rules_loaded/data.json.gz b/x-pack/test/siem_cypress/es_archives/prebuilt_rules_loaded/data.json.gz index 90d4cfe0f2734823f0acccd4ba4ea977fe939f4d..573c006d1507d9c84c581c9abab7d60d96bfebe3 100644 GIT binary patch literal 41865 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 ULoqGFCDyS252ti$R7;5k0Bqt4ng9R* diff --git a/x-pack/test/siem_cypress/es_archives/prebuilt_rules_loaded/mappings.json b/x-pack/test/siem_cypress/es_archives/prebuilt_rules_loaded/mappings.json index 99ef5863ba6c86..f4278c4d4318f3 100644 --- a/x-pack/test/siem_cypress/es_archives/prebuilt_rules_loaded/mappings.json +++ b/x-pack/test/siem_cypress/es_archives/prebuilt_rules_loaded/mappings.json @@ -11,12 +11,13 @@ "migrationMappingPropertyHashes": { "action": "6e96ac5e648f57523879661ea72525b7", "action_task_params": "a9d49f184ee89641044be0ca2950fa3a", + "agent_actions": "ed270b46812f0fa1439366c428a2cf17", "agent_configs": "38abaf89513877745c359e7700c0c66a", "agent_events": "3231653fafe4ef3196fe3b32ab774bf2", - "agents": "75c0f4a11560dbc38b65e5e1d98fc9da", + "agents": "c3eeb7b9d97176f15f6d126370ab23c7", "alert": "7b44fba6773e37c806ce290ea9b7024e", "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", - "apm-telemetry": "e8619030e08b671291af04c4603b4944", + "apm-telemetry": "3525d7c22c42bc80f5e6e9cb3f2b26a2", "application_usage_totals": "c897e4310c5f24b07caaff3db53ae2c1", "application_usage_transactional": "965839e75f809fefe04f92dc4d99722a", "canvas-element": "7390014e1091044523666d97247392fc", @@ -29,7 +30,7 @@ "dashboard": "d00f614b29a80360e1190193fd333bab", "datasources": "d4bc0c252b2b5683ff21ea32d00acffc", "enrollment_api_keys": "28b91e20b105b6f928e2012600085d8f", - "epm-package": "75d12cd13c867fd713d7dfb27366bc20", + "epm-package": "0be91c6758421dd5d0f1a58e9e5bc7c3", "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", "index-pattern": "66eccb05066c5a89924f48a9e9736499", @@ -50,6 +51,7 @@ "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", "search": "181661168bbadd1eff5902361e2a0d5c", "server": "ec97f1c5da1a19609a60874e5af1100c", + "siem-detection-engine-rule-actions": "90eee2e4635260f4be0a1da8f5bc0aa0", "siem-detection-engine-rule-status": "ae783f41c6937db6b7a2ef5c93a9e9b0", "siem-ui-timeline": "ac8020190f5950dd3250b6499144e7fb", "siem-ui-timeline-note": "8874706eedc49059d4cf0f5094559084", @@ -106,6 +108,25 @@ } } }, + "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": { @@ -179,26 +200,6 @@ "access_api_key_id": { "type": "keyword" }, - "actions": { - "properties": { - "created_at": { - "type": "date" - }, - "data": { - "type": "text" - }, - "id": { - "type": "keyword" - }, - "sent_at": { - "type": "date" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" - }, "active": { "type": "boolean" }, @@ -361,7 +362,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -371,23 +372,31 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } }, "language": { "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, "name": { - "ignore_above": 256, + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, "type": "keyword" } } @@ -395,15 +404,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -417,7 +426,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -427,15 +436,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -443,15 +452,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -459,15 +468,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -481,7 +490,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -491,15 +500,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -507,15 +516,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -523,15 +532,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -545,7 +554,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -555,15 +564,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -571,15 +580,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -587,15 +596,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -609,7 +618,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -619,15 +628,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -635,15 +644,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -651,15 +660,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -673,7 +682,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -683,15 +692,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -699,15 +708,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -715,15 +724,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -737,7 +746,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -747,15 +756,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -763,15 +772,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -779,15 +788,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -801,7 +810,7 @@ "agent": { "properties": { "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -811,15 +820,15 @@ "framework": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -827,15 +836,15 @@ "language": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -843,15 +852,15 @@ "runtime": { "properties": { "composite": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "name": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" }, "version": { - "ignore_above": 256, + "ignore_above": 1024, "type": "keyword" } } @@ -1565,15 +1574,6 @@ "properties": { "buildNum": { "type": "keyword" - }, - "dateFormat:tz": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" } } }, @@ -1750,6 +1750,9 @@ }, "type": "nested" }, + "internal": { + "type": "boolean" + }, "name": { "type": "keyword" }, @@ -2332,6 +2335,36 @@ } } }, + "siem-detection-engine-rule-actions": { + "properties": { + "actions": { + "properties": { + "action_type_id": { + "type": "keyword" + }, + "group": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "params": { + "dynamic": "true", + "type": "object" + } + } + }, + "alertThrottle": { + "type": "keyword" + }, + "ruleAlertId": { + "type": "keyword" + }, + "ruleThrottle": { + "type": "keyword" + } + } + }, "siem-detection-engine-rule-status": { "properties": { "alertId": { @@ -2708,9 +2741,6 @@ } } }, - "spaceId": { - "type": "keyword" - }, "telemetry": { "properties": { "allowChangingOptInStatus": { @@ -2931,2774 +2961,4 @@ } } } -} - -{ - "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" - } - } - }, - "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" - } - } - } - } - }, - "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" - }, - "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" - } - } - }, - "file": { - "properties": { - "accessed": { - "type": "date" - }, - "attributes": { - "ignore_above": 1024, - "type": "keyword" - }, - "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" - }, - "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" - }, - "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" - } - } - }, - "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" - }, - "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" - } - } - }, - "observer": { - "properties": { - "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" - }, - "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" - } - } - }, - "process": { - "properties": { - "args": { - "ignore_above": 1024, - "type": "keyword" - }, - "args_count": { - "type": "long" - }, - "command_line": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "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" - }, - "command_line": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "executable": { - "fields": { - "text": { - "norms": false, - "type": "text" - } - }, - "ignore_above": 1024, - "type": "keyword" - }, - "exit_code": { - "type": "long" - }, - "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" - } - } - }, - "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": { - "category": { - "ignore_above": 1024, - "type": "keyword" - }, - "description": { - "ignore_above": 1024, - "type": "keyword" - }, - "id": { - "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": { - "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" - }, - "max_signals": { - "type": "keyword" - }, - "name": { - "type": "keyword" - }, - "note": { - "type": "text" - }, - "output_index": { - "type": "keyword" - }, - "query": { - "type": "keyword" - }, - "references": { - "type": "keyword" - }, - "risk_score": { - "type": "keyword" - }, - "rule_id": { - "type": "keyword" - }, - "saved_id": { - "type": "keyword" - }, - "severity": { - "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" - }, - "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" - } - } - }, - "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" - }, - "number_of_replicas": "1", - "number_of_shards": "1" - } - } - } } \ No newline at end of file From 7882e0c3a817bafc9716647add8d8555c20899f8 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 6 Apr 2020 21:26:10 -0600 Subject: [PATCH 6/8] [Maps] Always show current zoom level (#62684) Co-authored-by: Elastic Machine --- .../view_control/view_control.js | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/view_control/view_control.js b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/view_control/view_control.js index 445e5be542ffb4..19b60221ead36e 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/view_control/view_control.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/view_control/view_control.js @@ -5,28 +5,33 @@ */ import _ from 'lodash'; -import React from 'react'; +import React, { Fragment } from 'react'; import { EuiText } from '@elastic/eui'; import { DECIMAL_DEGREES_PRECISION } from '../../../../common/constants'; import { FormattedMessage } from '@kbn/i18n/react'; export function ViewControl({ mouseCoordinates, zoom }) { - if (!mouseCoordinates) { - return null; + let latLon; + if (mouseCoordinates) { + latLon = ( + + + + {' '} + {_.round(mouseCoordinates.lat, DECIMAL_DEGREES_PRECISION)},{' '} + + + {' '} + {_.round(mouseCoordinates.lon, DECIMAL_DEGREES_PRECISION)},{' '} + + ); } return (
- - - {' '} - {_.round(mouseCoordinates.lat, DECIMAL_DEGREES_PRECISION)},{' '} - - - {' '} - {_.round(mouseCoordinates.lon, DECIMAL_DEGREES_PRECISION)},{' '} + {latLon} {' '} From 3f11d9c84b3463127858dee244660a7b07880e81 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 6 Apr 2020 21:26:55 -0600 Subject: [PATCH 7/8] [Maps] do not show circle border when symbol size is zero (#62644) Co-authored-by: Elastic Machine --- .../styles/vector/properties/dynamic_size_property.js | 10 +++++++--- .../styles/vector/properties/static_size_property.js | 8 ++++++-- .../maps/public/layers/styles/vector/vector_style.js | 7 +++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js b/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js index 8b3f670bfa5280..71ac25f0c6e619 100644 --- a/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js +++ b/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js @@ -99,9 +99,13 @@ export class DynamicSizeProperty extends DynamicStyleProperty { } } - syncCircleStrokeWidthWithMb(mbLayerId, mbMap) { - const lineWidth = this.getMbSizeExpression(); - mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth); + syncCircleStrokeWidthWithMb(mbLayerId, mbMap, hasNoRadius) { + if (hasNoRadius) { + mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', 0); + } else { + const lineWidth = this.getMbSizeExpression(); + mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth); + } } syncCircleRadiusWithMb(mbLayerId, mbMap) { diff --git a/x-pack/plugins/maps/public/layers/styles/vector/properties/static_size_property.js b/x-pack/plugins/maps/public/layers/styles/vector/properties/static_size_property.js index 2383a5932cb9b1..d86556c6218cf8 100644 --- a/x-pack/plugins/maps/public/layers/styles/vector/properties/static_size_property.js +++ b/x-pack/plugins/maps/public/layers/styles/vector/properties/static_size_property.js @@ -35,8 +35,12 @@ export class StaticSizeProperty extends StaticStyleProperty { mbMap.setLayoutProperty(symbolLayerId, 'icon-size', this._options.size / halfIconPixels); } - syncCircleStrokeWidthWithMb(mbLayerId, mbMap) { - mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', this._options.size); + syncCircleStrokeWidthWithMb(mbLayerId, mbMap, hasNoRadius) { + if (hasNoRadius) { + mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', 0); + } else { + mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', this._options.size); + } } syncCircleRadiusWithMb(mbLayerId, mbMap) { diff --git a/x-pack/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/plugins/maps/public/layers/styles/vector/vector_style.js index ae5d148e43cfd8..b044c98d44d417 100644 --- a/x-pack/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/plugins/maps/public/layers/styles/vector/vector_style.js @@ -543,8 +543,11 @@ export class VectorStyle extends AbstractStyle { setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) { this._fillColorStyleProperty.syncCircleColorWithMb(pointLayerId, mbMap, alpha); this._lineColorStyleProperty.syncCircleStrokeWithMb(pointLayerId, mbMap, alpha); - this._lineWidthStyleProperty.syncCircleStrokeWidthWithMb(pointLayerId, mbMap); - this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap); + const hasNoRadius = + !this._iconSizeStyleProperty.isDynamic() && + this._iconSizeStyleProperty.getOptions().size === 0; + this._lineWidthStyleProperty.syncCircleStrokeWidthWithMb(pointLayerId, mbMap, hasNoRadius); + this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap, hasNoRadius); } setMBPropertiesForLabelText({ alpha, mbMap, textLayerId }) { From dc013cb80f4256f7ffbcb8b814efee8590fc4a8a Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 6 Apr 2020 21:27:47 -0600 Subject: [PATCH 8/8] [Maps] Allow updating requestType for ESGeoGridSource (#62365) * [Maps] Allow updating requestType for ESGeoGridSource * re-add import removed from last merge Co-authored-by: Elastic Machine --- .../data_request_descriptor_types.d.ts | 17 ++++++++++++++++- .../es_geo_grid_source/create_source_editor.js | 3 +-- .../es_geo_grid_source/es_geo_grid_source.js | 6 ++++++ .../es_geo_grid_source/render_as_select.tsx | 7 +++++++ .../es_geo_grid_source/update_source_editor.js | 10 ++++++++++ .../maps/public/layers/sources/source.js | 4 ---- .../public/layers/sources/vector_source.d.ts | 3 +++ .../maps/public/layers/sources/vector_source.js | 4 ++++ 8 files changed, 47 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts index ca0e474491780d..ceba2fe56db12c 100644 --- a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts +++ b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts @@ -5,6 +5,7 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ +import { RENDER_AS, SORT_ORDER, SCALING_TYPES } from '../constants'; import { MapExtent, MapQuery } from './map_descriptor'; // Global map state passed to every layer. @@ -18,12 +19,26 @@ export type MapFilters = { zoom: number; }; +type ESSearchSourceSyncMeta = { + sortField: string; + sortOrder: SORT_ORDER; + scalingType: SCALING_TYPES; + topHitsSplitField: string; + topHitsSize: number; +}; + +type ESGeoGridSourceSyncMeta = { + requestType: RENDER_AS; +}; + +export type VectorSourceSyncMeta = ESSearchSourceSyncMeta | ESGeoGridSourceSyncMeta; + export type VectorSourceRequestMeta = MapFilters & { applyGlobalQuery: boolean; fieldNames: string[]; geogridPrecision: number; sourceQuery: MapQuery; - sourceMeta: unknown; + sourceMeta: VectorSourceSyncMeta; }; export type VectorStyleRequestMeta = MapFilters & { diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js index 4aec390bec745a..265606dc87e0fa 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js @@ -9,7 +9,6 @@ import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; import { SingleFieldSelect } from '../../../components/single_field_select'; -import { RENDER_AS } from '../../../../common/constants'; import { getIndexPatternService, getIndexPatternSelectComponent } from '../../../kibana_services'; import { NoIndexPatternCallout } from '../../../components/no_index_pattern_callout'; import { i18n } from '@kbn/i18n'; @@ -155,7 +154,7 @@ export class CreateSourceEditor extends Component { } _renderRenderAsSelect() { - if (this.state.requestType === RENDER_AS.HEATMAP || !this.state.indexPattern) { + if (!this.state.indexPattern) { return null; } diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index dec802ac3cf1a7..04f944396ab35b 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -70,6 +70,12 @@ export class ESGeoGridSource extends AbstractESAggSource { ); } + getSyncMeta() { + return { + requestType: this._descriptor.requestType, + }; + } + async getImmutableProperties() { let indexPatternTitle = this.getIndexPatternId(); try { diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx index c82781ede186f2..899f4a797ea757 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx @@ -27,7 +27,12 @@ const options = [ export function RenderAsSelect(props: { renderAs: RENDER_AS; onChange: (newValue: RENDER_AS) => void; + isColumnCompressed?: boolean; }) { + if (props.renderAs === RENDER_AS.HEATMAP) { + return null; + } + function onChange(selectedOptions: Array>) { if (!selectedOptions || !selectedOptions.length) { return; @@ -46,6 +51,7 @@ export function RenderAsSelect(props: { label={i18n.translate('xpack.maps.source.esGeoGrid.showAsLabel', { defaultMessage: 'Show as', })} + display={props.isColumnCompressed ? 'columnCompressed' : 'row'} > ); diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js index cd494db3897fb7..c0d6cba3a024a3 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js @@ -15,6 +15,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { isMetricCountable } from '../../util/is_metric_countable'; import { indexPatterns } from '../../../../../../../src/plugins/data/public'; +import { RenderAsSelect } from './render_as_select'; export class UpdateSourceEditor extends Component { state = { @@ -65,6 +66,10 @@ export class UpdateSourceEditor extends Component { this.props.onChange({ propName: 'resolution', value: e }); }; + _onRequestTypeSelect = requestType => { + this.props.onChange({ propName: 'requestType', value: requestType }); + }; + _renderMetricsPanel() { const metricsFilter = this.props.renderAs === RENDER_AS.HEATMAP @@ -113,6 +118,11 @@ export class UpdateSourceEditor extends Component { resolution={this.props.resolution} onChange={this._onResolutionChange} /> + diff --git a/x-pack/plugins/maps/public/layers/sources/source.js b/x-pack/plugins/maps/public/layers/sources/source.js index 368de421e23ce1..3029a5c0912026 100644 --- a/x-pack/plugins/maps/public/layers/sources/source.js +++ b/x-pack/plugins/maps/public/layers/sources/source.js @@ -111,10 +111,6 @@ export class AbstractSource { return 0; } - getSyncMeta() { - return {}; - } - isJoinable() { return false; } diff --git a/x-pack/plugins/maps/public/layers/sources/vector_source.d.ts b/x-pack/plugins/maps/public/layers/sources/vector_source.d.ts index 1400654297e011..d597e642771866 100644 --- a/x-pack/plugins/maps/public/layers/sources/vector_source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/vector_source.d.ts @@ -12,6 +12,7 @@ import { ESSearchSourceResponseMeta, MapExtent, VectorSourceRequestMeta, + VectorSourceSyncMeta, } from '../../../common/descriptor_types'; export type GeoJsonFetchMeta = ESSearchSourceResponseMeta; @@ -31,6 +32,7 @@ export interface IVectorSource extends ISource { getFields(): Promise; getFieldByName(fieldName: string): IField; + getSyncMeta(): VectorSourceSyncMeta; } export class AbstractVectorSource extends AbstractSource implements IVectorSource { @@ -43,4 +45,5 @@ export class AbstractVectorSource extends AbstractSource implements IVectorSourc getFields(): Promise; getFieldByName(fieldName: string): IField; + getSyncMeta(): VectorSourceSyncMeta; } diff --git a/x-pack/plugins/maps/public/layers/sources/vector_source.js b/x-pack/plugins/maps/public/layers/sources/vector_source.js index 7ff1c735c8613a..7f97b1b21d189a 100644 --- a/x-pack/plugins/maps/public/layers/sources/vector_source.js +++ b/x-pack/plugins/maps/public/layers/sources/vector_source.js @@ -151,4 +151,8 @@ export class AbstractVectorSource extends AbstractSource { getSourceTooltipContent(/* sourceDataRequest */) { return { tooltipContent: null, areResultsTrimmed: false }; } + + getSyncMeta() { + return {}; + } }