From e1b9f932cd480d91c74c9585e180bc289e449cb6 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Wed, 16 Feb 2022 14:16:46 +0100 Subject: [PATCH 001/104] Add bulk action outcome to the Bulk API response (#125551) --- .../response/perform_bulk_action_schema.ts | 37 -- .../containers/detection_engine/rules/api.ts | 25 +- .../detection_engine/rules/types.ts | 39 +- .../detection_engine/rules/all/actions.ts | 2 +- .../all/bulk_actions/use_bulk_actions.tsx | 10 +- .../routes/__mocks__/test_adapters.ts | 5 + .../routes/rules/create_rules_bulk_route.ts | 4 +- .../routes/rules/create_rules_route.ts | 4 +- .../routes/rules/patch_rules_bulk_route.ts | 6 +- .../routes/rules/patch_rules_route.ts | 6 +- .../rules/perform_bulk_action_route.test.ts | 70 +++- .../routes/rules/perform_bulk_action_route.ts | 339 ++++++++---------- .../routes/rules/preview_rules_route.ts | 4 +- .../routes/rules/update_rules_bulk_route.ts | 4 +- .../routes/rules/update_rules_route.ts | 4 +- .../routes/rules/utils.test.ts | 22 +- .../detection_engine/routes/rules/utils.ts | 15 +- .../routes/rules/utils/import_rules_utils.ts | 4 +- .../detection_engine/routes/rules/validate.ts | 5 +- ...gacy_get_bulk_rule_actions_saved_object.ts | 2 +- .../client_for_routes/client.ts | 4 +- .../rules/get_export_by_object_ids.ts | 4 +- .../lib/detection_engine/rules/types.ts | 4 +- .../lib/machine_learning/validation.test.ts | 14 +- .../server/lib/machine_learning/validation.ts | 6 +- .../server/utils/promise_pool.test.ts | 56 ++- .../server/utils/promise_pool.ts | 48 ++- .../tests/perform_bulk_action.ts | 87 +++-- 28 files changed, 448 insertions(+), 382 deletions(-) delete mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/perform_bulk_action_schema.ts diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/perform_bulk_action_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/perform_bulk_action_schema.ts deleted file mode 100644 index 2bc3ea8448ee9..0000000000000 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/perform_bulk_action_schema.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; -import { PositiveInteger, PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; - -const rule = t.type({ - id: t.string, - name: t.union([t.string, t.undefined]), -}); - -const error = t.type({ - status_code: PositiveIntegerGreaterThanZero, - message: t.string, - rules: t.array(rule), -}); - -export const bulkActionPartialErrorResponseSchema = t.exact( - t.type({ - status_code: PositiveIntegerGreaterThanZero, - message: t.string, - attributes: t.type({ - errors: t.array(error), - rules: t.type({ - failed: PositiveInteger, - succeeded: PositiveInteger, - total: PositiveInteger, - }), - }), - }) -); - -export type BulkActionPartialErrorResponse = t.TypeOf; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts index c765db6eaecd8..427cf28ef8f2f 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts @@ -45,7 +45,7 @@ import { BulkRuleResponse, PatchRuleProps, BulkActionProps, - BulkActionResponse, + BulkActionResponseMap, PreviewRulesProps, } from './types'; import { KibanaServices } from '../../../../common/lib/kibana'; @@ -266,16 +266,19 @@ export const performBulkAction = async ({ query, edit, ids, -}: BulkActionProps): Promise> => - KibanaServices.get().http.fetch>(DETECTION_ENGINE_RULES_BULK_ACTION, { - method: 'POST', - body: JSON.stringify({ - action, - ...(edit ? { edit } : {}), - ...(ids ? { ids } : {}), - ...(query !== undefined ? { query } : {}), - }), - }); +}: BulkActionProps): Promise> => + KibanaServices.get().http.fetch>( + DETECTION_ENGINE_RULES_BULK_ACTION, + { + method: 'POST', + body: JSON.stringify({ + action, + ...(edit ? { edit } : {}), + ...(ids ? { ids } : {}), + ...(query !== undefined ? { query } : {}), + }), + } + ); /** * Create Prepackaged Rules diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts index 7943bca613488..af5e4fd568a64 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts @@ -236,18 +236,41 @@ export interface BulkActionProps { edit?: BulkActionEditPayload[]; } +export interface BulkActionSummary { + failed: number; + succeeded: number; + total: number; +} + export interface BulkActionResult { - success: boolean; - rules_count: number; + updated: Rule[]; + created: Rule[]; + deleted: Rule[]; +} + +export interface BulkActionAggregatedError { + message: string; + status_code: number; + rules: Array<{ id: string; name?: string }>; +} + +export interface BulkActionResponse { + success?: boolean; + rules_count?: number; + attributes: { + summary: BulkActionSummary; + results: BulkActionResult; + errors?: BulkActionAggregatedError[]; + }; } -export type BulkActionResponse = { - [BulkAction.delete]: BulkActionResult; - [BulkAction.disable]: BulkActionResult; - [BulkAction.enable]: BulkActionResult; - [BulkAction.duplicate]: BulkActionResult; +export type BulkActionResponseMap = { + [BulkAction.delete]: BulkActionResponse; + [BulkAction.disable]: BulkActionResponse; + [BulkAction.enable]: BulkActionResponse; + [BulkAction.duplicate]: BulkActionResponse; [BulkAction.export]: Blob; - [BulkAction.edit]: BulkActionResult; + [BulkAction.edit]: BulkActionResponse; }[Action]; export interface BasicFetchProps { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts index 5b2fdbc5e290e..29b374f3fb26e 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts @@ -209,7 +209,7 @@ const executeRulesBulkAction = async ({ } else { const response = await performBulkAction({ ...search, action, edit: payload?.edit }); - onSuccess?.({ rulesCount: response.rules_count }); + onSuccess?.({ rulesCount: response.attributes.summary.succeeded }); } } catch (e) { if (onError) { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx index 4d3767e73a59e..556213d985db9 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx @@ -45,8 +45,10 @@ import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts'; import { useIsExperimentalFeatureEnabled } from '../../../../../../common/hooks/use_experimental_features'; import { convertRulesFilterToKQL } from '../../../../../containers/detection_engine/rules/utils'; -import type { FilterOptions } from '../../../../../containers/detection_engine/rules/types'; -import type { BulkActionPartialErrorResponse } from '../../../../../../../common/detection_engine/schemas/response/perform_bulk_action_schema'; +import type { + BulkActionResponse, + FilterOptions, +} from '../../../../../containers/detection_engine/rules/types'; import type { HTTPError } from '../../../../../../../common/detection_engine/types'; import { useInvalidateRules } from '../../../../../containers/detection_engine/rules/use_find_rules_query'; @@ -300,8 +302,8 @@ export const useBulkActions = ({ hideWarningToast(); // if response doesn't have number of failed rules, it means the whole bulk action failed // and general error toast will be shown. Otherwise - error toast for partial failure - const failedRulesCount = (error?.body as BulkActionPartialErrorResponse)?.attributes - ?.rules?.failed; + const failedRulesCount = (error?.body as BulkActionResponse)?.attributes?.summary + ?.failed; if (isNaN(failedRulesCount)) { toasts.addError(error, { title: i18n.BULK_ACTION_FAILED }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/test_adapters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/test_adapters.ts index f5d652ef34236..bfbd396851cd8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/test_adapters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/test_adapters.ts @@ -35,6 +35,11 @@ const buildResponses = (method: Method, calls: MockCall[]): ResponseCall[] => { status: call.statusCode, body: JSON.parse(call.body), })); + case 'customError': + return calls.map(([call]) => ({ + status: call.statusCode, + body: call.body, + })); default: throw new Error(`Encountered unexpected call to response.${method}`); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts index a5a982a6d78c6..74f777b29ca01 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts @@ -17,7 +17,7 @@ import { } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { readRules } from '../../rules/read_rules'; import { getDuplicates } from './utils'; import { transformValidateBulkError } from './validate'; @@ -92,7 +92,7 @@ export const createRulesBulkRoute = ( }); } - throwHttpError(await mlAuthz.validateRuleType(internalRule.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(internalRule.params.type)); const finalIndex = internalRule.params.outputIndex; const indexExists = await getIndexExists(esClient.asCurrentUser, finalIndex); if (!isRuleRegistryEnabled && !indexExists) { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts index ef5c7368841db..fe39c5cb9680e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts @@ -14,7 +14,7 @@ import { import { SetupPlugins } from '../../../../plugin'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { readRules } from '../../rules/read_rules'; import { buildSiemResponse } from '../utils'; @@ -79,7 +79,7 @@ export const createRulesRoute = ( request, savedObjectsClient, }); - throwHttpError(await mlAuthz.validateRuleType(internalRule.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(internalRule.params.type)); const indexExists = await getIndexExists( esClient.asCurrentUser, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts index 55c05dd73e33b..58d364cb34b5c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts @@ -17,7 +17,7 @@ import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { transformBulkError, buildSiemResponse } from '../utils'; import { getIdBulkError } from './utils'; import { transformValidateBulkError } from './validate'; @@ -117,7 +117,7 @@ export const patchRulesBulkRoute = ( try { if (type) { // reject an unauthorized "promotion" to ML - throwHttpError(await mlAuthz.validateRuleType(type)); + throwAuthzError(await mlAuthz.validateRuleType(type)); } const existingRule = await readRules({ @@ -128,7 +128,7 @@ export const patchRulesBulkRoute = ( }); if (existingRule?.params.type) { // reject an unauthorized modification of an ML rule - throwHttpError(await mlAuthz.validateRuleType(existingRule?.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(existingRule?.params.type)); } const migratedRule = await legacyMigrate({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts index 0767e86c4e22c..a5bc76cc5ef2e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts @@ -17,7 +17,7 @@ import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { patchRules } from '../../rules/patch_rules'; import { buildSiemResponse } from '../utils'; @@ -118,7 +118,7 @@ export const patchRulesRoute = ( }); if (type) { // reject an unauthorized "promotion" to ML - throwHttpError(await mlAuthz.validateRuleType(type)); + throwAuthzError(await mlAuthz.validateRuleType(type)); } const existingRule = await readRules({ @@ -129,7 +129,7 @@ export const patchRulesRoute = ( }); if (existingRule?.params.type) { // reject an unauthorized modification of an ML rule - throwHttpError(await mlAuthz.validateRuleType(existingRule?.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(existingRule?.params.type)); } const migratedRule = await legacyMigrate({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts index 386b87fefc40c..ecf925bda97e5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts @@ -51,14 +51,36 @@ describe.each([ it('returns 200 when performing bulk action with all dependencies present', async () => { const response = await server.inject(getBulkActionRequest(), context); expect(response.status).toEqual(200); - expect(response.body).toEqual({ success: true, rules_count: 1 }); + expect(response.body).toEqual({ + success: true, + rules_count: 1, + attributes: { + results: someBulkActionResults(), + summary: { + failed: 0, + succeeded: 1, + total: 1, + }, + }, + }); }); it("returns 200 when provided filter query doesn't match any rules", async () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); const response = await server.inject(getBulkActionRequest(), context); expect(response.status).toEqual(200); - expect(response.body).toEqual({ success: true, rules_count: 0 }); + expect(response.body).toEqual({ + success: true, + rules_count: 0, + attributes: { + results: someBulkActionResults(), + summary: { + failed: 0, + succeeded: 0, + total: 0, + }, + }, + }); }); it('returns 400 when provided filter query matches too many rules', async () => { @@ -93,7 +115,7 @@ describe.each([ errors: [ { message: 'Elastic rule can`t be edited', - status_code: 403, + status_code: 400, rules: [ { id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', @@ -102,7 +124,8 @@ describe.each([ ], }, ], - rules: { + results: someBulkActionResults(), + summary: { failed: 1, succeeded: 0, total: 1, @@ -133,7 +156,8 @@ describe.each([ ], }, ], - rules: { + results: someBulkActionResults(), + summary: { failed: 1, succeeded: 0, total: 1, @@ -165,7 +189,8 @@ describe.each([ ], }, ], - rules: { + results: someBulkActionResults(), + summary: { failed: 1, succeeded: 0, total: 1, @@ -202,7 +227,7 @@ describe.each([ expect(response.status).toEqual(500); expect(response.body).toEqual({ attributes: { - rules: { + summary: { failed: 1, succeeded: 0, total: 1, @@ -220,6 +245,7 @@ describe.each([ ], }, ], + results: someBulkActionResults(), }, message: 'Bulk edit failed', status_code: 500, @@ -252,7 +278,7 @@ describe.each([ expect(response.status).toEqual(500); expect(response.body).toEqual({ attributes: { - rules: { + summary: { failed: 1, succeeded: 0, total: 1, @@ -269,6 +295,7 @@ describe.each([ ], }, ], + results: someBulkActionResults(), }, message: 'Bulk edit failed', status_code: 500, @@ -303,7 +330,7 @@ describe.each([ expect(response.status).toEqual(500); expect(response.body).toEqual({ attributes: { - rules: { + summary: { failed: 3, succeeded: 2, total: 5, @@ -334,6 +361,7 @@ describe.each([ ], }, ], + results: someBulkActionResults(), }, message: 'Bulk edit partially failed', status_code: 500, @@ -369,14 +397,14 @@ describe.each([ expect(response.status).toEqual(500); expect(response.body).toEqual({ attributes: { - rules: { + summary: { failed: 1, succeeded: 1, total: 2, }, errors: [ { - message: 'Can`t fetch a rule', + message: 'Rule not found', status_code: 500, rules: [ { @@ -385,6 +413,7 @@ describe.each([ ], }, ], + results: someBulkActionResults(), }, message: 'Bulk edit partially failed', status_code: 500, @@ -498,6 +527,23 @@ describe.each([ const response = await server.inject(getBulkActionEditRequest(), context); expect(response.status).toEqual(200); - expect(response.body).toEqual({ success: true, rules_count: rulesNumber }); + expect(response.body).toEqual( + expect.objectContaining({ + success: true, + rules_count: rulesNumber, + attributes: { + summary: { failed: 0, succeeded: rulesNumber, total: rulesNumber }, + results: someBulkActionResults(), + }, + }) + ); }); }); + +function someBulkActionResults() { + return { + created: expect.any(Array), + deleted: expect.any(Array), + updated: expect.any(Array), + }; +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts index 89f92448847a2..1e1c894ad097c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts @@ -5,11 +5,12 @@ * 2.0. */ +import { truncate } from 'lodash'; import moment from 'moment'; -import { transformError } from '@kbn/securitysolution-es-utils'; -import { Logger } from 'src/core/server'; +import { BadRequestError, transformError } from '@kbn/securitysolution-es-utils'; +import { KibanaResponseFactory, Logger } from 'src/core/server'; -import { RuleAlertType as Rule } from '../../rules/types'; +import { RuleAlertType } from '../../rules/types'; import type { RulesClient } from '../../../../../../alerting/server'; @@ -24,9 +25,13 @@ import { SetupPlugins } from '../../../../plugin'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { routeLimitedConcurrencyTag } from '../../../../utils/route_limited_concurrency_tag'; -import { initPromisePool } from '../../../../utils/promise_pool'; +import { + initPromisePool, + PromisePoolError, + PromisePoolOutcome, +} from '../../../../utils/promise_pool'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { deleteRules } from '../../rules/delete_rules'; import { duplicateRule } from '../../rules/duplicate_rule'; import { findRules } from '../../rules/find_rules'; @@ -35,28 +40,13 @@ import { patchRules } from '../../rules/patch_rules'; import { applyBulkActionEditToRule } from '../../rules/bulk_action_edit'; import { getExportByObjectIds } from '../../rules/get_export_by_object_ids'; import { buildSiemResponse } from '../utils'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; +import { internalRuleToAPIResponse } from '../../schemas/rule_converters'; const MAX_RULES_TO_PROCESS_TOTAL = 10000; const MAX_ERROR_MESSAGE_LENGTH = 1000; const MAX_ROUTE_CONCURRENCY = 5; -type RuleActionFn = (rule: Rule) => Promise; - -type RuleActionSuccess = undefined; - -type RuleActionResult = RuleActionSuccess | RuleActionError; - -interface RuleActionError { - error: { - message: string; - statusCode: number; - }; - rule: { - id: string; - name: string; - }; -} - interface NormalizedRuleError { message: string; status_code: number; @@ -66,18 +56,25 @@ interface NormalizedRuleError { }>; } -const normalizeErrorResponse = (errors: RuleActionError[]): NormalizedRuleError[] => { +const normalizeErrorResponse = ( + errors: Array | PromisePoolError> +): NormalizedRuleError[] => { const errorsMap = new Map(); - errors.forEach((ruleError) => { - const { message } = ruleError.error; + errors.forEach(({ error, item }) => { + const { message, statusCode } = + error instanceof Error ? transformError(error) : { message: String(error), statusCode: 500 }; + // The promise pool item is either a rule ID string or a rule object. We have + // string IDs when we fail to fetch rules. Rule objects come from other + // situations when we found a rule but failed somewhere else. + const rule = typeof item === 'string' ? { id: item } : { id: item.id, name: item.name }; + if (errorsMap.has(message)) { - errorsMap.get(message).rules.push(ruleError.rule); + errorsMap.get(message).rules.push(rule); } else { - const { error, rule } = ruleError; errorsMap.set(message, { - message: error.message, - status_code: error.statusCode, + message: truncate(message, { length: MAX_ERROR_MESSAGE_LENGTH }), + status_code: statusCode, rules: [rule], }); } @@ -86,93 +83,58 @@ const normalizeErrorResponse = (errors: RuleActionError[]): NormalizedRuleError[ return Array.from(errorsMap, ([_, normalizedError]) => normalizedError); }; -const getErrorResponseBody = (errors: RuleActionError[], rulesCount: number) => { - const errorsCount = errors.length; - return { - message: errorsCount === rulesCount ? 'Bulk edit failed' : 'Bulk edit partially failed', - status_code: 500, - attributes: { - errors: normalizeErrorResponse(errors).map(({ message, ...error }) => ({ - ...error, - message: - message.length > MAX_ERROR_MESSAGE_LENGTH - ? `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH - 3)}...` - : message, - })), - rules: { - total: rulesCount, - failed: errorsCount, - succeeded: rulesCount - errorsCount, - }, - }, +const buildBulkResponse = ( + response: KibanaResponseFactory, + fetchRulesOutcome: PromisePoolOutcome, + bulkActionOutcome: PromisePoolOutcome +) => { + const errors = [...fetchRulesOutcome.errors, ...bulkActionOutcome.errors]; + const summary = { + failed: errors.length, + succeeded: bulkActionOutcome.results.length, + total: bulkActionOutcome.results.length + errors.length, }; -}; -const executeActionAndHandleErrors = async ( - rule: Rule, - action: RuleActionFn -): Promise => { - try { - await action(rule); - } catch (err) { - const { message, statusCode } = transformError(err); - return { - error: { message, statusCode }, - rule: { id: rule.id, name: rule.name }, - }; - } -}; - -const executeBulkAction = async (rules: Rule[], action: RuleActionFn, abortSignal: AbortSignal) => - initPromisePool({ - concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, - items: rules, - executor: async (rule) => executeActionAndHandleErrors(rule, action), - abortSignal, - }); - -const getRulesByIds = async ({ - ids, - rulesClient, - isRuleRegistryEnabled, - abortSignal, -}: { - ids: string[]; - rulesClient: RulesClient; - isRuleRegistryEnabled: boolean; - abortSignal: AbortSignal; -}) => { - const readRulesExecutor = async (id: string) => { - try { - const rule = await readRules({ id, rulesClient, isRuleRegistryEnabled, ruleId: undefined }); - if (rule == null) { - throw Error('Can`t fetch a rule'); - } - return { rule }; - } catch (err) { - const { message, statusCode } = transformError(err); - return { - error: { message, statusCode }, - rule: { id }, - }; - } + const results = { + updated: bulkActionOutcome.results + .filter(({ item, result }) => item.id === result?.id) + .map(({ result }) => result && internalRuleToAPIResponse(result)), + created: bulkActionOutcome.results + .filter(({ item, result }) => result != null && result.id !== item.id) + .map(({ result }) => result && internalRuleToAPIResponse(result)), + deleted: bulkActionOutcome.results + .filter(({ result }) => result == null) + .map(({ item }) => internalRuleToAPIResponse(item)), }; - const { results } = await initPromisePool({ - concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, - items: ids, - executor: readRulesExecutor, - abortSignal, - }); + if (errors.length > 0) { + return response.custom({ + headers: { 'content-type': 'application/json' }, + body: Buffer.from( + JSON.stringify({ + message: summary.succeeded > 0 ? 'Bulk edit partially failed' : 'Bulk edit failed', + status_code: 500, + attributes: { + errors: normalizeErrorResponse(errors), + results, + summary, + }, + }) + ), + statusCode: 500, + }); + } - return { - total: ids.length, - rules: results.filter((rule) => rule.error === undefined).map(({ rule }) => rule) as Rule[], - fetchErrors: results.filter((rule): rule is RuleActionError => rule.error !== undefined), - }; + return response.ok({ + body: { + success: true, + rules_count: summary.total, + attributes: { results, summary }, + }, + }); }; -const fetchRules = async ({ +const fetchRulesByQueryOrIds = async ({ query, ids, rulesClient, @@ -184,12 +146,18 @@ const fetchRules = async ({ rulesClient: RulesClient; isRuleRegistryEnabled: boolean; abortSignal: AbortSignal; -}) => { +}): Promise> => { if (ids) { - return getRulesByIds({ - ids, - rulesClient, - isRuleRegistryEnabled, + return initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: ids, + executor: async (id: string) => { + const rule = await readRules({ id, rulesClient, isRuleRegistryEnabled, ruleId: undefined }); + if (rule == null) { + throw Error('Rule not found'); + } + return rule; + }, abortSignal, }); } @@ -205,10 +173,15 @@ const fetchRules = async ({ fields: undefined, }); + if (total > MAX_RULES_TO_PROCESS_TOTAL) { + throw new BadRequestError( + `More than ${MAX_RULES_TO_PROCESS_TOTAL} rules matched the filter query. Try to narrow it down.` + ); + } + return { - rules: data, - total, - fetchErrors: [] as RuleActionError[], + results: data.map((rule) => ({ item: rule.id, result: rule })), + errors: [], }; }; @@ -268,7 +241,7 @@ export const performBulkActionRoute = ( savedObjectsClient, }); - const { rules, total, fetchErrors } = await fetchRules({ + const fetchRulesOutcome = await fetchRulesByQueryOrIds({ isRuleRegistryEnabled, rulesClient, query: body.query, @@ -276,68 +249,77 @@ export const performBulkActionRoute = ( abortSignal: abortController.signal, }); - if (total > MAX_RULES_TO_PROCESS_TOTAL) { - return siemResponse.error({ - body: `More than ${MAX_RULES_TO_PROCESS_TOTAL} rules matched the filter query. Try to narrow it down.`, - statusCode: 400, - }); - } + const rules = fetchRulesOutcome.results.map(({ result }) => result); + let bulkActionOutcome: PromisePoolOutcome; - let processingResponse: { - results: RuleActionResult[]; - } = { - results: [], - }; switch (body.action) { case BulkAction.enable: - processingResponse = await executeBulkAction( - rules, - async (rule) => { + bulkActionOutcome = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { if (!rule.enabled) { - throwHttpError(await mlAuthz.validateRuleType(rule.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(rule.params.type)); await rulesClient.enable({ id: rule.id }); } + + return { + ...rule, + enabled: true, + }; }, - abortController.signal - ); + abortSignal: abortController.signal, + }); break; case BulkAction.disable: - processingResponse = await executeBulkAction( - rules, - async (rule) => { + bulkActionOutcome = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { if (rule.enabled) { - throwHttpError(await mlAuthz.validateRuleType(rule.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(rule.params.type)); await rulesClient.disable({ id: rule.id }); } + + return { + ...rule, + enabled: false, + }; }, - abortController.signal - ); + abortSignal: abortController.signal, + }); break; case BulkAction.delete: - processingResponse = await executeBulkAction( - rules, - async (rule) => { + bulkActionOutcome = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { await deleteRules({ ruleId: rule.id, rulesClient, ruleExecutionLog, }); + + return null; }, - abortController.signal - ); + abortSignal: abortController.signal, + }); break; case BulkAction.duplicate: - processingResponse = await executeBulkAction( - rules, - async (rule) => { - throwHttpError(await mlAuthz.validateRuleType(rule.params.type)); + bulkActionOutcome = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { + throwAuthzError(await mlAuthz.validateRuleType(rule.params.type)); - await rulesClient.create({ + const createdRule = await rulesClient.create({ data: duplicateRule(rule, isRuleRegistryEnabled), }); + + return createdRule; }, - abortController.signal - ); + abortSignal: abortController.signal, + }); break; case BulkAction.export: const exported = await getExportByObjectIds( @@ -359,15 +341,15 @@ export const performBulkActionRoute = ( body: responseBody, }); case BulkAction.edit: - processingResponse = await executeBulkAction( - rules, - async (rule) => { - throwHttpError({ - valid: !rule.params.immutable, - message: 'Elastic rule can`t be edited', - }); + bulkActionOutcome = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { + if (rule.params.immutable) { + throw new BadRequestError('Elastic rule can`t be edited'); + } - throwHttpError(await mlAuthz.validateRuleType(rule.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(rule.params.type)); const editedRule = body[BulkAction.edit].reduce( (acc, action) => applyBulkActionEditToRule(acc, action), @@ -385,40 +367,19 @@ export const performBulkActionRoute = ( timelineTitle, timelineId, }); + + return editedRule; }, - abortController.signal - ); + abortSignal: abortController.signal, + }); + break; } if (abortController.signal.aborted === true) { - throw Error('Bulk action was aborted'); + throw new AbortError('Bulk action was aborted'); } - const errors = [ - ...fetchErrors, - ...processingResponse.results.filter( - (resp): resp is RuleActionError => resp?.error !== undefined - ), - ]; - - if (errors.length > 0) { - const responseBody = getErrorResponseBody(errors, total); - - return response.custom({ - headers: { - 'content-type': 'application/json', - }, - body: Buffer.from(JSON.stringify(responseBody)), - statusCode: 500, - }); - } - - return response.ok({ - body: { - success: true, - rules_count: total, - }, - }); + return buildBulkResponse(response, fetchRulesOutcome, bulkActionOutcome); } catch (err) { const error = transformError(err); return siemResponse.error({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts index e4626aaa93216..775817dcb8a0c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts @@ -14,7 +14,7 @@ import { RuleParams } from '../../schemas/rule_schemas'; import { createPreviewRuleExecutionLogger } from '../../signals/preview/preview_rule_execution_logger'; import { parseInterval } from '../../signals/utils'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { SetupPlugins } from '../../../../plugin'; import type { SecuritySolutionPluginRouter } from '../../../../types'; @@ -106,7 +106,7 @@ export const previewRulesRoute = async ( request, savedObjectsClient, }); - throwHttpError(await mlAuthz.validateRuleType(internalRule.params.type)); + throwAuthzError(await mlAuthz.validateRuleType(internalRule.params.type)); await context.lists?.getExceptionListClient().createEndpointList(); const spaceId = siemClient.getSpaceId(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts index f560230cd531b..d1df5713914df 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts @@ -14,7 +14,7 @@ import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { getIdBulkError } from './utils'; import { transformValidateBulkError } from './validate'; import { transformBulkError, buildSiemResponse, createBulkErrorObject } from '../utils'; @@ -65,7 +65,7 @@ export const updateRulesBulkRoute = ( }); } - throwHttpError(await mlAuthz.validateRuleType(payloadRule.type)); + throwAuthzError(await mlAuthz.validateRuleType(payloadRule.type)); const existingRule = await readRules({ isRuleRegistryEnabled, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts index 4f63e49cd1690..8ac90748d9217 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts @@ -12,7 +12,7 @@ import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; -import { throwHttpError } from '../../../machine_learning/validation'; +import { throwAuthzError } from '../../../machine_learning/validation'; import { buildSiemResponse } from '../utils'; import { getIdError } from './utils'; @@ -54,7 +54,7 @@ export const updateRulesRoute = ( request, savedObjectsClient, }); - throwHttpError(await mlAuthz.validateRuleType(request.body.type)); + throwAuthzError(await mlAuthz.validateRuleType(request.body.type)); const existingRule = await readRules({ isRuleRegistryEnabled, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts index db04d8eded869..0ca665bb10584 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts @@ -10,7 +10,6 @@ import { createPromiseFromStreams } from '@kbn/utils'; import { Action, ThreatMapping } from '@kbn/securitysolution-io-ts-alerting-types'; import { - transformAlertToRule, getIdError, transformFindAlerts, transform, @@ -39,6 +38,7 @@ import { getQueryRuleParams, getThreatRuleParams, } from '../../schemas/rule_schemas.mock'; +import { internalRuleToAPIResponse } from '../../schemas/rule_converters'; import { requestContextMock } from '../__mocks__'; // eslint-disable-next-line no-restricted-imports @@ -70,17 +70,17 @@ describe.each([ ])('utils - %s', (_, isRuleRegistryEnabled) => { const { clients } = requestContextMock.createTools(); - describe('transformAlertToRule', () => { + describe('internalRuleToAPIResponse', () => { test('should work with a full data set', () => { const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); - const rule = transformAlertToRule(fullRule); + const rule = internalRuleToAPIResponse(fullRule); expect(rule).toEqual(getOutputRuleAlertForRest()); }); test('should omit note if note is undefined', () => { const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.params.note = undefined; - const rule = transformAlertToRule(fullRule); + const rule = internalRuleToAPIResponse(fullRule); const { note, ...expectedWithoutNote } = getOutputRuleAlertForRest(); expect(rule).toEqual(expectedWithoutNote); }); @@ -88,7 +88,7 @@ describe.each([ test('should return enabled is equal to false', () => { const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.enabled = false; - const ruleWithEnabledFalse = transformAlertToRule(fullRule); + const ruleWithEnabledFalse = internalRuleToAPIResponse(fullRule); const expected = getOutputRuleAlertForRest(); expected.enabled = false; expect(ruleWithEnabledFalse).toEqual(expected); @@ -97,7 +97,7 @@ describe.each([ test('should return immutable is equal to false', () => { const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.params.immutable = false; - const ruleWithEnabledFalse = transformAlertToRule(fullRule); + const ruleWithEnabledFalse = internalRuleToAPIResponse(fullRule); const expected = getOutputRuleAlertForRest(); expect(ruleWithEnabledFalse).toEqual(expected); }); @@ -105,7 +105,7 @@ describe.each([ test('should work with tags but filter out any internal tags', () => { const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.tags = ['tag 1', 'tag 2', `${INTERNAL_IDENTIFIER}_some_other_value`]; - const rule = transformAlertToRule(fullRule); + const rule = internalRuleToAPIResponse(fullRule); const expected = getOutputRuleAlertForRest(); expected.tags = ['tag 1', 'tag 2']; expect(rule).toEqual(expected); @@ -117,7 +117,7 @@ describe.each([ mlRule.params.machineLearningJobId = ['some_job_id']; mlRule.params.type = 'machine_learning'; - const rule = transformAlertToRule(mlRule); + const rule = internalRuleToAPIResponse(mlRule); expect(rule).toEqual( expect.objectContaining({ anomaly_threshold: 55, @@ -165,7 +165,7 @@ describe.each([ threatRule.params.threatMapping = threatMapping; threatRule.params.threatQuery = '*:*'; - const rule = transformAlertToRule(threatRule); + const rule = internalRuleToAPIResponse(threatRule); expect(rule).toEqual( expect.objectContaining({ threat_index: ['index-123'], @@ -183,7 +183,7 @@ describe.each([ lists: [], ...getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), }; - const rule = transformAlertToRule(result); + const rule = internalRuleToAPIResponse(result); expect(rule).toEqual( expect.not.objectContaining({ lists: [], @@ -198,7 +198,7 @@ describe.each([ exceptions_list: [], ...getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), }; - const rule = transformAlertToRule(result); + const rule = internalRuleToAPIResponse(result); expect(rule).toEqual( expect.not.objectContaining({ exceptions_list: [], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts index 7e9f03cf828a8..ff2eab1f799b9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts @@ -22,7 +22,6 @@ import { RuleAlertType, isAlertType } from '../../rules/types'; import { createBulkErrorObject, BulkError, OutputError } from '../utils'; import { internalRuleToAPIResponse } from '../../schemas/rule_converters'; import { RuleParams } from '../../schemas/rule_schemas'; -import { SanitizedAlert } from '../../../../../../alerting/common'; // eslint-disable-next-line no-restricted-imports import { LegacyRulesActionsSavedObject } from '../../rule_actions/legacy_get_rule_actions_saved_object'; import { RuleExecutionSummariesByRuleId } from '../../rule_execution_log'; @@ -93,21 +92,11 @@ export const transformTags = (tags: string[]): string[] => { return tags.filter((tag) => !tag.startsWith(INTERNAL_IDENTIFIER)); }; -// Transforms the data but will remove any null or undefined it encounters and not include -// those on the export -export const transformAlertToRule = ( - rule: SanitizedAlert, - ruleExecutionSummary?: RuleExecutionSummary | null, - legacyRuleActions?: LegacyRulesActionsSavedObject | null -): Partial => { - return internalRuleToAPIResponse(rule, ruleExecutionSummary, legacyRuleActions); -}; - export const transformAlertsToRules = ( rules: RuleAlertType[], legacyRuleActions: Record ): Array> => { - return rules.map((rule) => transformAlertToRule(rule, null, legacyRuleActions[rule.id])); + return rules.map((rule) => internalRuleToAPIResponse(rule, null, legacyRuleActions[rule.id])); }; export const transformFindAlerts = ( @@ -138,7 +127,7 @@ export const transform = ( legacyRuleActions?: LegacyRulesActionsSavedObject | null ): Partial | null => { if (isAlertType(isRuleRegistryEnabled ?? false, rule)) { - return transformAlertToRule(rule, ruleExecutionSummary, legacyRuleActions); + return internalRuleToAPIResponse(rule, ruleExecutionSummary, legacyRuleActions); } return null; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/import_rules_utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/import_rules_utils.ts index 121e54c768856..fd4c751d7fb84 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/import_rules_utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/import_rules_utils.ts @@ -21,7 +21,7 @@ import { readRules } from '../../../rules/read_rules'; import { patchRules } from '../../../rules/patch_rules'; import { ImportRulesSchemaDecoded } from '../../../../../../common/detection_engine/schemas/request/import_rules_schema'; import { MlAuthz } from '../../../../machine_learning/authz'; -import { throwHttpError } from '../../../../machine_learning/validation'; +import { throwAuthzError } from '../../../../machine_learning/validation'; import { RulesClient } from '../../../../../../../../plugins/alerting/server'; import { ExceptionListClient } from '../../../../../../../../plugins/lists/server'; import { checkRuleExceptionReferences } from './check_rule_exception_references'; @@ -165,7 +165,7 @@ export const importRules = async ({ const language = !isMlRule(type) && languageOrUndefined == null ? 'kuery' : languageOrUndefined; // TODO: Fix these either with an is conversion or by better typing them within io-ts const filters: PartialFilter[] | undefined = filtersRest as PartialFilter[]; - throwHttpError(await mlAuthz.validateRuleType(type)); + throwAuthzError(await mlAuthz.validateRuleType(type)); const rule = await readRules({ isRuleRegistryEnabled, rulesClient, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts index 54a1b3521f2b1..e743e26e8da3f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts @@ -19,10 +19,11 @@ import { import { PartialAlert } from '../../../../../../alerting/server'; import { isAlertType } from '../../rules/types'; import { createBulkErrorObject, BulkError } from '../utils'; -import { transform, transformAlertToRule } from './utils'; +import { transform } from './utils'; import { RuleParams } from '../../schemas/rule_schemas'; // eslint-disable-next-line no-restricted-imports import { LegacyRulesActionsSavedObject } from '../../rule_actions/legacy_get_rule_actions_saved_object'; +import { internalRuleToAPIResponse } from '../../schemas/rule_converters'; export const transformValidate = ( rule: PartialAlert, @@ -69,7 +70,7 @@ export const transformValidateBulkError = ( isRuleRegistryEnabled?: boolean ): RulesSchema | BulkError => { if (isAlertType(isRuleRegistryEnabled ?? false, rule)) { - const transformed = transformAlertToRule(rule, ruleExecutionSummary); + const transformed = internalRuleToAPIResponse(rule, ruleExecutionSummary); const [validated, errors] = validateNonExact(transformed, rulesSchema); if (errors != null || validated == null) { return createBulkErrorObject({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_get_bulk_rule_actions_saved_object.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_get_bulk_rule_actions_saved_object.ts index 72cfada909cdc..feaaa7f3e6c08 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_get_bulk_rule_actions_saved_object.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_get_bulk_rule_actions_saved_object.ts @@ -62,7 +62,7 @@ export const legacyGetBulkRuleActionsSavedObject = async ({ throw new AggregateError(errors, 'Error fetching rule actions'); } - const savedObjects = results.flatMap((result) => result.saved_objects); + const savedObjects = results.flatMap(({ result }) => result.saved_objects); return savedObjects.reduce( (acc: { [key: string]: LegacyRulesActionsSavedObject }, savedObject) => { const ruleAlertId = savedObject.references.find((reference) => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client.ts index 05647089bbd45..a4c528d941ba4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client.ts @@ -30,7 +30,7 @@ export const createClientForRoutes = ( return { /** * Get the current rule execution summary for each of the given rule IDs. - * This method splits work into chunks so not to owerwhelm Elasticsearch + * This method splits work into chunks so not to overwhelm Elasticsearch * when fetching statuses for a big number of rules. * * @param ruleIds A list of rule IDs (`rule.id`) to fetch summaries for @@ -71,7 +71,7 @@ export const createClientForRoutes = ( } // Merge all rule statuses into a single dict - return Object.assign({}, ...results); + return Object.assign({}, ...results.map(({ result }) => result)); } catch (e) { const ruleIdsString = `[${truncateList(ruleIds).join(', ')}]`; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts index 7381e2c3a1f02..1181995e0ae4a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts @@ -16,13 +16,13 @@ import { RulesClient, AlertServices } from '../../../../../alerting/server'; import { getExportDetailsNdjson } from './get_export_details_ndjson'; import { isAlertType } from '../rules/types'; -import { transformAlertToRule } from '../routes/rules/utils'; import { INTERNAL_RULE_ID_KEY } from '../../../../common/constants'; import { findRules } from './find_rules'; import { getRuleExceptionsForExport } from './get_export_rule_exceptions'; // eslint-disable-next-line no-restricted-imports import { legacyGetBulkRuleActionsSavedObject } from '../rule_actions/legacy_get_bulk_rule_actions_saved_object'; +import { internalRuleToAPIResponse } from '../schemas/rule_converters'; interface ExportSuccessRule { statusCode: 200; @@ -127,7 +127,7 @@ export const getRulesFromObjects = async ( ) { return { statusCode: 200, - rule: transformAlertToRule(matchingRule, null, legacyActions[matchingRule.id]), + rule: internalRuleToAPIResponse(matchingRule, null, legacyActions[matchingRule.id]), }; } else { return { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts index f726434b279f2..74fb5bfe672a0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts @@ -199,13 +199,13 @@ export interface CreateRulesOptions { export interface UpdateRulesOptions { rulesClient: RulesClient; defaultOutputIndex: string; - existingRule: SanitizedAlert | null | undefined; + existingRule: RuleAlertType | null | undefined; ruleUpdate: UpdateRulesSchema; } export interface PatchRulesOptions extends Partial { rulesClient: RulesClient; - rule: SanitizedAlert | null | undefined; + rule: RuleAlertType | null | undefined; } interface PatchRulesFieldsOptions { diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/validation.test.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/validation.test.ts index 53d6279b06f63..61f305c22d796 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/validation.test.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/validation.test.ts @@ -5,29 +5,29 @@ * 2.0. */ -import { toHttpError, throwHttpError } from './validation'; +import { toAuthzError, throwAuthzError } from './validation'; -describe('toHttpError', () => { +describe('toAuthzError', () => { it('returns nothing if validation is valid', () => { - expect(toHttpError({ valid: true, message: undefined })).toBeUndefined(); + expect(toAuthzError({ valid: true, message: undefined })).toBeUndefined(); }); it('returns an HTTP error if validation is invalid', () => { - const error = toHttpError({ valid: false, message: 'validation message' }); + const error = toAuthzError({ valid: false, message: 'validation message' }); expect(error?.statusCode).toEqual(403); expect(error?.message).toEqual('validation message'); }); }); -describe('throwHttpError', () => { +describe('throwAuthzError', () => { it('does nothing if validation is valid', () => { - expect(() => throwHttpError({ valid: true, message: undefined })).not.toThrowError(); + expect(() => throwAuthzError({ valid: true, message: undefined })).not.toThrowError(); }); it('throws an error if validation is invalid', () => { let error; try { - throwHttpError({ valid: false, message: 'validation failed' }); + throwAuthzError({ valid: false, message: 'validation failed' }); } catch (e) { error = e; } diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/validation.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/validation.ts index 614eff01c2bbf..45d6ebf7a905f 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/validation.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/validation.ts @@ -20,14 +20,14 @@ export class HttpAuthzError extends Error { } } -export const toHttpError = (validation: Validation): HttpAuthzError | undefined => { +export const toAuthzError = (validation: Validation): HttpAuthzError | undefined => { if (!validation.valid) { return new HttpAuthzError(validation.message); } }; -export const throwHttpError = (validation: Validation): void => { - const error = toHttpError(validation); +export const throwAuthzError = (validation: Validation): void => { + const error = toAuthzError(validation); if (error) { throw error; } diff --git a/x-pack/plugins/security_solution/server/utils/promise_pool.test.ts b/x-pack/plugins/security_solution/server/utils/promise_pool.test.ts index 585044de5856a..1203c35a4dc61 100644 --- a/x-pack/plugins/security_solution/server/utils/promise_pool.test.ts +++ b/x-pack/plugins/security_solution/server/utils/promise_pool.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { AbortError } from '../../../../../src/plugins/kibana_utils/common'; import { initPromisePool } from './promise_pool'; const nextTick = () => new Promise((resolve) => setImmediate(resolve)); @@ -50,7 +51,11 @@ describe('initPromisePool', () => { executor: async (x) => x, }); - expect(results).toEqual([1, 2, 3]); + expect(results).toEqual([ + { item: 1, result: 1 }, + { item: 2, result: 2 }, + { item: 3, result: 3 }, + ]); expect(errors).toEqual([]); }); @@ -65,9 +70,9 @@ describe('initPromisePool', () => { expect(results).toEqual([]); expect(errors).toEqual([ - new Error(`Error processing 1`), - new Error(`Error processing 2`), - new Error(`Error processing 3`), + { item: 1, error: new Error(`Error processing 1`) }, + { item: 2, error: new Error(`Error processing 2`) }, + { item: 3, error: new Error(`Error processing 3`) }, ]); }); @@ -104,7 +109,7 @@ describe('initPromisePool', () => { asyncTasks[3].resolve(); await nextTick(); - // Check that all taks have been settled + // Check that all tasks have been settled expect(asyncTasks).toEqual({ 1: expect.objectContaining({ status: 'resolved' }), 2: expect.objectContaining({ status: 'rejected' }), @@ -114,8 +119,11 @@ describe('initPromisePool', () => { const { results, errors } = await promisePool; // Check final results - expect(results).toEqual([1, 3]); - expect(errors).toEqual([new Error(`Error processing 2`)]); + expect(results).toEqual([ + { item: 1, result: 1 }, + { item: 3, result: 3 }, + ]); + expect(errors).toEqual([{ item: 2, error: new Error(`Error processing 2`) }]); }); it('should be possible to configure concurrency', async () => { @@ -157,7 +165,7 @@ describe('initPromisePool', () => { asyncTasks[5].resolve(); await nextTick(); - // Check that all taks have been settled + // Check that all tasks have been settled expect(asyncTasks).toEqual({ 1: expect.objectContaining({ status: 'resolved' }), 2: expect.objectContaining({ status: 'rejected' }), @@ -169,8 +177,15 @@ describe('initPromisePool', () => { const { results, errors } = await promisePool; // Check final results - expect(results).toEqual([1, 4, 5]); - expect(errors).toEqual([new Error(`Error processing 2`), new Error(`Error processing 3`)]); + expect(results).toEqual([ + { item: 1, result: 1 }, + { item: 4, result: 4 }, + { item: 5, result: 5 }, + ]); + expect(errors).toEqual([ + { item: 2, error: new Error(`Error processing 2`) }, + { item: 3, error: new Error(`Error processing 3`) }, + ]); }); it('should not execute tasks if abortSignal is aborted', async () => { @@ -183,12 +198,17 @@ describe('initPromisePool', () => { abortSignal as AbortSignal ); - const { results, errors, abortedExecutionsCount } = await promisePool; + const { results, errors } = await promisePool; // Check final results expect(results).toEqual([]); - expect(errors).toEqual([]); - expect(abortedExecutionsCount).toEqual(5); + expect(errors).toEqual([ + { item: 1, error: new AbortError() }, + { item: 2, error: new AbortError() }, + { item: 3, error: new AbortError() }, + { item: 4, error: new AbortError() }, + { item: 5, error: new AbortError() }, + ]); }); it('should abort executions of tasks if abortSignal was set to aborted during execution', async () => { @@ -209,11 +229,13 @@ describe('initPromisePool', () => { abortSignal.aborted = true; - const { results, errors, abortedExecutionsCount } = await promisePool; + const { results, errors } = await promisePool; // Check final results - expect(results).toEqual([1]); - expect(errors).toEqual([]); - expect(abortedExecutionsCount).toEqual(2); + expect(results).toEqual([{ item: 1, result: 1 }]); + expect(errors).toEqual([ + { item: 2, error: new AbortError() }, + { item: 3, error: new AbortError() }, + ]); }); }); diff --git a/x-pack/plugins/security_solution/server/utils/promise_pool.ts b/x-pack/plugins/security_solution/server/utils/promise_pool.ts index ed0922b952c77..766ba873fad53 100644 --- a/x-pack/plugins/security_solution/server/utils/promise_pool.ts +++ b/x-pack/plugins/security_solution/server/utils/promise_pool.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { AbortError } from '../../../../../src/plugins/kibana_utils/common'; + interface PromisePoolArgs { concurrency?: number; items: Item[]; @@ -12,6 +14,21 @@ interface PromisePoolArgs { abortSignal?: AbortSignal; } +export interface PromisePoolError { + item: Item; + error: Error; +} + +export interface PromisePoolResult { + item: Item; + result: Result; +} + +export interface PromisePoolOutcome { + results: Array>; + errors: Array>; +} + /** * Runs promises in batches. It ensures that the number of running async tasks * doesn't exceed the concurrency parameter passed to the function. @@ -24,15 +41,14 @@ interface PromisePoolArgs { * @returns Struct holding results or errors of async tasks, aborted executions count if applicable */ -export const initPromisePool = async ({ +export const initPromisePool = async ({ concurrency = 1, items, executor, abortSignal, -}: PromisePoolArgs) => { +}: PromisePoolArgs): Promise> => { const tasks: Array> = []; - const results: Result[] = []; - const errors: unknown[] = []; + const outcome: PromisePoolOutcome = { results: [], errors: [] }; for (const item of items) { // Check if the pool is full @@ -41,17 +57,20 @@ export const initPromisePool = async ({ await Promise.race(tasks); } - // if abort signal was sent stop processing tasks further - if (abortSignal?.aborted === true) { - break; - } + const executeItem = async () => { + // if abort signal was sent stop processing tasks further + if (abortSignal?.aborted === true) { + throw new AbortError(); + } + return executor(item); + }; - const task: Promise = executor(item) + const task: Promise = executeItem() .then((result) => { - results.push(result); + outcome.results.push({ item, result }); }) .catch(async (error) => { - errors.push(error); + outcome.errors.push({ item, error }); }) .finally(() => { tasks.splice(tasks.indexOf(task), 1); @@ -63,10 +82,5 @@ export const initPromisePool = async ({ // Wait for all remaining tasks to finish await Promise.all(tasks); - const aborted = - abortSignal?.aborted === true - ? { abortedExecutionsCount: items.length - results.length - errors.length } - : undefined; - - return { results, errors, ...aborted }; + return outcome; }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/perform_bulk_action.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/perform_bulk_action.ts index 06223fbca7070..1bbfafd8f0b14 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/perform_bulk_action.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/perform_bulk_action.ts @@ -79,15 +79,20 @@ export default ({ getService }: FtrProviderContext): void => { it('should delete rules', async () => { const ruleId = 'ruleId'; - await createRule(supertest, log, getSimpleRule(ruleId)); + const testRule = getSimpleRule(ruleId); + await createRule(supertest, log, testRule); const { body } = await postBulkAction() .send({ query: '', action: BulkAction.delete }) .expect(200); - expect(body).to.eql({ success: true, rules_count: 1 }); + expect(body.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + + // Check that the deleted rule is returned with the response + expect(body.attributes.results.deleted[0].name).to.eql(testRule.name); - await await fetchRule(ruleId).expect(404); + // Check that the updates have been persisted + await fetchRule(ruleId).expect(404); }); it('should enable rules', async () => { @@ -98,16 +103,14 @@ export default ({ getService }: FtrProviderContext): void => { .send({ query: '', action: BulkAction.enable }) .expect(200); - expect(body).to.eql({ success: true, rules_count: 1 }); - - const { body: ruleBody } = await fetchRule(ruleId).expect(200); - - const referenceRule = getSimpleRuleOutput(ruleId); - referenceRule.enabled = true; + expect(body.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); - const storedRule = removeServerGeneratedProperties(ruleBody); + // Check that the updated rule is returned with the response + expect(body.attributes.results.updated[0].enabled).to.eql(true); - expect(storedRule).to.eql(referenceRule); + // Check that the updates have been persisted + const { body: ruleBody } = await fetchRule(ruleId).expect(200); + expect(ruleBody.enabled).to.eql(true); }); it('should disable rules', async () => { @@ -118,26 +121,31 @@ export default ({ getService }: FtrProviderContext): void => { .send({ query: '', action: BulkAction.disable }) .expect(200); - expect(body).to.eql({ success: true, rules_count: 1 }); - - const { body: ruleBody } = await fetchRule(ruleId).expect(200); + expect(body.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); - const referenceRule = getSimpleRuleOutput(ruleId); - const storedRule = removeServerGeneratedProperties(ruleBody); + // Check that the updated rule is returned with the response + expect(body.attributes.results.updated[0].enabled).to.eql(false); - expect(storedRule).to.eql(referenceRule); + // Check that the updates have been persisted + const { body: ruleBody } = await fetchRule(ruleId).expect(200); + expect(ruleBody.enabled).to.eql(false); }); it('should duplicate rules', async () => { const ruleId = 'ruleId'; - await createRule(supertest, log, getSimpleRule(ruleId)); + const ruleToDuplicate = getSimpleRule(ruleId); + await createRule(supertest, log, ruleToDuplicate); const { body } = await postBulkAction() .send({ query: '', action: BulkAction.duplicate }) .expect(200); - expect(body).to.eql({ success: true, rules_count: 1 }); + expect(body.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + + // Check that the duplicated rule is returned with the response + expect(body.attributes.results.created[0].name).to.eql(`${ruleToDuplicate.name} [Duplicate]`); + // Check that the updates have been persisted const { body: rulesResponse } = await supertest .get(`${DETECTION_ENGINE_RULES_URL}/_find`) .set('kbn-xsrf', 'true') @@ -165,8 +173,12 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(setTagsBody).to.eql({ success: true, rules_count: 1 }); + expect(setTagsBody.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + // Check that the updated rule is returned with the response + expect(setTagsBody.attributes.results.updated[0].tags).to.eql(['reset-tag']); + + // Check that the updates have been persisted const { body: setTagsRule } = await fetchRule(ruleId).expect(200); expect(setTagsRule.tags).to.eql(['reset-tag']); @@ -184,8 +196,12 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(addTagsBody).to.eql({ success: true, rules_count: 1 }); + expect(addTagsBody.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + + // Check that the updated rule is returned with the response + expect(addTagsBody.attributes.results.updated[0].tags).to.eql(['reset-tag', ...tags]); + // Check that the updates have been persisted const { body: addedTagsRule } = await fetchRule(ruleId).expect(200); expect(addedTagsRule.tags).to.eql(['reset-tag', ...tags]); @@ -226,8 +242,12 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(setIndexBody).to.eql({ success: true, rules_count: 1 }); + expect(setIndexBody.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + // Check that the updated rule is returned with the response + expect(setIndexBody.attributes.results.updated[0].index).to.eql(['initial-index-*']); + + // Check that the updates have been persisted const { body: setIndexRule } = await fetchRule(ruleId).expect(200); expect(setIndexRule.index).to.eql(['initial-index-*']); @@ -245,8 +265,15 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(addIndexBody).to.eql({ success: true, rules_count: 1 }); + expect(addIndexBody.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + + // Check that the updated rule is returned with the response + expect(addIndexBody.attributes.results.updated[0].index).to.eql([ + 'initial-index-*', + ...indices, + ]); + // Check that the updates have been persisted const { body: addIndexRule } = await fetchRule(ruleId).expect(200); expect(addIndexRule.index).to.eql(['initial-index-*', ...indices]); @@ -291,8 +318,13 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(body).to.eql({ success: true, rules_count: 1 }); + expect(body.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + // Check that the updated rule is returned with the response + expect(body.attributes.results.updated[0].timeline_id).to.eql(timelineId); + expect(body.attributes.results.updated[0].timeline_title).to.eql(timelineTitle); + + // Check that the updates have been persisted const { body: rule } = await fetchRule(ruleId).expect(200); expect(rule.timeline_id).to.eql(timelineId); @@ -352,8 +384,13 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(body).to.eql({ success: true, rules_count: 1 }); + expect(body.attributes.summary).to.eql({ failed: 0, succeeded: 1, total: 1 }); + + // Check that the updated rule is returned with the response + expect(body.attributes.results.updated[0].timeline_id).to.eql(timelineId); + expect(body.attributes.results.updated[0].timeline_title).to.eql(timelineTitle); + // Check that the updates have been persisted const { body: rule } = await fetchRule(ruleId).expect(200); expect(rule.timeline_id).to.eql(timelineId); From d3201da51baaa7c26fa2a759ee319ad8d3f7909d Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Wed, 16 Feb 2022 14:43:11 +0100 Subject: [PATCH 002/104] [Fleet] added loading spinner to add agent flyout (#125760) * added loading spinner to add agent flyout * fixed create agent policy scenario --- .../agent_enrollment_flyout.test.tsx | 19 +++++++++++++++++++ .../agent_enrollment_flyout/index.tsx | 14 ++++++++++++-- .../managed_instructions.tsx | 6 +++++- .../agent_enrollment_flyout/types.ts | 1 + .../fleet/public/components/loading.tsx | 2 +- .../use_agent_enrollment_flyout.data.test.ts | 1 + .../hooks/use_agent_enrollment_flyout_data.ts | 10 +++++++++- 7 files changed, 48 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx index b0c9fac454c28..51836d9ebab3e 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx @@ -118,6 +118,25 @@ describe('', () => { jest.clearAllMocks(); }); + it('should show loading when agent policies are loading', async () => { + (useAgentEnrollmentFlyoutData as jest.Mock).mockReturnValue?.({ + agentPolicies: [], + refreshAgentPolicies: jest.fn(), + isLoadingInitialAgentPolicies: true, + }); + + await act(async () => { + testBed = await setup({ + onClose: jest.fn(), + }); + testBed.component.update(); + }); + + const { exists } = testBed; + expect(exists('agentEnrollmentFlyout')).toBe(true); + expect(exists('loadingSpinner')).toBe(true); + }); + describe('managed instructions', () => { it('uses the agent policy selection step', async () => { const { exists } = testBed; diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx index 960230820e074..4be8eb8a03cd4 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx @@ -31,6 +31,8 @@ import { import { FLEET_SERVER_PACKAGE } from '../../constants'; import type { PackagePolicy } from '../../types'; +import { Loading } from '..'; + import { ManagedInstructions } from './managed_instructions'; import { StandaloneInstructions } from './standalone_instructions'; import { MissingFleetServerHostCallout } from './missing_fleet_server_host_callout'; @@ -64,7 +66,12 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ const [policyId, setSelectedPolicyId] = useState(agentPolicy?.id); const [isFleetServerPolicySelected, setIsFleetServerPolicySelected] = useState(false); - const { agentPolicies, refreshAgentPolicies } = useAgentEnrollmentFlyoutData(); + const { + agentPolicies, + isLoadingInitialAgentPolicies, + isLoadingAgentPolicies, + refreshAgentPolicies, + } = useAgentEnrollmentFlyoutData(); useEffect(() => { async function checkPolicyIsFleetServer() { @@ -141,7 +148,9 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ ) : undefined } > - {mode === 'managed' ? ( + {isLoadingInitialAgentPolicies ? ( + + ) : mode === 'managed' ? ( = ({ viewDataStep={viewDataStep} isFleetServerPolicySelected={isFleetServerPolicySelected} refreshAgentPolicies={refreshAgentPolicies} + isLoadingAgentPolicies={isLoadingAgentPolicies} /> ) : ( ( isFleetServerPolicySelected, settings, refreshAgentPolicies, + isLoadingAgentPolicies, }) => { const fleetStatus = useFleetStatus(); @@ -161,7 +162,10 @@ export const ManagedInstructions = React.memo( return null; } - if (fleetStatus.isReady && (isLoadingAgents || fleetServers.length > 0)) { + if ( + fleetStatus.isReady && + (isLoadingAgents || isLoadingAgentPolicies || fleetServers.length > 0) + ) { return ( <> diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts index d66c1006c4654..0c447ad0870ff 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts @@ -31,4 +31,5 @@ export interface BaseProps { export interface InstructionProps extends BaseProps { agentPolicies: AgentPolicy[]; refreshAgentPolicies: () => void; + isLoadingAgentPolicies?: boolean; } diff --git a/x-pack/plugins/fleet/public/components/loading.tsx b/x-pack/plugins/fleet/public/components/loading.tsx index 3e6f000694dbc..5cff54cc49e88 100644 --- a/x-pack/plugins/fleet/public/components/loading.tsx +++ b/x-pack/plugins/fleet/public/components/loading.tsx @@ -12,7 +12,7 @@ import type { EuiLoadingSpinnerSize } from '@elastic/eui/src/components/loading/ export const Loading: React.FunctionComponent<{ size?: EuiLoadingSpinnerSize }> = ({ size }) => ( - + ); diff --git a/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout.data.test.ts b/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout.data.test.ts index a7b4137b5be29..f3f3fa5d109c0 100644 --- a/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout.data.test.ts +++ b/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout.data.test.ts @@ -23,6 +23,7 @@ describe('useAgentEnrollmentFlyoutData', () => { (useGetAgentPolicies as jest.Mock).mockReturnValue({ data: undefined, isLoading: true }); const { result } = testRenderer.renderHook(() => useAgentEnrollmentFlyoutData()); expect(result.current.agentPolicies).toEqual([]); + expect(result.current.isLoadingAgentPolicies).toBe(true); }); it('should return empty agentPolicies when http not loading and no data', () => { diff --git a/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts b/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts index d93afd9ac1349..b672e39be7a86 100644 --- a/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts +++ b/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts @@ -14,11 +14,14 @@ import { useGetAgentPolicies } from './use_request'; interface AgentEnrollmentFlyoutData { agentPolicies: AgentPolicy[]; refreshAgentPolicies: () => void; + isLoadingInitialAgentPolicies: boolean; + isLoadingAgentPolicies: boolean; } export function useAgentEnrollmentFlyoutData(): AgentEnrollmentFlyoutData { const { data: agentPoliciesData, + isInitialRequest, isLoading: isLoadingAgentPolicies, resendRequest: refreshAgentPolicies, } = useGetAgentPolicies({ @@ -34,5 +37,10 @@ export function useAgentEnrollmentFlyoutData(): AgentEnrollmentFlyoutData { return []; }, [isLoadingAgentPolicies, agentPoliciesData?.items]); - return { agentPolicies, refreshAgentPolicies }; + return { + agentPolicies, + refreshAgentPolicies, + isLoadingInitialAgentPolicies: isInitialRequest && isLoadingAgentPolicies, + isLoadingAgentPolicies, + }; } From 6ca15e5b49427ce0b226e2156c487efbccc4be5c Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Wed, 16 Feb 2022 07:51:14 -0600 Subject: [PATCH 003/104] [kibana_react] Deprecate Exit Full Screen Button in favor of Shared UX component. (#125750) --- .../exit_full_screen_button/exit_full_screen_button.tsx | 1 + .../exit_full_screen_button/exit_full_screen_button.tsx | 6 ++++-- .../public/components/exit_full_screen_button/index.ts | 8 -------- src/plugins/shared_ux/public/components/index.ts | 6 +++++- src/plugins/shared_ux/public/services/index.tsx | 5 ++++- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx index 593f45d87446b..5c559a8f9e06a 100644 --- a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx +++ b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx @@ -101,4 +101,5 @@ class ExitFullScreenButtonUi extends PureComponent { } } +/** @deprecated Use `ExitFullScreenButton` from `src/plugins/shared_ux/public`. */ export const ExitFullScreenButton = ExitFullScreenButtonUi; diff --git a/src/plugins/shared_ux/public/components/exit_full_screen_button/exit_full_screen_button.tsx b/src/plugins/shared_ux/public/components/exit_full_screen_button/exit_full_screen_button.tsx index eb941593bdf1a..1f0b2f43a6b25 100644 --- a/src/plugins/shared_ux/public/components/exit_full_screen_button/exit_full_screen_button.tsx +++ b/src/plugins/shared_ux/public/components/exit_full_screen_button/exit_full_screen_button.tsx @@ -25,8 +25,10 @@ export interface Props { /** * A service-enabled component that provides Kibana-specific functionality to the `ExitFullScreenButton` - * component. Use of this component requires both the `EuiTheme` context as well as the Shared UX - * `ServicesProvider`. + * component. + * + * Use of this component requires both the `EuiTheme` context as well as either a configured Shared UX + * `ServicesProvider` or the `ServicesContext` provided by the Shared UX public plugin contract. * * See shared-ux/public/services for information. */ diff --git a/src/plugins/shared_ux/public/components/exit_full_screen_button/index.ts b/src/plugins/shared_ux/public/components/exit_full_screen_button/index.ts index 0baf60d8499ca..66ffe2976d786 100644 --- a/src/plugins/shared_ux/public/components/exit_full_screen_button/index.ts +++ b/src/plugins/shared_ux/public/components/exit_full_screen_button/index.ts @@ -5,13 +5,5 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -/* eslint-disable import/no-default-export */ -import { ExitFullScreenButton } from './exit_full_screen_button'; export { ExitFullScreenButton } from './exit_full_screen_button'; - -/** - * Exporting the ExitFullScreenButton component as a default export so it can be - * loaded by React.lazy. - */ -export default ExitFullScreenButton; diff --git a/src/plugins/shared_ux/public/components/index.ts b/src/plugins/shared_ux/public/components/index.ts index f3c25ca023e8d..3c5e4424f99f5 100644 --- a/src/plugins/shared_ux/public/components/index.ts +++ b/src/plugins/shared_ux/public/components/index.ts @@ -13,7 +13,11 @@ import { withSuspense } from './utility'; * The Lazily-loaded `ExitFullScreenButton` component. Consumers should use `React.Suspennse` or the * `withSuspense` HOC to load this component. */ -export const LazyExitFullScreenButton = React.lazy(() => import('./exit_full_screen_button')); +export const LazyExitFullScreenButton = React.lazy(() => + import('./exit_full_screen_button').then(({ ExitFullScreenButton }) => ({ + default: ExitFullScreenButton, + })) +); /** * A `ExitFullScreenButton` component that is wrapped by the `withSuspense` HOC. This component can diff --git a/src/plugins/shared_ux/public/services/index.tsx b/src/plugins/shared_ux/public/services/index.tsx index acc8b9294d1df..0677f3ef0ca84 100644 --- a/src/plugins/shared_ux/public/services/index.tsx +++ b/src/plugins/shared_ux/public/services/index.tsx @@ -27,8 +27,11 @@ const ServicesContext = createContext(servicesFactory()); /** * The `React.Context` Provider component for the `SharedUXServices` context. Any - * plugin or environemnt that consumes SharedUX components needs to wrap their React + * plugin or environment that consumes SharedUX components needs to wrap their React * tree with this provider. + * + * Within a plugin, you can use the `ServicesContext` provided by the SharedUX plugin start + * lifeycle method. */ export const ServicesProvider: FC = ({ children, ...services }) => ( {children} From 86f212f6fefccafdca6dc4e2b39b1183bc35dda5 Mon Sep 17 00:00:00 2001 From: Georgii Gorbachev Date: Wed, 16 Feb 2022 17:04:01 +0300 Subject: [PATCH 004/104] [Security Solution][Detections] Remove the bulk editing feature switch (#125772) **Addresses:** https://github.com/elastic/kibana/issues/125502 ## Summary Removed the `rulesBulkEditEnabled` experimental flag from the config and its usage from the client-side code. --- .../common/experimental_features.ts | 1 - .../all/bulk_actions/use_bulk_actions.tsx | 47 ++++++++----------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 25bc0c48e4ac0..0ae0dda273958 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -22,7 +22,6 @@ export const allowedExperimentalValues = Object.freeze({ riskyHostsEnabled: false, securityRulesCancelEnabled: false, pendingActionResponsesWithAck: true, - rulesBulkEditEnabled: true, policyListEnabled: false, /** diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx index 556213d985db9..7058b95bf5fc9 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx @@ -42,7 +42,6 @@ import { useHasActionsPrivileges } from '../use_has_actions_privileges'; import { useHasMlPermissions } from '../use_has_ml_permissions'; import { getCustomRulesCountFromCache } from './use_custom_rules_count'; import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts'; -import { useIsExperimentalFeatureEnabled } from '../../../../../../common/hooks/use_experimental_features'; import { convertRulesFilterToKQL } from '../../../../../containers/detection_engine/rules/utils'; import type { @@ -76,7 +75,6 @@ export const useBulkActions = ({ const [, dispatchToaster] = useStateToaster(); const hasActionsPrivileges = useHasActionsPrivileges(); const toasts = useAppToasts(); - const isRulesBulkEditEnabled = useIsExperimentalFeatureEnabled('rulesBulkEditEnabled'); const getIsMounted = useIsMounted(); const filterQuery = convertRulesFilterToKQL(filterOptions); @@ -342,7 +340,7 @@ export const useBulkActions = ({ return [ { id: 0, - title: isRulesBulkEditEnabled ? i18n.BULK_ACTION_MENU_TITLE : undefined, + title: i18n.BULK_ACTION_MENU_TITLE, items: [ { key: i18n.BULK_ACTION_ENABLE, @@ -353,7 +351,7 @@ export const useBulkActions = ({ onClick: handleActivateAction, toolTipContent: missingActionPrivileges ? i18n.EDIT_RULE_SETTINGS_TOOLTIP : undefined, toolTipPosition: 'right', - icon: isRulesBulkEditEnabled ? undefined : 'checkInCircleFilled', + icon: undefined, }, { key: i18n.BULK_ACTION_DUPLICATE, @@ -363,26 +361,22 @@ export const useBulkActions = ({ onClick: handleDuplicateAction, toolTipContent: missingActionPrivileges ? i18n.EDIT_RULE_SETTINGS_TOOLTIP : undefined, toolTipPosition: 'right', - icon: isRulesBulkEditEnabled ? undefined : 'crossInACircleFilled', + icon: undefined, + }, + { + key: i18n.BULK_ACTION_INDEX_PATTERNS, + name: i18n.BULK_ACTION_INDEX_PATTERNS, + 'data-test-subj': 'indexPatternsBulkEditRule', + disabled: isEditDisabled, + panel: 2, + }, + { + key: i18n.BULK_ACTION_TAGS, + name: i18n.BULK_ACTION_TAGS, + 'data-test-subj': 'tagsBulkEditRule', + disabled: isEditDisabled, + panel: 1, }, - ...(isRulesBulkEditEnabled - ? [ - { - key: i18n.BULK_ACTION_INDEX_PATTERNS, - name: i18n.BULK_ACTION_INDEX_PATTERNS, - 'data-test-subj': 'indexPatternsBulkEditRule', - disabled: isEditDisabled, - panel: 2, - }, - { - key: i18n.BULK_ACTION_TAGS, - name: i18n.BULK_ACTION_TAGS, - 'data-test-subj': 'tagsBulkEditRule', - disabled: isEditDisabled, - panel: 1, - }, - ] - : []), { key: i18n.BULK_ACTION_EXPORT, name: i18n.BULK_ACTION_EXPORT, @@ -392,7 +386,7 @@ export const useBulkActions = ({ containsLoading || selectedRuleIds.length === 0, onClick: handleExportAction, - icon: isRulesBulkEditEnabled ? undefined : 'exportAction', + icon: undefined, }, { key: i18n.BULK_ACTION_DISABLE, @@ -403,7 +397,7 @@ export const useBulkActions = ({ onClick: handleDeactivateActions, toolTipContent: missingActionPrivileges ? i18n.EDIT_RULE_SETTINGS_TOOLTIP : undefined, toolTipPosition: 'right', - icon: isRulesBulkEditEnabled ? undefined : 'copy', + icon: undefined, }, { key: i18n.BULK_ACTION_DELETE, @@ -421,7 +415,7 @@ export const useBulkActions = ({ ? i18n.BATCH_ACTION_DELETE_SELECTED_IMMUTABLE : undefined, toolTipPosition: 'right', - icon: isRulesBulkEditEnabled ? undefined : 'trash', + icon: undefined, }, ], }, @@ -479,7 +473,6 @@ export const useBulkActions = ({ rules, selectedRuleIds, hasActionsPrivileges, - isRulesBulkEditEnabled, isAllSelected, loadingRuleIds, hasMlPermissions, From 335d9f376a8af2b6518628f73777fcf02141587c Mon Sep 17 00:00:00 2001 From: Josh Dover <1813008+joshdover@users.noreply.github.com> Date: Wed, 16 Feb 2022 15:19:51 +0100 Subject: [PATCH 005/104] Update token used for Fleet QA labeling action (#125774) --- .github/workflows/label-qa-fixed-in.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/label-qa-fixed-in.yml b/.github/workflows/label-qa-fixed-in.yml index e1dafa061f623..7ef6b0666e6c6 100644 --- a/.github/workflows/label-qa-fixed-in.yml +++ b/.github/workflows/label-qa-fixed-in.yml @@ -37,7 +37,7 @@ jobs: } } prnumber: ${{ github.event.number }} - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.FLEET_TECH_KIBANA_USER_TOKEN }} - uses: sergeysova/jq-action@v2 id: issues_to_label with: @@ -75,4 +75,4 @@ jobs: } issueid: ${{ matrix.issueNodeId }} labelids: ${{ needs.fetch_issues_to_label.outputs.label_ids }} - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.FLEET_TECH_KIBANA_USER_TOKEN }} From 995c1776291485d1d7079dab914a0e41576b9181 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Wed, 16 Feb 2022 15:39:49 +0100 Subject: [PATCH 006/104] [Workplace Search] Add indexing rules table (#124353) [Workplace Search] Add indexing rules table --- .../inline_editable_table.tsx | 4 + .../inline_editable_table_logic.ts | 8 +- .../__mocks__/content_sources.mock.ts | 18 +- .../workplace_search/constants.ts | 6 +- .../applications/workplace_search/routes.ts | 3 +- .../applications/workplace_search/types.ts | 13 + .../components/source_sub_nav.test.tsx | 6 +- ...s.test.tsx => assets_and_objects.test.tsx} | 18 +- ..._and_assets.tsx => assets_and_objects.tsx} | 65 +-- .../indexing_rules_table.test.tsx | 250 +++++++++++ .../synchronization/indexing_rules_table.tsx | 235 ++++++++++ .../synchronization_logic.test.ts | 406 ++++++++++++++++-- .../synchronization/synchronization_logic.ts | 179 +++++++- .../synchronization_router.test.tsx | 7 +- .../synchronization_router.tsx | 15 +- .../synchronization_sub_nav.test.tsx | 6 +- .../synchronization_sub_nav.tsx | 8 +- .../views/content_sources/constants.ts | 22 +- .../routes/workplace_search/sources.test.ts | 80 ++++ .../server/routes/workplace_search/sources.ts | 63 +++ .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - 22 files changed, 1312 insertions(+), 106 deletions(-) rename x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/{objects_and_assets.test.tsx => assets_and_objects.test.tsx} (83%) rename x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/{objects_and_assets.tsx => assets_and_objects.tsx} (71%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx index 3ccd5f15e29e9..73380c0270821 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx @@ -27,6 +27,7 @@ import './inline_editable_tables.scss'; export interface InlineEditableTableProps { columns: Array>; items: Item[]; + defaultItem?: Partial; title: string; addButtonText?: string; canRemoveLastItem?: boolean; @@ -53,6 +54,7 @@ export const InlineEditableTable = ( const { instanceId, columns, + defaultItem, onAdd, onDelete, onReorder, @@ -67,6 +69,7 @@ export const InlineEditableTable = ( props={{ instanceId, columns, + defaultItem, onAdd, onDelete, onReorder, @@ -90,6 +93,7 @@ export const InlineEditableTableContents = ({ description, isLoading, lastItemWarning, + defaultItem, noItemsMessage = () => null, uneditableItems, ...rest diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts index d62d894d18ef5..a4a25d0ed5a66 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts @@ -48,6 +48,7 @@ interface InlineEditableTableValues { export interface InlineEditableTableProps { columns: Array>; instanceId: string; + defaultItem: Item; // TODO Because these callbacks are params, they are only set on the logic once (i.e., they are cached) // which makes using "useState" to back this really hard. onAdd(item: Item, onSuccess: () => void): void; @@ -79,12 +80,15 @@ export const InlineEditableTableLogic = kea ({ fieldErrors }), setRowErrors: (rowErrors) => ({ rowErrors }), }), - reducers: ({ props: { columns } }) => ({ + reducers: ({ props: { columns, defaultItem } }) => ({ editingItemValue: [ null, { doneEditing: () => null, - editNewItem: () => generateEmptyItem(columns), + editNewItem: () => + defaultItem + ? { ...generateEmptyItem(columns), ...defaultItem } + : generateEmptyItem(columns), editExistingItem: (_, { item }) => item, setEditingItemValue: (_, { item }) => item, }, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index 7af40b23d9f64..b5309d8fedc1b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -7,6 +7,7 @@ import { groups } from './groups.mock'; +import { IndexingRule } from '../types'; import { staticSourceData } from '../views/content_sources/source_data'; import { mergeServerAndStaticData } from '../views/content_sources/sources_logic'; @@ -45,10 +46,25 @@ export const contentSources = [ }, ]; +const defaultIndexingRules: IndexingRule[] = [ + { + filterType: 'object_type', + include: 'value', + }, + { + filterType: 'path_template', + exclude: 'value', + }, + { + filterType: 'file_extension', + include: 'value', + }, +]; + const defaultIndexing = { enabled: true, defaultAction: 'include', - rules: [], + rules: defaultIndexingRules, schedule: { full: 'P1D', incremental: 'PT2H', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts index 9d3b2cb8aaefd..4510498465793 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts @@ -60,10 +60,10 @@ export const NAV = { defaultMessage: 'Frequency', } ), - SYNCHRONIZATION_OBJECTS_AND_ASSETS: i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.nav.synchronizationObjectsAndAssets', + SYNCHRONIZATION_ASSETS_AND_OBJECTS: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.nav.synchronizationAssetsAndObjects', { - defaultMessage: 'Objects and assets', + defaultMessage: 'Assets and objects', } ), DISPLAY_SETTINGS: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.displaySettings', { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts index ee180ae52e0b7..4857fa2a158a0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts @@ -76,7 +76,8 @@ export const DISPLAY_SETTINGS_RESULT_DETAIL_PATH = `${SOURCE_DISPLAY_SETTINGS_PA export const SYNC_FREQUENCY_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/frequency`; export const BLOCKED_TIME_WINDOWS_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/frequency/blocked_windows`; -export const OBJECTS_AND_ASSETS_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/objects_and_assets`; +export const OLD_OBJECTS_AND_ASSETS_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/objects_and_assets`; +export const ASSETS_AND_OBJECTS_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/assets_and_objects`; export const ORG_SETTINGS_PATH = '/settings'; export const ORG_SETTINGS_CUSTOMIZE_PATH = `${ORG_SETTINGS_PATH}/customize`; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts index 2e933d7bdf94a..b01700b8bce34 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts @@ -168,6 +168,18 @@ export interface BlockedWindow { end: string; } +export interface IndexingRuleExclude { + filterType: 'object_type' | 'path_template' | 'file_extension'; + exclude: string; +} + +export interface IndexingRuleInclude { + filterType: 'object_type' | 'path_template' | 'file_extension'; + include: string; +} + +export type IndexingRule = IndexingRuleInclude | IndexingRuleExclude; + export interface IndexingConfig { enabled: boolean; features: { @@ -178,6 +190,7 @@ export interface IndexingConfig { enabled: boolean; }; }; + rules: IndexingRule[]; schedule: IndexingSchedule; } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx index d5ba030e582b8..66c7f5df0b5b2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx @@ -119,9 +119,9 @@ describe('useSourceSubNav', () => { href: '/sources/2/synchronization/frequency', }, { - id: 'sourceSynchronizationObjectsAndAssets', - name: 'Objects and assets', - href: '/sources/2/synchronization/objects_and_assets', + id: 'sourceSynchronizationAssetsAndObjects', + name: 'Assets and objects', + href: '/sources/2/synchronization/assets_and_objects', }, ], }, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/assets_and_objects.test.tsx similarity index 83% rename from x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/assets_and_objects.test.tsx index 13dc2872037c1..aee83b31be045 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/assets_and_objects.test.tsx @@ -16,19 +16,19 @@ import { shallow } from 'enzyme'; import { EuiSwitch } from '@elastic/eui'; -import { ObjectsAndAssets } from './objects_and_assets'; +import { AssetsAndObjects } from './assets_and_objects'; -describe('ObjectsAndAssets', () => { +describe('AssetsAndObjects', () => { const setThumbnailsChecked = jest.fn(); const setContentExtractionChecked = jest.fn(); - const updateObjectsAndAssetsSettings = jest.fn(); + const updateAssetsAndObjectsSettings = jest.fn(); const resetSyncSettings = jest.fn(); const contentSource = fullContentSources[0]; const mockActions = { setThumbnailsChecked, setContentExtractionChecked, - updateObjectsAndAssetsSettings, + updateAssetsAndObjectsSettings, resetSyncSettings, }; const mockValues = { @@ -37,7 +37,7 @@ describe('ObjectsAndAssets', () => { contentSource, thumbnailsChecked: true, contentExtractionChecked: true, - hasUnsavedObjectsAndAssetsChanges: false, + hasUnsavedAssetsAndObjectsChanges: false, }; beforeEach(() => { @@ -46,13 +46,13 @@ describe('ObjectsAndAssets', () => { }); it('renders', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(EuiSwitch)).toHaveLength(2); }); it('handles thumbnails switch change', () => { - const wrapper = shallow(); + const wrapper = shallow(); wrapper .find('[data-test-subj="ThumbnailsToggle"]') .simulate('change', { target: { checked: false } }); @@ -61,7 +61,7 @@ describe('ObjectsAndAssets', () => { }); it('handles content extraction switch change', () => { - const wrapper = shallow(); + const wrapper = shallow(); wrapper .find('[data-test-subj="ContentExtractionToggle"]') .simulate('change', { target: { checked: false } }); @@ -77,7 +77,7 @@ describe('ObjectsAndAssets', () => { areThumbnailsConfigEnabled: false, }, }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find('[data-test-subj="ThumbnailsToggle"]').prop('label')).toEqual( 'Sync thumbnails - disabled at global configuration level' diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/assets_and_objects.tsx similarity index 71% rename from x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx rename to x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/assets_and_objects.tsx index 460f7e7f42055..1d92398f53539 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/assets_and_objects.tsx @@ -18,7 +18,7 @@ import { EuiLink, EuiSpacer, EuiSwitch, - EuiText, + EuiTitle, } from '@elastic/eui'; import { SAVE_BUTTON_LABEL } from '../../../../../shared/constants'; @@ -27,27 +27,29 @@ import { UnsavedChangesPrompt } from '../../../../../shared/unsaved_changes_prom import { ViewContentHeader } from '../../../../components/shared/view_content_header'; import { NAV, RESET_BUTTON } from '../../../../constants'; import { - LEARN_MORE_LINK, SYNC_MANAGEMENT_CONTENT_EXTRACTION_LABEL, SYNC_MANAGEMENT_THUMBNAILS_LABEL, SYNC_MANAGEMENT_THUMBNAILS_GLOBAL_CONFIG_LABEL, - SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION, - SOURCE_OBJECTS_AND_ASSETS_LABEL, + SOURCE_ASSETS_AND_OBJECTS_DESCRIPTION, + SOURCE_ASSETS_AND_OBJECTS_ASSETS_LABEL, SYNC_UNSAVED_CHANGES_MESSAGE, + SOURCE_ASSETS_AND_OBJECTS_LEARN_MORE_LINK, + SOURCE_ASSETS_AND_OBJECTS_OBJECTS_LABEL, } from '../../constants'; import { SourceLogic } from '../../source_logic'; import { SourceLayout } from '../source_layout'; +import { IndexingRulesTable } from './indexing_rules_table'; import { SynchronizationLogic } from './synchronization_logic'; -export const ObjectsAndAssets: React.FC = () => { +export const AssetsAndObjects: React.FC = () => { const { contentSource, dataLoading } = useValues(SourceLogic); - const { thumbnailsChecked, contentExtractionChecked, hasUnsavedObjectsAndAssetsChanges } = + const { thumbnailsChecked, contentExtractionChecked, hasUnsavedAssetsAndObjectsChanges } = useValues(SynchronizationLogic({ contentSource })); const { setThumbnailsChecked, setContentExtractionChecked, - updateObjectsAndAssetsSettings, + updateAssetsAndObjectsSettings, resetSyncSettings, } = useActions(SynchronizationLogic({ contentSource })); @@ -55,47 +57,43 @@ export const ObjectsAndAssets: React.FC = () => { const actions = ( - - - {RESET_BUTTON} - - {SAVE_BUTTON_LABEL} + + + {RESET_BUTTON} + + ); return ( - - {SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION}{' '} - - {LEARN_MORE_LINK} - - - } - action={actions} - /> + + {SOURCE_ASSETS_AND_OBJECTS_DESCRIPTION} + + + {SOURCE_ASSETS_AND_OBJECTS_LEARN_MORE_LINK} + - {SOURCE_OBJECTS_AND_ASSETS_LABEL} + +

{SOURCE_ASSETS_AND_OBJECTS_ASSETS_LABEL}

+
@@ -122,6 +120,15 @@ export const ObjectsAndAssets: React.FC = () => { /> + + +

{SOURCE_ASSETS_AND_OBJECTS_OBJECTS_LABEL}

+
+ + + + +
); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.test.tsx new file mode 100644 index 0000000000000..7d4b47e7cd8e6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.test.tsx @@ -0,0 +1,250 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + LogicMounter, + mockFlashMessageHelpers, + setMockActions, + setMockValues, +} from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; + +import React from 'react'; + +import { shallow, ShallowWrapper } from 'enzyme'; + +import { EuiFieldText, EuiSelect } from '@elastic/eui'; + +import { InlineEditableTable } from '../../../../../shared/tables/inline_editable_table'; + +import { SourceLogic } from '../../source_logic'; + +import { IndexingRulesTable } from './indexing_rules_table'; +import { SynchronizationLogic } from './synchronization_logic'; + +describe('IndexingRulesTable', () => { + const { clearFlashMessages } = mockFlashMessageHelpers; + const { mount: sourceMount } = new LogicMounter(SourceLogic); + const { mount: syncMount } = new LogicMounter(SynchronizationLogic); + + const indexingRules = [ + { id: 0, valueType: 'exclude', filterType: 'path_template', value: 'value' }, + { id: 1, valueType: 'include', filterType: 'file_extension', value: 'value' }, + { id: 2, valueType: 'include', filterType: 'object_type', value: 'value 2' }, + { id: 3, valueType: 'broken', filterType: 'not allowed', value: 'value 2' }, + ]; + const contentSource = fullContentSources[0]; + + beforeEach(() => { + jest.clearAllMocks(); + sourceMount({}, {}); + setMockValues({ contentSource }); + syncMount({}, { contentSource }); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(InlineEditableTable).exists()).toBe(true); + }); + + describe('columns', () => { + let wrapper: ShallowWrapper; + + beforeEach(() => { + wrapper = shallow(); + }); + + const renderColumn = (index: number, ruleIndex: number) => { + const columns = wrapper.find(InlineEditableTable).prop('columns'); + return shallow(
{columns[index].render(indexingRules[ruleIndex])}
); + }; + + const onChange = jest.fn(); + const renderColumnInEditingMode = (index: number, ruleIndex: number) => { + const columns = wrapper.find(InlineEditableTable).prop('columns'); + return shallow( +
+ {columns[index].editingRender(indexingRules[ruleIndex], onChange, { + isInvalid: false, + isLoading: false, + })} +
+ ); + }; + + describe(' column', () => { + it('shows the value type of an indexing rule', () => { + expect(renderColumn(0, 0).html()).toContain('Exclude'); + expect(renderColumn(0, 1).html()).toContain('Include'); + expect(renderColumn(0, 3).html()).toContain(''); + }); + + it('can show the value type of an indexing rule as editable', () => { + const column = renderColumnInEditingMode(0, 0); + + const selectField = column.find(EuiSelect); + expect(selectField.props()).toEqual( + expect.objectContaining({ + value: 'exclude', + disabled: false, + isInvalid: false, + options: [ + { text: 'Include', value: 'include' }, + { text: 'Exclude', value: 'exclude' }, + ], + }) + ); + + selectField.simulate('change', { target: { value: 'include' } }); + expect(onChange).toHaveBeenCalledWith('include'); + }); + }); + + describe('filter type column', () => { + it('shows the filter type of an indexing rule', () => { + expect(renderColumn(1, 0).html()).toContain('Path'); + expect(renderColumn(1, 1).html()).toContain('File'); + expect(renderColumn(1, 2).html()).toContain('Item'); + expect(renderColumn(1, 3).html()).toContain(''); + }); + + it('can show the filter type of an indexing rule as editable', () => { + const column = renderColumnInEditingMode(1, 0); + + const selectField = column.find(EuiSelect); + expect(selectField.props()).toEqual( + expect.objectContaining({ + value: 'path_template', + disabled: false, + isInvalid: false, + options: [ + { text: 'Item', value: 'object_type' }, + { text: 'Path', value: 'path_template' }, + { text: 'File type', value: 'file_extension' }, + ], + }) + ); + + selectField.simulate('change', { target: { value: 'object_type' } }); + expect(onChange).toHaveBeenCalledWith('object_type'); + }); + }); + + describe('pattern column', () => { + it('shows the value of an indexing rule', () => { + expect(renderColumn(2, 0).html()).toContain('value'); + }); + + it('can show the value of a indexing rule as editable', () => { + const column = renderColumnInEditingMode(2, 0); + + const field = column.find(EuiFieldText); + expect(field.props()).toEqual( + expect.objectContaining({ + value: 'value', + disabled: false, + isInvalid: false, + }) + ); + + field.simulate('change', { target: { value: 'foo' } }); + expect(onChange).toHaveBeenCalledWith('foo'); + }); + }); + }); + + describe('when an indexing rule is added', () => { + it('should update the indexing rules for the current domain, and clear flash messages', () => { + const initAddIndexingRule = jest.fn(); + const done = jest.fn(); + setMockActions({ + initAddIndexingRule, + }); + const wrapper = shallow(); + const table = wrapper.find(InlineEditableTable); + + const newIndexingRule = { + id: 2, + value: 'new value', + filterType: 'path_template', + valueType: 'include', + }; + table.prop('onAdd')(newIndexingRule, done); + expect(initAddIndexingRule).toHaveBeenCalledWith(newIndexingRule); + expect(clearFlashMessages).toHaveBeenCalled(); + }); + }); + + describe('when an indexing rule is updated', () => { + it('should update the indexing rules for the current domain, and clear flash messages', () => { + const initSetIndexingRule = jest.fn(); + const done = jest.fn(); + setMockActions({ + initSetIndexingRule, + }); + const wrapper = shallow(); + const table = wrapper.find(InlineEditableTable); + + const newIndexingRule = { + id: 2, + value: 'new value', + filterType: 'path_template', + valueType: 'include', + }; + table.prop('onUpdate')(newIndexingRule, done); + expect(initSetIndexingRule).toHaveBeenCalledWith(newIndexingRule); + expect(clearFlashMessages).toHaveBeenCalled(); + }); + }); + + describe('when a indexing rule is deleted', () => { + it('should update the indexing rules for the current domain, and clear flash messages', () => { + const deleteIndexingRule = jest.fn(); + const done = jest.fn(); + setMockActions({ + deleteIndexingRule, + }); + const wrapper = shallow(); + const table = wrapper.find(InlineEditableTable); + + const newIndexingRule = { + id: 2, + value: 'new value', + filterType: 'path_template', + valueType: 'include', + }; + table.prop('onDelete')(newIndexingRule, done); + expect(deleteIndexingRule).toHaveBeenCalledWith(newIndexingRule); + expect(clearFlashMessages).toHaveBeenCalled(); + }); + }); + + describe('when an indexing rule is reordered', () => { + it('should update the indexing rules for the current domain, and clear flash messages', () => { + const setIndexingRules = jest.fn(); + const done = jest.fn(); + setMockActions({ + setIndexingRules, + }); + const wrapper = shallow(); + const table = wrapper.find(InlineEditableTable); + + const newIndexingRules = [ + { + id: 2, + value: 'new value', + filterType: 'path_template', + valueType: 'include', + }, + ]; + table.prop('onReorder')!(newIndexingRules, indexingRules, done); + expect(setIndexingRules).toHaveBeenCalledWith(newIndexingRules); + expect(clearFlashMessages).toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.tsx new file mode 100644 index 0000000000000..ed1eb40c61ce5 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/indexing_rules_table.tsx @@ -0,0 +1,235 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useActions, useValues } from 'kea'; + +import { + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiSelect, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { docLinks } from '../../../../../shared/doc_links'; +import { clearFlashMessages } from '../../../../../shared/flash_messages'; +import { InlineEditableTable } from '../../../../../shared/tables/inline_editable_table/inline_editable_table'; +import { InlineEditableTableColumn } from '../../../../../shared/tables/inline_editable_table/types'; + +import { SourceLogic } from '../../source_logic'; + +import { EditableIndexingRule, SynchronizationLogic } from './synchronization_logic'; + +const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_POLICY_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTablePolicyLabel', + { + defaultMessage: 'Policy', + } +); + +const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_PATH_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTablePathLabel', + { + defaultMessage: 'Path', + } +); + +export const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_ITEM_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTableItemLabel', + { + defaultMessage: 'Item', + } +); + +export const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_FILE_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTableFileLabel', + { + defaultMessage: 'File type', + } +); + +export const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_INCLUDE_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTableIncludeLabel', + { + defaultMessage: 'Include', + } +); + +export const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_EXCLUDE_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTableExcludeLabel', + { + defaultMessage: 'Exclude', + } +); + +export const IndexingRulesTable: React.FC = () => { + const { contentSource } = useValues(SourceLogic); + const indexingRulesInstanceId = 'IndexingRulesTable'; + const { indexingRules } = useValues( + SynchronizationLogic({ contentSource, indexingRulesInstanceId }) + ); + const { initAddIndexingRule, deleteIndexingRule, initSetIndexingRule, setIndexingRules } = + useActions(SynchronizationLogic({ contentSource })); + + const description = ( + + {i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsDescription', + { + defaultMessage: + 'Include or exclude high level items, file types and (file or folder) paths to synchronize from {contentSourceName}. Everything is included by default. Each document is tested against the rules below and the first rule that matches will be applied.', + values: { contentSourceName: contentSource.name }, + } + )} + + + {i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsSyncLearnMoreLink', + { + defaultMessage: 'Learn more about sync rules.', + } + )} + + + ); + + const valueTypeToString = (input: string): string => { + switch (input) { + case 'include': + return SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_INCLUDE_LABEL; + case 'exclude': + return SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_EXCLUDE_LABEL; + default: + return ''; + } + }; + + const filterTypeToString = (input: string): string => { + switch (input) { + case 'object_type': + return SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_ITEM_LABEL; + case 'path_template': + return SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_PATH_LABEL; + case 'file_extension': + return SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_FILE_LABEL; + default: + return ''; + } + }; + + const columns: Array> = [ + { + editingRender: (indexingRule, onChange, { isInvalid, isLoading }) => ( + onChange(e.target.value)} + disabled={isLoading} + isInvalid={isInvalid} + options={[ + { text: SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_INCLUDE_LABEL, value: 'include' }, + { text: SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_EXCLUDE_LABEL, value: 'exclude' }, + ]} + /> + ), + render: (indexingRule) => ( + {valueTypeToString(indexingRule.valueType)} + ), + name: SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_POLICY_LABEL, + field: 'valueType', + }, + { + editingRender: (indexingRule, onChange, { isInvalid, isLoading }) => ( + onChange(e.target.value)} + disabled={isLoading} + isInvalid={isInvalid} + options={[ + { text: SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_ITEM_LABEL, value: 'object_type' }, + { text: SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_PATH_LABEL, value: 'path_template' }, + { text: SOURCE_ASSETS_AND_OBJECTS_OBJECTS_TABLE_FILE_LABEL, value: 'file_extension' }, + ]} + /> + ), + render: (indexingRule) => ( + {filterTypeToString(indexingRule.filterType)} + ), + name: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTableRuleLabel', + { + defaultMessage: 'Rule', + } + ), + field: 'filterType', + }, + { + editingRender: (indexingRule, onChange, { isInvalid, isLoading }) => ( + + + onChange(e.target.value)} + disabled={isLoading} + isInvalid={isInvalid} + /> + + + ), + render: (indexingRule) => {indexingRule.value}, + name: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsTableValueLabel', + { + defaultMessage: 'Value', + } + ), + field: 'value', + }, + ]; + + return ( + { + initAddIndexingRule(newRule); + clearFlashMessages(); + }} + onDelete={(rule) => { + deleteIndexingRule(rule); + clearFlashMessages(); + }} + onUpdate={(rule) => { + initSetIndexingRule(rule); + clearFlashMessages(); + }} + onReorder={(newIndexingRules) => { + setIndexingRules(newIndexingRules); + clearFlashMessages(); + }} + title="" + canRemoveLastItem + /> + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts index 20a6ba238a2f4..63de2e4d55838 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts @@ -15,6 +15,11 @@ import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; import { nextTick } from '@kbn/test-jest-helpers'; +import { + InlineEditableTableLogic, + InlineEditableTableProps, +} from '../../../../../shared/tables/inline_editable_table/inline_editable_table_logic'; +import { ItemWithAnID } from '../../../../../shared/tables/types'; import { itShowsServerErrorAsFlashMessage } from '../../../../../test_helpers'; jest.mock('../../source_logic', () => ({ @@ -30,11 +35,12 @@ import { SynchronizationLogic, emptyBlockedWindow, stripScheduleSeconds, + EditableIndexingRule, } from './synchronization_logic'; describe('SynchronizationLogic', () => { const { http } = mockHttpValues; - const { flashSuccessToast } = mockFlashMessageHelpers; + const { flashSuccessToast, flashAPIErrors } = mockFlashMessageHelpers; const { navigateToUrl } = mockKibanaValues; const { mount } = new LogicMounter(SynchronizationLogic); const contentSource = fullContentSources[0]; @@ -49,12 +55,49 @@ describe('SynchronizationLogic', () => { }, }; + const defaultIndexingRules: EditableIndexingRule[] = [ + { + filterType: 'object_type', + id: 0, + value: 'value', + valueType: 'include', + }, + { + filterType: 'path_template', + id: 1, + value: 'value', + valueType: 'exclude', + }, + { + filterType: 'file_extension', + id: 2, + value: 'value', + valueType: 'include', + }, + ]; + const defaultValues = { navigatingBetweenTabs: false, - hasUnsavedObjectsAndAssetsChanges: false, + hasUnsavedAssetsAndObjectsChanges: false, + hasUnsavedIndexingRulesChanges: false, hasUnsavedFrequencyChanges: false, contentExtractionChecked: true, thumbnailsChecked: true, + indexingRules: defaultIndexingRules, + indexingRulesForAPI: [ + { + filter_type: 'object_type', + include: 'value', + }, + { + filter_type: 'path_template', + exclude: 'value', + }, + { + filter_type: 'file_extension', + include: 'value', + }, + ], schedule: contentSource.indexing.schedule, cachedSchedule: contentSource.indexing.schedule, }; @@ -109,10 +152,17 @@ describe('SynchronizationLogic', () => { it('resetSyncSettings', () => { SynchronizationLogic.actions.setContentExtractionChecked(false); SynchronizationLogic.actions.setThumbnailsChecked(false); + SynchronizationLogic.actions.addIndexingRule({ + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + }); SynchronizationLogic.actions.resetSyncSettings(); expect(SynchronizationLogic.values.thumbnailsChecked).toEqual(true); expect(SynchronizationLogic.values.contentExtractionChecked).toEqual(true); + expect(SynchronizationLogic.values.indexingRules).toEqual(defaultIndexingRules); + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(false); }); describe('setSyncFrequency', () => { @@ -151,37 +201,133 @@ describe('SynchronizationLogic', () => { expect(SynchronizationLogic.values.schedule.blockedWindows).toBeUndefined(); }); }); - }); - describe('setBlockedTimeWindow', () => { - it('sets "jobType"', () => { - SynchronizationLogic.actions.addBlockedWindow(); - SynchronizationLogic.actions.setBlockedTimeWindow(0, 'jobType', 'incremental'); + describe('setBlockedTimeWindow', () => { + it('sets "jobType"', () => { + SynchronizationLogic.actions.addBlockedWindow(); + SynchronizationLogic.actions.setBlockedTimeWindow(0, 'jobType', 'incremental'); + + expect(SynchronizationLogic.values.schedule.blockedWindows![0].jobType).toEqual( + 'incremental' + ); + }); + + it('sets "day"', () => { + SynchronizationLogic.actions.addBlockedWindow(); + SynchronizationLogic.actions.setBlockedTimeWindow(0, 'day', 'tuesday'); + + expect(SynchronizationLogic.values.schedule.blockedWindows![0].day).toEqual('tuesday'); + }); + + it('sets "start"', () => { + SynchronizationLogic.actions.addBlockedWindow(); + SynchronizationLogic.actions.setBlockedTimeWindow(0, 'start', '9:00:00Z'); - expect(SynchronizationLogic.values.schedule.blockedWindows![0].jobType).toEqual( - 'incremental' - ); + expect(SynchronizationLogic.values.schedule.blockedWindows![0].start).toEqual('9:00:00Z'); + }); + + it('sets "end"', () => { + SynchronizationLogic.actions.addBlockedWindow(); + SynchronizationLogic.actions.setBlockedTimeWindow(0, 'end', '11:00:00Z'); + + expect(SynchronizationLogic.values.schedule.blockedWindows![0].end).toEqual('11:00:00Z'); + }); }); - it('sets "day"', () => { - SynchronizationLogic.actions.addBlockedWindow(); - SynchronizationLogic.actions.setBlockedTimeWindow(0, 'day', 'tuesday'); + describe('addIndexingRule', () => { + const indexingRule: EditableIndexingRule = { + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + id: 10, + }; - expect(SynchronizationLogic.values.schedule.blockedWindows![0].day).toEqual('tuesday'); + it('adds indexing rule with id 0', () => { + SynchronizationLogic.actions.setIndexingRules([]); + SynchronizationLogic.actions.addIndexingRule(indexingRule); + + expect(SynchronizationLogic.values.indexingRules).toEqual([{ ...indexingRule, id: 0 }]); + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(true); + }); + + it('adds indexing rule with id existing length + 1', () => { + SynchronizationLogic.actions.addIndexingRule(indexingRule); + + expect(SynchronizationLogic.values.indexingRules).toEqual([ + ...defaultValues.indexingRules, + { ...indexingRule, id: 3 }, + ]); + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(true); + }); + it('adds indexing rule with unique id in case of previous deletions', () => { + SynchronizationLogic.actions.deleteIndexingRule({ ...indexingRule, id: 1 }); + SynchronizationLogic.actions.addIndexingRule(indexingRule); + + expect(SynchronizationLogic.values.indexingRules).toEqual([ + defaultValues.indexingRules[0], + defaultValues.indexingRules[2], + { ...indexingRule, id: 3 }, + ]); + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(true); + }); }); - it('sets "start"', () => { - SynchronizationLogic.actions.addBlockedWindow(); - SynchronizationLogic.actions.setBlockedTimeWindow(0, 'start', '9:00:00Z'); + describe('setIndexingRule', () => { + const indexingRule: EditableIndexingRule = { + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + id: 1, + }; + + it('updates indexing rule', () => { + SynchronizationLogic.actions.setIndexingRule(indexingRule); - expect(SynchronizationLogic.values.schedule.blockedWindows![0].start).toEqual('9:00:00Z'); + expect(SynchronizationLogic.values.indexingRules).toEqual([ + defaultValues.indexingRules[0], + indexingRule, + defaultValues.indexingRules[2], + ]); + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(true); + }); }); - it('sets "end"', () => { - SynchronizationLogic.actions.addBlockedWindow(); - SynchronizationLogic.actions.setBlockedTimeWindow(0, 'end', '11:00:00Z'); + describe('setIndexingRules', () => { + const indexingRule: EditableIndexingRule = { + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + id: 1, + }; - expect(SynchronizationLogic.values.schedule.blockedWindows![0].end).toEqual('11:00:00Z'); + it('updates indexing rules', () => { + SynchronizationLogic.actions.setIndexingRules([indexingRule, indexingRule]); + + expect(SynchronizationLogic.values.indexingRules).toEqual([ + { ...indexingRule, id: 0 }, + { ...indexingRule, id: 1 }, + ]); + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(true); + }); + }); + + describe('deleteIndexingRule', () => { + const indexingRule: EditableIndexingRule = { + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + id: 1, + }; + + it('updates indexing rules', () => { + const newIndexingRules = defaultValues.indexingRules.filter( + (val) => val.id !== indexingRule.id + ); + SynchronizationLogic.actions.deleteIndexingRule(indexingRule); + expect(SynchronizationLogic.values.indexingRules).toEqual(newIndexingRules); + + expect(SynchronizationLogic.values.hasUnsavedIndexingRulesChanges).toEqual(true); + }); }); }); @@ -209,6 +355,204 @@ describe('SynchronizationLogic', () => { }); }); + describe('initAddIndexingRule', () => { + const indexingRule: EditableIndexingRule = { + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + id: 1, + }; + it('calls validate endpoint and continues if no errors happen', async () => { + const addIndexingRuleSpy = jest.spyOn(SynchronizationLogic.actions, 'addIndexingRule'); + const promise = Promise.resolve({ rules: [] }); + const doneSpy = jest.spyOn( + InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps).actions, + 'doneEditing' + ); + http.post.mockReturnValue(promise); + SynchronizationLogic.actions.initAddIndexingRule(indexingRule); + + expect(http.post).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/indexing_rules/validate', + { + body: JSON.stringify({ + rules: [ + { + filter_type: 'file_extension', + exclude: 'value', + }, + ], + }), + } + ); + await promise; + expect(addIndexingRuleSpy).toHaveBeenCalledWith(indexingRule); + expect(doneSpy).toHaveBeenCalled(); + }); + + it('calls validate endpoint and sets errors if there is an error', async () => { + const addIndexingRuleSpy = jest.spyOn(SynchronizationLogic.actions, 'addIndexingRule'); + const promise = Promise.resolve({ rules: [{ valid: false, error: 'error' }] }); + http.post.mockReturnValue(promise); + SynchronizationLogic.actions.initAddIndexingRule({ ...indexingRule, valueType: 'include' }); + const doneSpy = jest.spyOn( + InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps).actions, + 'doneEditing' + ); + + expect(http.post).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/indexing_rules/validate', + { + body: JSON.stringify({ + rules: [ + { + filter_type: 'file_extension', + include: 'value', + }, + ], + }), + } + ); + await promise; + expect(addIndexingRuleSpy).not.toHaveBeenCalled(); + expect(doneSpy).toHaveBeenCalled(); + }); + + it('flashes an error if the API call fails', async () => { + const addIndexingRuleSpy = jest.spyOn(SynchronizationLogic.actions, 'addIndexingRule'); + const promise = Promise.reject('error'); + http.post.mockReturnValue(promise); + const doneSpy = jest.spyOn( + InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps).actions, + 'doneEditing' + ); + SynchronizationLogic.actions.initAddIndexingRule(indexingRule); + + expect(http.post).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/indexing_rules/validate', + { + body: JSON.stringify({ + rules: [ + { + filter_type: 'file_extension', + exclude: 'value', + }, + ], + }), + } + ); + await nextTick(); + expect(addIndexingRuleSpy).not.toHaveBeenCalled(); + expect(doneSpy).not.toHaveBeenCalled(); + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); + }); + + describe('initSetIndexingRule', () => { + const indexingRule: EditableIndexingRule = { + filterType: 'file_extension', + valueType: 'exclude', + value: 'value', + id: 1, + }; + + it('calls validate endpoint and continues if no errors happen', async () => { + const setIndexingRuleSpy = jest.spyOn(SynchronizationLogic.actions, 'setIndexingRule'); + const promise = Promise.resolve({ rules: [] }); + http.post.mockReturnValue(promise); + const doneSpy = jest.spyOn( + InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps).actions, + 'doneEditing' + ); + SynchronizationLogic.actions.initSetIndexingRule(indexingRule); + + expect(http.post).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/indexing_rules/validate', + { + body: JSON.stringify({ + rules: [ + { + filter_type: 'file_extension', + exclude: 'value', + }, + ], + }), + } + ); + await promise; + expect(setIndexingRuleSpy).toHaveBeenCalledWith(indexingRule); + expect(doneSpy).toHaveBeenCalled(); + }); + + it('calls validate endpoint and sets errors if there is an error', async () => { + const setIndexingRuleSpy = jest.spyOn(SynchronizationLogic.actions, 'setIndexingRule'); + const promise = Promise.resolve({ rules: [{ valid: false, error: 'error' }] }); + http.post.mockReturnValue(promise); + const doneSpy = jest.spyOn( + InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps).actions, + 'doneEditing' + ); + SynchronizationLogic.actions.initSetIndexingRule({ ...indexingRule, valueType: 'include' }); + + expect(http.post).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/indexing_rules/validate', + { + body: JSON.stringify({ + rules: [ + { + filter_type: 'file_extension', + include: 'value', + }, + ], + }), + } + ); + await promise; + expect(setIndexingRuleSpy).not.toHaveBeenCalled(); + expect(doneSpy).toHaveBeenCalled(); + }); + it('flashes an error if the API call fails', async () => { + const setIndexingRuleSpy = jest.spyOn(SynchronizationLogic.actions, 'setIndexingRule'); + const promise = Promise.reject('error'); + http.post.mockReturnValue(promise); + const doneSpy = jest.spyOn( + InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps).actions, + 'doneEditing' + ); + SynchronizationLogic.actions.initSetIndexingRule(indexingRule); + + expect(http.post).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/indexing_rules/validate', + { + body: JSON.stringify({ + rules: [ + { + filter_type: 'file_extension', + exclude: 'value', + }, + ], + }), + } + ); + await nextTick(); + expect(setIndexingRuleSpy).not.toHaveBeenCalled(); + expect(doneSpy).not.toHaveBeenCalled(); + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); + }); + describe('updateSyncEnabled', () => { it('calls updateServerSettings method', async () => { const updateServerSettingsSpy = jest.spyOn( @@ -225,13 +569,13 @@ describe('SynchronizationLogic', () => { }); }); - describe('updateObjectsAndAssetsSettings', () => { + describe('updateAssetsAndObjectsSettings', () => { it('calls updateServerSettings method', async () => { const updateServerSettingsSpy = jest.spyOn( SynchronizationLogic.actions, 'updateServerSettings' ); - SynchronizationLogic.actions.updateObjectsAndAssetsSettings(); + SynchronizationLogic.actions.updateAssetsAndObjectsSettings(); expect(updateServerSettingsSpy).toHaveBeenCalledWith({ content_source: { @@ -240,6 +584,20 @@ describe('SynchronizationLogic', () => { content_extraction: { enabled: true }, thumbnails: { enabled: true }, }, + rules: [ + { + filter_type: 'object_type', + include: 'value', + }, + { + filter_type: 'path_template', + exclude: 'value', + }, + { + filter_type: 'file_extension', + include: 'value', + }, + ], }, }, }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts index 2f4fdca44d441..547ff1e849734 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts @@ -14,6 +14,11 @@ export type TabId = 'source_sync_frequency' | 'blocked_time_windows'; import { flashAPIErrors, flashSuccessToast } from '../../../../../shared/flash_messages'; import { HttpLogic } from '../../../../../shared/http'; import { KibanaLogic } from '../../../../../shared/kibana'; +import { + InlineEditableTableLogic, + InlineEditableTableProps, +} from '../../../../../shared/tables/inline_editable_table/inline_editable_table_logic'; +import { ItemWithAnID } from '../../../../../shared/tables/types'; import { AppLogic } from '../../../../app_logic'; import { SYNC_FREQUENCY_PATH, @@ -25,9 +30,11 @@ import { BlockedWindow, DayOfWeek, IndexingSchedule, + IndexingRule, ContentSourceFullData, SyncJobType, TimeUnit, + IndexingRuleInclude, } from '../../../../types'; import { SYNC_SETTINGS_UPDATED_MESSAGE } from '../../constants'; @@ -57,6 +64,7 @@ interface ServerSyncSettingsBody { permissions?: string; blocked_windows?: ServerBlockedWindow[]; }; + rules?: IndexingRule[]; }; }; } @@ -67,7 +75,7 @@ interface SynchronizationActions { addBlockedWindow(): void; removeBlockedWindow(index: number): number; updateFrequencySettings(): void; - updateObjectsAndAssetsSettings(): void; + updateAssetsAndObjectsSettings(): void; resetSyncSettings(): void; updateSyncEnabled(enabled: boolean): boolean; setThumbnailsChecked(checked: boolean): boolean; @@ -88,16 +96,26 @@ interface SynchronizationActions { setContentExtractionChecked(checked: boolean): boolean; setServerSchedule(schedule: IndexingSchedule): IndexingSchedule; updateServerSettings(body: ServerSyncSettingsBody): ServerSyncSettingsBody; + addIndexingRule(indexingRule: EditableIndexingRuleBase): EditableIndexingRuleBase; + initAddIndexingRule(rule: EditableIndexingRule): { rule: EditableIndexingRule }; + setIndexingRules(indexingRules: EditableIndexingRule[]): EditableIndexingRule[]; + setIndexingRule(indexingRule: EditableIndexingRule): EditableIndexingRule; + initSetIndexingRule(indexingRule: EditableIndexingRule): { rule: EditableIndexingRule }; + deleteIndexingRule(indexingRule: EditableIndexingRule): EditableIndexingRule; } interface SynchronizationValues { navigatingBetweenTabs: boolean; + hasUnsavedIndexingRulesChanges: boolean; hasUnsavedFrequencyChanges: boolean; - hasUnsavedObjectsAndAssetsChanges: boolean; + hasUnsavedAssetsAndObjectsChanges: boolean; + indexingRules: EditableIndexingRule[]; thumbnailsChecked: boolean; contentExtractionChecked: boolean; cachedSchedule: IndexingSchedule; schedule: IndexingSchedule; + indexingRulesForAPI: IndexingRule[]; + errors: string[]; } export const emptyBlockedWindow: BlockedWindow = { @@ -111,6 +129,26 @@ type BlockedWindowMap = { [prop in keyof BlockedWindow]: SyncJobType | DayOfWeek | 'all' | string; }; +interface EditableIndexingRuleBase { + filterType: 'object_type' | 'path_template' | 'file_extension'; + valueType: 'include' | 'exclude'; + value: string; +} + +export interface EditableIndexingRule extends EditableIndexingRuleBase { + id: number; +} + +interface IndexingRuleForAPI { + filter_type: 'object_type' | 'path_template' | 'file_extension'; + include?: string; + exclude?: string; +} + +const isIncludeRule = (rule: IndexingRule): rule is IndexingRuleInclude => { + return !!(rule as IndexingRuleInclude).include; +}; + export const SynchronizationLogic = kea< MakeLogicType >({ @@ -135,11 +173,28 @@ export const SynchronizationLogic = kea< setServerSchedule: (schedule: IndexingSchedule) => schedule, removeBlockedWindow: (index: number) => index, updateFrequencySettings: true, - updateObjectsAndAssetsSettings: true, + updateAssetsAndObjectsSettings: true, resetSyncSettings: true, addBlockedWindow: true, + addIndexingRule: (rule: EditableIndexingRuleBase) => rule, + deleteIndexingRule: (rule: EditableIndexingRule) => rule, + initAddIndexingRule: (rule: EditableIndexingRule) => ({ rule }), + initSetIndexingRule: (rule: EditableIndexingRule) => ({ rule }), + setIndexingRules: (indexingRules: EditableIndexingRule[]) => indexingRules, + setIndexingRule: (rule: EditableIndexingRule) => rule, }, reducers: ({ props }) => ({ + hasUnsavedIndexingRulesChanges: [ + false, + { + setIndexingRule: () => true, + setIndexingRules: () => true, + addIndexingRule: () => true, + deleteIndexingRule: () => true, + resetSyncSettings: () => false, + updateServerSettings: () => false, + }, + ], navigatingBetweenTabs: [ false, { @@ -228,15 +283,55 @@ export const SynchronizationLogic = kea< }, }, ], + indexingRules: [ + (props.contentSource.indexing.rules as IndexingRule[]).map((rule, index) => ({ + filterType: rule.filterType, + id: index, + valueType: isIncludeRule(rule) ? 'include' : 'exclude', + value: isIncludeRule(rule) ? rule.include : rule.exclude, + })), + { + addIndexingRule: (indexingRules, rule) => [ + ...indexingRules, + { + ...rule, + // make sure that we get a unique number, in case of multiple deletions and additions + id: indexingRules.reduce( + (prev, curr) => (curr.id >= prev ? curr.id + 1 : prev), + indexingRules.length + ), + }, + ], + deleteIndexingRule: (indexingRules, rule) => + indexingRules.filter((currentRule) => currentRule.id !== rule.id), + resetSyncSettings: () => + (props.contentSource.indexing.rules as IndexingRule[]).map((rule, index) => ({ + filterType: rule.filterType, + id: index, + valueType: isIncludeRule(rule) ? 'include' : 'exclude', + value: isIncludeRule(rule) ? rule.include : rule.exclude, + })), + setIndexingRules: (_, indexingRules) => + indexingRules.map((val, index) => ({ ...val, id: index })), + setIndexingRule: (state, rule) => + state.map((currentRule) => (currentRule.id === rule.id ? rule : currentRule)), + }, + ], }), selectors: ({ selectors }) => ({ - hasUnsavedObjectsAndAssetsChanges: [ + hasUnsavedAssetsAndObjectsChanges: [ () => [ selectors.thumbnailsChecked, selectors.contentExtractionChecked, + selectors.hasUnsavedIndexingRulesChanges, (_, props) => props.contentSource, ], - (thumbnailsChecked, contentExtractionChecked, contentSource) => { + ( + thumbnailsChecked, + contentExtractionChecked, + hasUnsavedIndexingRulesChanges, + contentSource + ) => { const { indexing: { features: { @@ -248,7 +343,8 @@ export const SynchronizationLogic = kea< return ( thumbnailsChecked !== thumbnailsEnabled || - contentExtractionChecked !== contentExtractionEnabled + contentExtractionChecked !== contentExtractionEnabled || + hasUnsavedIndexingRulesChanges ); }, ], @@ -256,6 +352,11 @@ export const SynchronizationLogic = kea< () => [selectors.cachedSchedule, selectors.schedule], (cachedSchedule, schedule) => !isEqual(cachedSchedule, schedule), ], + indexingRulesForAPI: [ + () => [selectors.indexingRules], + (indexingRules: EditableIndexingRule[]) => + indexingRules.map((indexingRule) => indexingRuleToApiFormat(indexingRule)), + ], }), listeners: ({ actions, values, props }) => ({ handleSelectedTabChanged: async (tabId, breakpoint) => { @@ -277,6 +378,62 @@ export const SynchronizationLogic = kea< KibanaLogic.values.navigateToUrl(path); actions.setNavigatingBetweenTabs(false); }, + initAddIndexingRule: async ({ rule }) => { + const { id: sourceId } = props.contentSource; + const route = `/internal/workplace_search/org/sources/${sourceId}/indexing_rules/validate`; + try { + const response = await HttpLogic.values.http.post<{ + rules: Array<{ + valid: boolean; + error?: string; + }>; + }>(route, { + body: JSON.stringify({ + rules: [indexingRuleToApiFormat(rule)], + }), + }); + const error = response.rules[0]?.error; + const tableLogic = InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps); + if (error) { + tableLogic.actions.setRowErrors([error]); + } else { + actions.addIndexingRule(rule); + } + tableLogic.actions.doneEditing(); + } catch (e) { + flashAPIErrors(e); + } + }, + initSetIndexingRule: async ({ rule }) => { + const { id: sourceId } = props.contentSource; + const route = `/internal/workplace_search/org/sources/${sourceId}/indexing_rules/validate`; + try { + const response = await HttpLogic.values.http.post<{ + rules: Array<{ + valid: boolean; + error?: string; + }>; + }>(route, { + body: JSON.stringify({ + rules: [indexingRuleToApiFormat(rule)], + }), + }); + const error = response.rules[0]?.error; + const tableLogic = InlineEditableTableLogic({ + instanceId: 'IndexingRulesTable', + } as InlineEditableTableProps); + if (error) { + tableLogic.actions.setRowErrors([error]); + } else { + actions.setIndexingRule(rule); + } + tableLogic.actions.doneEditing(); + } catch (e) { + flashAPIErrors(e); + } + }, updateSyncEnabled: async (enabled) => { actions.updateServerSettings({ content_source: { @@ -284,7 +441,7 @@ export const SynchronizationLogic = kea< }, }); }, - updateObjectsAndAssetsSettings: () => { + updateAssetsAndObjectsSettings: () => { actions.updateServerSettings({ content_source: { indexing: { @@ -292,6 +449,7 @@ export const SynchronizationLogic = kea< content_extraction: { enabled: values.contentExtractionChecked }, thumbnails: { enabled: values.thumbnailsChecked }, }, + rules: values.indexingRulesForAPI, }, }, }); @@ -360,3 +518,10 @@ const formatBlockedWindowsForServer = ( end, })); }; + +const indexingRuleToApiFormat = (indexingRule: EditableIndexingRule): IndexingRuleForAPI => { + const { valueType, filterType, value } = indexingRule; + return valueType === 'include' + ? { filter_type: filterType, include: value } + : { filter_type: filterType, exclude: value }; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx index cf130d2c21a57..b863c43edcb3d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx @@ -10,12 +10,12 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockValues } from '../../../../../__mocks__/kea_logic'; import React from 'react'; -import { Route, Switch } from 'react-router-dom'; +import { Redirect, Route, Switch } from 'react-router-dom'; import { shallow } from 'enzyme'; +import { AssetsAndObjects } from './assets_and_objects'; import { Frequency } from './frequency'; -import { ObjectsAndAssets } from './objects_and_assets'; import { Synchronization } from './synchronization'; import { SynchronizationRouter } from './synchronization_router'; @@ -25,9 +25,10 @@ describe('SynchronizationRouter', () => { const wrapper = shallow(); expect(wrapper.find(Synchronization)).toHaveLength(1); - expect(wrapper.find(ObjectsAndAssets)).toHaveLength(1); + expect(wrapper.find(AssetsAndObjects)).toHaveLength(1); expect(wrapper.find(Frequency)).toHaveLength(2); expect(wrapper.find(Switch)).toHaveLength(1); expect(wrapper.find(Route)).toHaveLength(4); + expect(wrapper.find(Redirect)).toHaveLength(1); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx index ede0f293377cf..ad91dfb1bd65e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx @@ -6,18 +6,19 @@ */ import React from 'react'; -import { Route, Switch } from 'react-router-dom'; +import { Redirect, Route, Switch } from 'react-router-dom'; import { SYNC_FREQUENCY_PATH, BLOCKED_TIME_WINDOWS_PATH, - OBJECTS_AND_ASSETS_PATH, + ASSETS_AND_OBJECTS_PATH, SOURCE_SYNCHRONIZATION_PATH, getSourcesPath, + OLD_OBJECTS_AND_ASSETS_PATH, } from '../../../../routes'; +import { AssetsAndObjects } from './assets_and_objects'; import { Frequency } from './frequency'; -import { ObjectsAndAssets } from './objects_and_assets'; import { Synchronization } from './synchronization'; export const SynchronizationRouter: React.FC = () => ( @@ -31,8 +32,12 @@ export const SynchronizationRouter: React.FC = () => ( - - + + + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx index a2978c34475db..80e4e1fc06b10 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx @@ -24,9 +24,9 @@ describe('useSynchronizationSubNav', () => { href: '/sources/1/synchronization/frequency', }, { - id: 'sourceSynchronizationObjectsAndAssets', - name: 'Objects and assets', - href: '/sources/1/synchronization/objects_and_assets', + id: 'sourceSynchronizationAssetsAndObjects', + name: 'Assets and objects', + href: '/sources/1/synchronization/assets_and_objects', }, ]); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx index 2df6e9177211f..ab4f0cb3c0c09 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx @@ -14,7 +14,7 @@ import { NAV } from '../../../../constants'; import { getContentSourcePath, SYNC_FREQUENCY_PATH, - OBJECTS_AND_ASSETS_PATH, + ASSETS_AND_OBJECTS_PATH, } from '../../../../routes'; import { SourceLogic } from '../../source_logic'; @@ -35,9 +35,9 @@ export const useSynchronizationSubNav = () => { }), }, { - id: 'sourceSynchronizationObjectsAndAssets', - name: NAV.SYNCHRONIZATION_OBJECTS_AND_ASSETS, - ...generateNavLink({ to: getContentSourcePath(OBJECTS_AND_ASSETS_PATH, id, true) }), + id: 'sourceSynchronizationAssetsAndObjects', + name: NAV.SYNCHRONIZATION_ASSETS_AND_OBJECTS, + ...generateNavLink({ to: getContentSourcePath(ASSETS_AND_OBJECTS_PATH, id, true) }), }, ]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts index 92749f5129197..4dd41a7930181 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts @@ -543,21 +543,31 @@ export const SOURCE_FREQUENCY_DESCRIPTION = i18n.translate( } ); -export const SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION = i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsDescription', +export const SOURCE_ASSETS_AND_OBJECTS_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsDescription', { defaultMessage: - 'Customize the indexing rules that determine which objects and assets are synchronized from this content source to Workplace Search.', + 'Flexibly manage the documents to be synchronized and made available for search using granular controls below.', } ); -export const SOURCE_OBJECTS_AND_ASSETS_LABEL = i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsLabel', +export const SOURCE_ASSETS_AND_OBJECTS_LEARN_MORE_LINK = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsLearnMoreLink', { - defaultMessage: 'Object and details to include in search results', + defaultMessage: 'Learn more about sync objects types.', } ); +export const SOURCE_ASSETS_AND_OBJECTS_ASSETS_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsAssetsLabel', + { defaultMessage: 'Assets' } +); + +export const SOURCE_ASSETS_AND_OBJECTS_OBJECTS_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceAssetsAndObjectsObjectsLabel', + { defaultMessage: 'Objects' } +); + export const SOURCE_SYNCHRONIZATION_TOGGLE_LABEL = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSynchronizationToggleLabel', { diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.test.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.test.ts index 3702298e8bcae..bbcb102c6c4ed 100644 --- a/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.test.ts @@ -44,6 +44,8 @@ import { registerOrgSourceOauthConfigurationRoute, registerOrgSourceSynchronizeRoute, registerOauthConnectorParamsRoute, + registerAccountSourceValidateIndexingRulesRoute, + registerOrgSourceValidateIndexingRulesRoute, } from './sources'; const mockConfig = { @@ -310,6 +312,45 @@ describe('sources routes', () => { }); }); + describe('POST /internal/workplace_search/account/sources/{id}/indexing_rules/validate', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'post', + path: '/internal/workplace_search/account/sources/{id}/indexing_rules/validate', + }); + + registerAccountSourceValidateIndexingRulesRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/sources/:id/indexing_rules/validate', + }); + }); + + describe('validates', () => { + it('correctly', () => { + const request = { + body: { + rules: [ + { + filter_type: 'path_template', + exclude: '', + }, + ], + }, + }; + mockRouter.shouldValidate(request); + }); + }); + }); + describe('GET /internal/workplace_search/account/pre_sources/{id}', () => { let mockRouter: MockRouter; @@ -818,6 +859,45 @@ describe('sources routes', () => { }); }); + describe('POST /internal/workplace_search/org/sources/{id}/indexing_rules/validate', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'post', + path: '/internal/workplace_search/org/sources/{id}/indexing_rules/validate', + }); + + registerOrgSourceValidateIndexingRulesRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/sources/:id/indexing_rules/validate', + }); + }); + + describe('validates', () => { + it('correctly', () => { + const request = { + body: { + rules: [ + { + filter_type: 'path_template', + exclude: '', + }, + ], + }, + }; + mockRouter.shouldValidate(request); + }); + }); + }); + describe('GET /internal/workplace_search/org/pre_sources/{id}', () => { let mockRouter: MockRouter; diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts index 12f4844461409..222288d369fdb 100644 --- a/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts @@ -96,11 +96,32 @@ const sourceSettingsSchema = schema.object({ ), }) ), + rules: schema.maybe( + schema.arrayOf( + schema.object({ + filter_type: schema.string(), + exclude: schema.maybe(schema.string()), + include: schema.maybe(schema.string()), + }) + ) + ), }) ), }), }); +const validateRulesSchema = schema.object({ + rules: schema.maybe( + schema.arrayOf( + schema.object({ + filter_type: schema.string(), + exclude: schema.maybe(schema.string()), + include: schema.maybe(schema.string()), + }) + ) + ), +}); + // Account routes export function registerAccountSourcesRoute({ router, @@ -273,6 +294,26 @@ export function registerAccountSourceSettingsRoute({ ); } +export function registerAccountSourceValidateIndexingRulesRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.post( + { + path: '/internal/workplace_search/account/sources/{id}/indexing_rules/validate', + validate: { + body: validateRulesSchema, + params: schema.object({ + id: schema.string(), + }), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/sources/:id/indexing_rules/validate', + }) + ); +} + export function registerAccountPreSourceRoute({ router, enterpriseSearchRequestHandler, @@ -620,6 +661,26 @@ export function registerOrgSourceSettingsRoute({ ); } +export function registerOrgSourceValidateIndexingRulesRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.post( + { + path: '/internal/workplace_search/org/sources/{id}/indexing_rules/validate', + validate: { + body: validateRulesSchema, + params: schema.object({ + id: schema.string(), + }), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/sources/:id/indexing_rules/validate', + }) + ); +} + export function registerOrgPreSourceRoute({ router, enterpriseSearchRequestHandler, @@ -955,6 +1016,7 @@ export const registerSourcesRoutes = (dependencies: RouteDependencies) => { registerAccountSourceFederatedSummaryRoute(dependencies); registerAccountSourceReauthPrepareRoute(dependencies); registerAccountSourceSettingsRoute(dependencies); + registerAccountSourceValidateIndexingRulesRoute(dependencies); registerAccountPreSourceRoute(dependencies); registerAccountPrepareSourcesRoute(dependencies); registerAccountSourceSearchableRoute(dependencies); @@ -970,6 +1032,7 @@ export const registerSourcesRoutes = (dependencies: RouteDependencies) => { registerOrgSourceFederatedSummaryRoute(dependencies); registerOrgSourceReauthPrepareRoute(dependencies); registerOrgSourceSettingsRoute(dependencies); + registerOrgSourceValidateIndexingRulesRoute(dependencies); registerOrgPreSourceRoute(dependencies); registerOrgPrepareSourcesRoute(dependencies); registerOrgSourceSearchableRoute(dependencies); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 481c7e3911753..5956b7ad84108 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -10666,7 +10666,6 @@ "xpack.enterpriseSearch.workplaceSearch.nav.sources": "ソース", "xpack.enterpriseSearch.workplaceSearch.nav.synchronization": "同期", "xpack.enterpriseSearch.workplaceSearch.nav.synchronizationFrequency": "頻度", - "xpack.enterpriseSearch.workplaceSearch.nav.synchronizationObjectsAndAssets": "オブジェクトとアセット", "xpack.enterpriseSearch.workplaceSearch.nonPlatinumOauthDescription": "Workplace Search検索APIを安全に使用するために、OAuthアプリケーションを構成します。プラチナライセンスにアップグレードして、検索APIを有効にし、OAuthアプリケーションを作成します。", "xpack.enterpriseSearch.workplaceSearch.nonPlatinumOauthTitle": "カスタム検索アプリケーションのOAuthを構成", "xpack.enterpriseSearch.workplaceSearch.oauth.description": "組織のOAuthクライアントを作成します。", @@ -10920,8 +10919,6 @@ "xpack.enterpriseSearch.workplaceSearch.sources.sourceNames.sharePoint": "SharePoint Online", "xpack.enterpriseSearch.workplaceSearch.sources.sourceNames.slack": "Slack", "xpack.enterpriseSearch.workplaceSearch.sources.sourceNames.zendesk": "Zendesk", - "xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsDescription": "このコンテンツソースからWorkplace Searchに同期されるオブジェクトとアセットを決定するインデックスルールをカスタマイズします。", - "xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsLabel": "検索結果に含めるオブジェクトと詳細", "xpack.enterpriseSearch.workplaceSearch.sources.sourceOverviewTitle": "ソース概要", "xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncConfirmMessage": "この要求を続行し、他のすべての同期を停止しますか?", "xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncConfirmTitle": "新しいコンテンツ同期を開始しますか?", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9fe16bef172a0..49f8d466523ac 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10524,7 +10524,6 @@ "xpack.enterpriseSearch.workplaceSearch.nav.sources": "源", "xpack.enterpriseSearch.workplaceSearch.nav.synchronization": "同步", "xpack.enterpriseSearch.workplaceSearch.nav.synchronizationFrequency": "频率", - "xpack.enterpriseSearch.workplaceSearch.nav.synchronizationObjectsAndAssets": "对象和资产", "xpack.enterpriseSearch.workplaceSearch.nonPlatinumOauthDescription": "配置 OAuth 应用程序,以安全使用 Workplace Search 搜索 API。升级到白金级许可证,以启用搜索 API 并创建您的 OAuth 应用程序。", "xpack.enterpriseSearch.workplaceSearch.nonPlatinumOauthTitle": "正在为定制搜索应用程序配置 OAuth", "xpack.enterpriseSearch.workplaceSearch.oauth.description": "为您的组织创建 OAuth 客户端。", @@ -10779,8 +10778,6 @@ "xpack.enterpriseSearch.workplaceSearch.sources.sourceNames.sharePoint": "Sharepoint", "xpack.enterpriseSearch.workplaceSearch.sources.sourceNames.slack": "Slack", "xpack.enterpriseSearch.workplaceSearch.sources.sourceNames.zendesk": "Zendesk", - "xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsDescription": "定制确定将哪些对象和资产从此内容源同步到 Workplace Search 的索引规则。", - "xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsLabel": "要包括在搜索结果中的对象和详情", "xpack.enterpriseSearch.workplaceSearch.sources.sourceOverviewTitle": "源概览", "xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncConfirmMessage": "是否确定要继续处理此请求并停止所有其他同步?", "xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncConfirmTitle": "开始新内容同步?", From 3fe08aff12834c1c0d556a7ba4cf8ff1488cb585 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Wed, 16 Feb 2022 16:10:14 +0100 Subject: [PATCH 007/104] [Fleet] readded missing packages to keep up to date list (#125787) * readded missing packages to keep up to date list * rename --- .../fleet/common/constants/preconfiguration.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/common/constants/preconfiguration.ts b/x-pack/plugins/fleet/common/constants/preconfiguration.ts index 5689223852a32..e1dc87a3ebd06 100644 --- a/x-pack/plugins/fleet/common/constants/preconfiguration.ts +++ b/x-pack/plugins/fleet/common/constants/preconfiguration.ts @@ -7,6 +7,8 @@ import { uniqBy } from 'lodash'; +import { FLEET_ELASTIC_AGENT_PACKAGE, FLEET_SERVER_PACKAGE, FLEET_SYSTEM_PACKAGE } from '.'; + import { autoUpdatePackages, autoUpgradePoliciesPackages } from './epm'; // UUID v5 values require a namespace. We use UUID v5 for some of our preconfigured ID values. @@ -28,9 +30,18 @@ export const AUTO_UPGRADE_POLICIES_PACKAGES = autoUpgradePoliciesPackages.map((n version: PRECONFIGURATION_LATEST_KEYWORD, })); +export const FLEET_PACKAGES = [ + FLEET_SYSTEM_PACKAGE, + FLEET_ELASTIC_AGENT_PACKAGE, + FLEET_SERVER_PACKAGE, +].map((name) => ({ + name, + version: PRECONFIGURATION_LATEST_KEYWORD, +})); + // Controls whether the `Keep Policies up to date` setting is exposed to the user export const KEEP_POLICIES_UP_TO_DATE_PACKAGES = uniqBy( - [...AUTO_UPGRADE_POLICIES_PACKAGES, ...AUTO_UPDATE_PACKAGES], + [...AUTO_UPGRADE_POLICIES_PACKAGES, ...FLEET_PACKAGES, ...AUTO_UPDATE_PACKAGES], ({ name }) => name ); From f894d8673b30c5eb8f239f740b1b8fa27057ee64 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Wed, 16 Feb 2022 07:20:17 -0800 Subject: [PATCH 008/104] [Security Solution][Lists] - Fix exception list with comments import bug (#124909) ### Summary Addresses https://github.com/elastic/kibana/issues/124742 #### Issue TLDR Import of rules that reference exception items with comments fail. Failure message states that comments cannot include `created_at`, `created_by`, `id`. --- .../index.test.ts | 87 ++++++++++ .../default_import_comments_array/index.ts | 27 +++ .../index.test.ts | 4 +- .../default_update_comments_array/index.ts | 10 +- .../src/common/import_comment/index.test.ts | 135 +++++++++++++++ .../src/common/import_comment/index.ts | 19 +++ .../src/common/index.ts | 2 + .../src/common/update_comment/index.test.ts | 2 +- .../index.test.ts | 30 ++++ .../import_exception_item_schema/index.ts | 8 +- .../create_exceptions_stream_logic.test.ts | 46 +++++ .../import/create_exceptions_stream_logic.ts | 25 ++- .../tests/import_export_rules.ts | 126 ++++++++++++++ .../security_and_spaces/tests/import_rules.ts | 159 +++++++++++++++++- .../security_and_spaces/tests/index.ts | 1 + .../detection_engine_api_integration/utils.ts | 2 +- 16 files changed, 666 insertions(+), 17 deletions(-) create mode 100644 packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts create mode 100644 packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts create mode 100644 packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts create mode 100644 packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_export_rules.ts diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts new file mode 100644 index 0000000000000..8584edfabeebd --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.test.ts @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; +import { ImportCommentsArray } from '../import_comment'; +import { DefaultImportCommentsArray } from '../default_import_comments_array'; +import { getCommentsArrayMock } from '../comment/index.mock'; +import { getCreateCommentsArrayMock } from '../create_comment/index.mock'; + +describe('default_import_comments_array', () => { + test('it should pass validation when supplied an empty array', () => { + const payload: ImportCommentsArray = []; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of comments', () => { + const payload: ImportCommentsArray = getCommentsArrayMock(); + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of new comments', () => { + const payload: ImportCommentsArray = getCreateCommentsArrayMock(); + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should pass validation when supplied an array of new and existing comments', () => { + const payload: ImportCommentsArray = [ + ...getCommentsArrayMock(), + ...getCreateCommentsArrayMock(), + ]; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it should fail validation when supplied an array of numbers', () => { + const payload = [1]; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "DefaultImportComments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should fail validation when supplied an array of strings', () => { + const payload = ['some string']; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "some string" supplied to "DefaultImportComments"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it should return a default array entry', () => { + const payload = null; + const decoded = DefaultImportCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual([]); + }); +}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts new file mode 100644 index 0000000000000..2e3ec1e00375a --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_import_comments_array/index.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as t from 'io-ts'; +import { Either } from 'fp-ts/lib/Either'; +import { importComment, ImportCommentsArray } from '../import_comment'; + +/** + * Types the DefaultImportCommentsArray as: + * - If null or undefined, then a default array of type ImportCommentsArray will be set + */ +export const DefaultImportCommentsArray = new t.Type< + ImportCommentsArray, + ImportCommentsArray, + unknown +>( + 'DefaultImportComments', + t.array(importComment).is, + (input, context): Either => + input == null ? t.success([]) : t.array(importComment).validate(input, context), + t.identity +); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts index fa6613538b18e..05c4e91355da4 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.test.ts @@ -38,7 +38,7 @@ describe('default_update_comments_array', () => { const message = pipe(decoded, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', + 'Invalid value "1" supplied to "DefaultUpdateComments"', ]); expect(message.schema).toEqual({}); }); @@ -49,7 +49,7 @@ describe('default_update_comments_array', () => { const message = pipe(decoded, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', + 'Invalid value "some string" supplied to "DefaultUpdateComments"', ]); expect(message.schema).toEqual({}); }); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts index 26bfdad597100..cc70ba1d095b8 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/default_update_comments_array/index.ts @@ -11,17 +11,17 @@ import { Either } from 'fp-ts/lib/Either'; import { updateCommentsArray, UpdateCommentsArray } from '../update_comment'; /** - * Types the DefaultCommentsUpdate as: - * - If null or undefined, then a default array of type entry will be set + * Types the DefaultUpdateComments as: + * - If null or undefined, then a default array of type UpdateCommentsArray will be set */ export const DefaultUpdateCommentsArray = new t.Type< UpdateCommentsArray, UpdateCommentsArray, unknown >( - 'DefaultCreateComments', + 'DefaultUpdateComments', updateCommentsArray.is, - (input): Either => - input == null ? t.success([]) : updateCommentsArray.decode(input), + (input, context): Either => + input == null ? t.success([]) : updateCommentsArray.validate(input, context), t.identity ); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts new file mode 100644 index 0000000000000..53383d80f441d --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.test.ts @@ -0,0 +1,135 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; +import { getCommentsArrayMock, getCommentsMock } from '../comment/index.mock'; +import { getCreateCommentsArrayMock } from '../create_comment/index.mock'; +import { + importComment, + ImportCommentsArray, + importCommentsArray, + ImportCommentsArrayOrUndefined, + importCommentsArrayOrUndefined, +} from '.'; +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('ImportComment', () => { + describe('importComment', () => { + test('it passes validation with a typical comment', () => { + const payload = getCommentsMock(); + const decoded = importComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation with a new comment', () => { + const payload = { comment: 'new comment' }; + const decoded = importComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = importComment.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('importCommentsArray', () => { + test('it passes validation an array of Comment', () => { + const payload = getCommentsArrayMock(); + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation an array of CreateComment', () => { + const payload = getCreateCommentsArrayMock(); + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation an array of Comment and CreateComment', () => { + const payload = [...getCommentsArrayMock(), ...getCreateCommentsArrayMock()]; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when undefined', () => { + const payload = undefined; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "undefined" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', + ]); + expect(message.schema).toEqual({}); + }); + + test('it fails validation when array includes non ImportComment types', () => { + const payload = [1] as unknown as ImportCommentsArray; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', + ]); + expect(message.schema).toEqual({}); + }); + }); + + describe('importCommentsArrayOrUndefined', () => { + test('it passes validation an array of ImportComment', () => { + const payload = [...getCommentsArrayMock(), ...getCreateCommentsArrayMock()]; + const decoded = importCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it passes validation when undefined', () => { + const payload = undefined; + const decoded = importCommentsArrayOrUndefined.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it fails validation when array includes non ImportComment types', () => { + const payload = [1] as unknown as ImportCommentsArrayOrUndefined; + const decoded = importCommentsArray.decode(payload); + const message = pipe(decoded, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "1" supplied to "Array<(({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: NonEmptyString |})>"', + ]); + expect(message.schema).toEqual({}); + }); + }); +}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts new file mode 100644 index 0000000000000..43a0755bb5b51 --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/import_comment/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as t from 'io-ts'; +import { createComment } from '../create_comment'; +import { comment } from '../comment'; + +export const importComment = t.union([comment, createComment]); + +export type ImportComment = t.TypeOf; +export const importCommentsArray = t.array(importComment); +export type ImportCommentsArray = t.TypeOf; +export const importCommentsArrayOrUndefined = t.union([importCommentsArray, t.undefined]); +export type ImportCommentsArrayOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts index 98c160e2c4302..fadf00fa7a40b 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts @@ -13,6 +13,7 @@ export * from './created_by'; export * from './cursor'; export * from './default_namespace'; export * from './default_namespace_array'; +export * from './default_import_comments_array'; export * from './description'; export * from './deserializer'; export * from './endpoint'; @@ -29,6 +30,7 @@ export * from './exception_list_item_type'; export * from './filter'; export * from './id'; export * from './immutable'; +export * from './import_comment'; export * from './item_id'; export * from './list_id'; export * from './list_operator'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts index 7ddbdf31ca317..04a0d49306b36 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.test.ts @@ -19,7 +19,7 @@ import { } from '.'; import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -describe('CommentsUpdate', () => { +describe('UpdateComment', () => { describe('updateComment', () => { test('it should pass validation when supplied typical comment update', () => { const payload = getUpdateCommentMock(); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts index d202f65b57ab5..a5cb57dfb56a8 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.test.ts @@ -15,6 +15,7 @@ import { getImportExceptionsListItemSchemaDecodedMock, getImportExceptionsListItemSchemaMock, } from './index.mock'; +import { getCommentsArrayMock } from '../../common/comment/index.mock'; describe('import_list_item_schema', () => { test('it should validate a typical item request', () => { @@ -27,6 +28,35 @@ describe('import_list_item_schema', () => { expect(message.schema).toEqual(getImportExceptionsListItemSchemaDecodedMock()); }); + test('it should validate a typical item request with comments', () => { + const payload = { + ...getImportExceptionsListItemSchemaMock(), + comments: getCommentsArrayMock(), + }; + const decoded = importExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual({ + ...getImportExceptionsListItemSchemaDecodedMock(), + comments: [ + { + comment: 'some old comment', + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'some user', + id: 'uuid_here', + }, + { + comment: 'some old comment', + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'some user', + id: 'uuid_here', + }, + ], + }); + }); + test('it should NOT accept an undefined for "item_id"', () => { const payload: Partial> = getImportExceptionsListItemSchemaMock(); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts index 3da30a21a0115..dc5a48597211e 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/request/import_exception_item_schema/index.ts @@ -29,8 +29,8 @@ import { nonEmptyEntriesArray } from '../../common/non_empty_entries_array'; import { exceptionListItemType } from '../../common/exception_list_item_type'; import { ItemId } from '../../common/item_id'; import { EntriesArray } from '../../common/entries'; -import { CreateCommentsArray } from '../../common/create_comment'; -import { DefaultCreateCommentsArray } from '../../common/default_create_comments_array'; +import { DefaultImportCommentsArray } from '../../common/default_import_comments_array'; +import { ImportCommentsArray } from '../../common'; /** * Differences from this and the createExceptionsListItemSchema are @@ -56,7 +56,7 @@ export const importExceptionListItemSchema = t.intersection([ t.exact( t.partial({ id, // defaults to undefined if not set during decode - comments: DefaultCreateCommentsArray, // defaults to empty array if not set during decode + comments: DefaultImportCommentsArray, // defaults to empty array if not set during decode created_at, // defaults undefined if not set during decode updated_at, // defaults undefined if not set during decode created_by, // defaults undefined if not set during decode @@ -78,7 +78,7 @@ export type ImportExceptionListItemSchemaDecoded = Omit< ImportExceptionListItemSchema, 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments' > & { - comments: CreateCommentsArray; + comments: ImportCommentsArray; tags: Tags; item_id: ItemId; entries: EntriesArray; diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts b/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts index 684be2de2e030..37e3201dcfe42 100644 --- a/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts +++ b/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.test.ts @@ -24,6 +24,7 @@ import { PromiseStream } from '../../import_exception_list_and_items'; import { createExceptionsStreamFromNdjson, exceptionsChecksFromArray, + manageExceptionComments, } from './create_exceptions_stream_logic'; describe('create_exceptions_stream_logic', () => { @@ -338,4 +339,49 @@ describe('create_exceptions_stream_logic', () => { }); }); }); + + describe('manageExceptionComments', () => { + test('returns empty array if passed in "comments" undefined', () => { + const result = manageExceptionComments(undefined); + expect(result).toEqual([]); + }); + + test('returns empty array if passed in "comments" empty array', () => { + const result = manageExceptionComments([]); + expect(result).toEqual([]); + }); + + test('returns formatted existing comment', () => { + const result = manageExceptionComments([ + { + comment: 'some old comment', + created_at: '2020-04-20T15:25:31.830Z', + created_by: 'kibana', + id: 'uuid_here', + updated_at: '2020-05-20T15:25:31.830Z', + updated_by: 'lily', + }, + ]); + + expect(result).toEqual([ + { + comment: 'some old comment', + }, + ]); + }); + + test('returns formatted new comment', () => { + const result = manageExceptionComments([ + { + comment: 'some new comment', + }, + ]); + + expect(result).toEqual([ + { + comment: 'some new comment', + }, + ]); + }); + }); }); diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts b/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts index af39936b26142..eb009d2492b6a 100644 --- a/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts +++ b/x-pack/plugins/lists/server/services/exception_lists/utils/import/create_exceptions_stream_logic.ts @@ -12,7 +12,9 @@ import { has } from 'lodash/fp'; import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { + CreateCommentsArray, ExportExceptionDetails, + ImportCommentsArray, ImportExceptionListItemSchema, ImportExceptionListItemSchemaDecoded, ImportExceptionListSchemaDecoded, @@ -120,6 +122,24 @@ export const sortExceptionsStream = (): Transform => { ); }; +/** + * Updates any comments associated with exception items to resemble + * comment creation schema. + * See issue for context https://github.com/elastic/kibana/issues/124742#issuecomment-1033082093 + * @returns {array} comments reformatted properly for import + */ +export const manageExceptionComments = ( + comments: ImportCommentsArray | undefined +): CreateCommentsArray => { + if (comments == null || !comments.length) { + return []; + } else { + return comments.map(({ comment }) => ({ + comment, + })); + } +}; + /** * * Validating exceptions logic @@ -206,8 +226,9 @@ export const validateExceptionsItems = ( return items.map((item: ImportExceptionListItemSchema | Error) => { if (!(item instanceof Error)) { - const decodedItem = importExceptionListItemSchema.decode(item); - const checkedItem = exactCheck(item, decodedItem); + const itemWithUpdatedComments = { ...item, comments: manageExceptionComments(item.comments) }; + const decodedItem = importExceptionListItemSchema.decode(itemWithUpdatedComments); + const checkedItem = exactCheck(itemWithUpdatedComments, decodedItem); return pipe(checkedItem, fold(onLeft, onRight)); } else { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_export_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_export_rules.ts new file mode 100644 index 0000000000000..21d545aef0f04 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_export_rules.ts @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; + +import { deleteAllExceptions } from '../../../lists_api_integration/utils'; +import { getCreateExceptionListItemMinimalSchemaMock } from '../../../../plugins/lists/common/schemas/request/create_exception_list_item_schema.mock'; +import { getCreateExceptionListMinimalSchemaMock } from '../../../../plugins/lists/common/schemas/request/create_exception_list_schema.mock'; +import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + binaryToString, + createRule, + createSignalsIndex, + deleteAllAlerts, + deleteSignalsIndex, + getSimpleRule, +} from '../../utils'; +import { ROLES } from '../../../../plugins/security_solution/common/test'; +import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; + +// This test was meant to be more full flow, ensuring that +// exported rules are able to be reimported as opposed to +// testing the import/export functionality separately +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const log = getService('log'); + + describe('import_export_rules_flow', () => { + beforeEach(async () => { + await createSignalsIndex(supertest, log); + await createUserAndRole(getService, ROLES.soc_manager); + }); + + afterEach(async () => { + await deleteUserAndRole(getService, ROLES.soc_manager); + await deleteAllExceptions(supertest, log); + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + + it('should be able to reimport a rule referencing an exception list with existing comments', async () => { + // create an exception list + const { body: exceptionBody } = await supertestWithoutAuth + .post(EXCEPTION_LIST_URL) + .auth(ROLES.soc_manager, 'changeme') + .set('kbn-xsrf', 'true') + .send(getCreateExceptionListMinimalSchemaMock()) + .expect(200); + + // create an exception list item + const { body: exceptionItemBody } = await supertestWithoutAuth + .post(EXCEPTION_LIST_ITEM_URL) + .auth(ROLES.soc_manager, 'changeme') + .set('kbn-xsrf', 'true') + .send({ + ...getCreateExceptionListItemMinimalSchemaMock(), + comments: [{ comment: 'this exception item rocks' }], + }) + .expect(200); + + const { body: exceptionItem } = await supertest + .get(`${EXCEPTION_LIST_ITEM_URL}?item_id=${exceptionItemBody.item_id}`) + .set('kbn-xsrf', 'true') + .expect(200); + + expect(exceptionItem.comments).to.eql([ + { + comment: 'this exception item rocks', + created_at: `${exceptionItem.comments[0].created_at}`, + created_by: 'soc_manager', + id: `${exceptionItem.comments[0].id}`, + }, + ]); + + await createRule(supertest, log, { + ...getSimpleRule(), + exceptions_list: [ + { + id: exceptionBody.id, + list_id: exceptionBody.list_id, + type: exceptionBody.type, + namespace_type: exceptionBody.namespace_type, + }, + ], + }); + + const { body } = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_export`) + .set('kbn-xsrf', 'true') + .send() + .expect(200) + .parse(binaryToString); + + await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_import?overwrite=true&overwrite_exceptions=true`) + .set('kbn-xsrf', 'true') + .attach('file', Buffer.from(body), 'rules.ndjson') + .expect(200); + + const { body: exceptionItemFind2 } = await supertest + .get(`${EXCEPTION_LIST_ITEM_URL}?item_id=${exceptionItemBody.item_id}`) + .set('kbn-xsrf', 'true') + .expect(200); + + // NOTE: Existing comment is uploaded successfully + // however, the meta now reflects who imported it, + // not who created the initial comment + expect(exceptionItemFind2.comments).to.eql([ + { + comment: 'this exception item rocks', + created_at: `${exceptionItemFind2.comments[0].created_at}`, + created_by: 'elastic', + id: `${exceptionItemFind2.comments[0].id}`, + }, + ]); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts index 81e0374b96738..ab509a7cba825 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; +import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; import { getCreateExceptionListMinimalSchemaMock } from '../../../../plugins/lists/common/schemas/request/create_exception_list_schema.mock'; import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; @@ -831,7 +831,33 @@ export default ({ getService }: FtrProviderContext): void => { type: 'detection', namespace_type: 'single', }, - getImportExceptionsListItemSchemaMock('test_item_id', 'i_exist'), + { + description: 'some description', + entries: [ + { + entries: [ + { + field: 'nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + field: 'some.parentField', + type: 'nested', + }, + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + item_id: 'item_id_1', + list_id: 'i_exist', + name: 'Query with a rule id', + type: 'simple', + }, ]) ), 'rules.ndjson' @@ -871,6 +897,135 @@ export default ({ getService }: FtrProviderContext): void => { exceptions_success_count: 2, }); }); + + it('should resolve exception references that include comments', async () => { + // So importing a rule that references an exception list + // Keep in mind, no exception lists or rules exist yet + const simpleRule: ReturnType = { + ...getSimpleRule('rule-1'), + exceptions_list: [ + { + id: 'abc', + list_id: 'i_exist', + type: 'detection', + namespace_type: 'single', + }, + ], + }; + + // Importing the "simpleRule", along with the exception list + // it's referencing and the list's item + const { body } = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach( + 'file', + Buffer.from( + toNdJsonString([ + simpleRule, + { + ...getImportExceptionsListSchemaMock('i_exist'), + id: 'abc', + type: 'detection', + namespace_type: 'single', + }, + { + comments: [ + { + comment: 'This is an exception to the rule', + created_at: '2022-02-04T02:27:40.938Z', + created_by: 'elastic', + id: '845fc456-91ff-4530-bcc1-5b7ebd2f75b5', + }, + { + comment: 'I decided to add a new comment', + }, + ], + description: 'some description', + entries: [ + { + entries: [ + { + field: 'nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + field: 'some.parentField', + type: 'nested', + }, + { + field: 'some.not.nested.field', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + item_id: 'item_id_1', + list_id: 'i_exist', + name: 'Query with a rule id', + type: 'simple', + }, + ]) + ), + 'rules.ndjson' + ) + .expect(200); + + const { body: ruleResponse } = await supertest + .get(`${DETECTION_ENGINE_RULES_URL}?rule_id=rule-1`) + .send() + .expect(200); + const bodyToCompare = removeServerGeneratedProperties(ruleResponse); + const referencedExceptionList = ruleResponse.exceptions_list[0]; + + // create an exception list + const { body: exceptionBody } = await supertest + .get( + `${EXCEPTION_LIST_URL}?list_id=${referencedExceptionList.list_id}&id=${referencedExceptionList.id}` + ) + .set('kbn-xsrf', 'true') + .expect(200); + + expect(bodyToCompare.exceptions_list).to.eql([ + { + id: exceptionBody.id, + list_id: 'i_exist', + namespace_type: 'single', + type: 'detection', + }, + ]); + + const { body: exceptionItemBody } = await supertest + .get(`${EXCEPTION_LIST_ITEM_URL}?item_id="item_id_1"`) + .set('kbn-xsrf', 'true') + .expect(200); + + expect(exceptionItemBody.comments).to.eql([ + { + comment: 'This is an exception to the rule', + created_at: `${exceptionItemBody.comments[0].created_at}`, + created_by: 'elastic', + id: `${exceptionItemBody.comments[0].id}`, + }, + { + comment: 'I decided to add a new comment', + created_at: `${exceptionItemBody.comments[1].created_at}`, + created_by: 'elastic', + id: `${exceptionItemBody.comments[1].id}`, + }, + ]); + + expect(body).to.eql({ + success: true, + success_count: 1, + errors: [], + exceptions_errors: [], + exceptions_success: true, + exceptions_success_count: 2, + }); + }); }); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts index 55b7327670631..a9bda19638041 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts @@ -33,6 +33,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./generating_signals')); loadTestFile(require.resolve('./get_prepackaged_rules_status')); loadTestFile(require.resolve('./import_rules')); + loadTestFile(require.resolve('./import_export_rules')); loadTestFile(require.resolve('./read_rules')); loadTestFile(require.resolve('./resolve_read_rules')); loadTestFile(require.resolve('./update_rules')); diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index 9cbaef3ad0fe2..496faa3c5e421 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -1043,8 +1043,8 @@ export const countDownTest = async ( * and error about the race condition. * rule a second attempt. It only re-tries adding the rule if it encounters a conflict once. * @param supertest The supertest deps - * @param rule The rule to create * @param log The tooling logger + * @param rule The rule to create */ export const createRule = async ( supertest: SuperTest.SuperTest, From 680ef034834d9c55ec1a9abb789f0fb0677db698 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Wed, 16 Feb 2022 10:00:39 -0600 Subject: [PATCH 009/104] Remove ts refs build from bootstrap (#125314) Co-authored-by: Tyler Smalley Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-pm/dist/index.js | 7 ------- packages/kbn-pm/src/commands/bootstrap.ts | 10 ---------- 2 files changed, 17 deletions(-) diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 607afa266da83..d390966a6a52f 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -8987,13 +8987,6 @@ const BootstrapCommand = { }, { prefix: '[vscode]', debug: false - }); - await Object(_utils_child_process__WEBPACK_IMPORTED_MODULE_3__["spawnStreaming"])(process.execPath, ['scripts/build_ts_refs', '--ignore-type-failures'], { - cwd: kbn.getAbsolute(), - env: process.env - }, { - prefix: '[ts refs]', - debug: false }); // send timings await reporter.timings({ diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index e7b8cad7ebc16..0b3141ab9a5a9 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -137,16 +137,6 @@ export const BootstrapCommand: ICommand = { { prefix: '[vscode]', debug: false } ); - await spawnStreaming( - process.execPath, - ['scripts/build_ts_refs', '--ignore-type-failures'], - { - cwd: kbn.getAbsolute(), - env: process.env, - }, - { prefix: '[ts refs]', debug: false } - ); - // send timings await reporter.timings({ upstreamBranch: kbn.kibanaProject.json.branch, From 4319ea80a430625213b1eff468b20da6ecb5a732 Mon Sep 17 00:00:00 2001 From: Lee Drengenberg Date: Wed, 16 Feb 2022 10:02:44 -0600 Subject: [PATCH 010/104] [Archive Migration] replace es_archive with kbn_archive invalid_scripted_field.json (#125321) * remove es_archive with kbn_archive invalid_scripted_field.json * remove unused es_archive files * replace another usage of es_archives/invalid_scripted_field * clear any existing index patterns before loading our new one * remove .only Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- test/functional/apps/discover/_errors.ts | 8 +- .../invalid_scripted_field/data.json.gz | Bin 956 -> 0 bytes .../invalid_scripted_field/mappings.json | 212 ------------------ .../kbn_archiver/invalid_scripted_field.json | 16 ++ .../apps/discover/error_handling.ts | 7 +- .../invalid_scripted_field/data.json.gz | Bin 956 -> 0 bytes .../invalid_scripted_field/mappings.json | 212 ------------------ 7 files changed, 27 insertions(+), 428 deletions(-) delete mode 100644 test/functional/fixtures/es_archiver/invalid_scripted_field/data.json.gz delete mode 100644 test/functional/fixtures/es_archiver/invalid_scripted_field/mappings.json create mode 100644 test/functional/fixtures/kbn_archiver/invalid_scripted_field.json delete mode 100644 x-pack/test/functional/es_archives/invalid_scripted_field/data.json.gz delete mode 100644 x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json diff --git a/test/functional/apps/discover/_errors.ts b/test/functional/apps/discover/_errors.ts index b252cbf5f0824..327f39ee0dec4 100644 --- a/test/functional/apps/discover/_errors.ts +++ b/test/functional/apps/discover/_errors.ts @@ -11,6 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); const toasts = getService('toasts'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'header', 'discover', 'timePicker']); @@ -18,13 +19,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('errors', function describeIndexTests() { before(async function () { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); - await esArchiver.load('test/functional/fixtures/es_archiver/invalid_scripted_field'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/invalid_scripted_field' + ); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); }); after(async function () { - await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); describe('invalid scripted field error', () => { diff --git a/test/functional/fixtures/es_archiver/invalid_scripted_field/data.json.gz b/test/functional/fixtures/es_archiver/invalid_scripted_field/data.json.gz deleted file mode 100644 index 380dd6049179a59865b91aef55ba5836c37dcea7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 956 zcmV;t14H~DiwFP!000026V;nRPunmQ$M1ZKD#wXNP0MJ>Y0@U7T{ulUY)sLs{gPNX zc4j*Rg!t~W(}XsxASz&eJyfcn9s8HRpP!vLzB?L?B6nM3l#U{e?T_Da_191 zDR{_bTIHfh=kX+-j6v2VByH(XKykbYW#TKb1O>g_>c+5jMWeow4U4xe8zK2cQ+ey+ zNf6h3i$+1^NNway4tv^J(2<-Bp?|6686 z?KSer9HhlyLNKg^r3@E3(*zq7g~0+`XYGp`1b%LG^+mJqK_J`b-5+lwiVa-9BUNYJ z1{Ja%F*ztKA&CMGEq#RVH3wBaBnl&HA3T}h`;lf#XJzf6q=RFbHjjq8YN{ogopE~O z>zp}Tg|Q*grg0BQD-I$(=3`-Kk4o@qaVQ0!<*h^eCJy}uFiZ+Bk9ZUZyYzo%!5fFl z3a#ik&jS)A2P#mO5Y&?r%1G@1^UG9o6EH>M0WQycFt+P{3(%DD_eWtP~1kO-Q6Q6Gf#A zR8&Gxg_Sn9bZ8vJzCuH$#{!T+32ifEygN`e7EPQBW8KP54^F~1w*7fmUDmYR-C&Le z$vAuG=byE5;T;4RCz!;v(p=;Mc^2M6(s%*+1ZmwYrLg58pju>()T@K%IVsJePmnq& z$gAlY2`j0K)IaOD%~E#FAtr4-MMY}!?+L&I&@e4g6s03CWyg64ie3xuO8SDfn6&k@ z!eK^h75)q)Z7rQ}lC+L3AaM=fcYpQu5_&A!3N}Vk7SQ7n*3Vsw@P$;$z;LoEZbBY_ zmWQw~-@!)l zYjS1Tthc>LLb$iEe+xoM?0VxZz61XiZ5)3J4tE~tFZ|7ggFNd~7sFzHxf8ObE&C|b diff --git a/test/functional/fixtures/es_archiver/invalid_scripted_field/mappings.json b/test/functional/fixtures/es_archiver/invalid_scripted_field/mappings.json deleted file mode 100644 index 0d41e0ce86c14..0000000000000 --- a/test/functional/fixtures/es_archiver/invalid_scripted_field/mappings.json +++ /dev/null @@ -1,212 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana": {} - }, - "index": ".kibana_1", - "mappings": { - "dynamic": "strict", - "properties": { - "config": { - "dynamic": "true", - "properties": { - "buildNum": { - "type": "keyword" - }, - "defaultIndex": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "dashboard": { - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "optionsJSON": { - "type": "text" - }, - "panelsJSON": { - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "type": "keyword" - }, - "pause": { - "type": "boolean" - }, - "section": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "timeFrom": { - "type": "keyword" - }, - "timeRestore": { - "type": "boolean" - }, - "timeTo": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "index-pattern": { - "properties": { - "fieldFormatMap": { - "type": "text" - }, - "fields": { - "type": "text" - }, - "intervalName": { - "type": "keyword" - }, - "notExpandable": { - "type": "boolean" - }, - "sourceFilters": { - "type": "text" - }, - "timeFieldName": { - "type": "keyword" - }, - "title": { - "type": "text" - } - } - }, - "search": { - "properties": { - "columns": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "sort": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "server": { - "properties": { - "uuid": { - "type": "keyword" - } - } - }, - "type": { - "type": "keyword" - }, - "updated_at": { - "type": "date" - }, - "url": { - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchId": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } - } - } - }, - "settings": { - "index": { - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} \ No newline at end of file diff --git a/test/functional/fixtures/kbn_archiver/invalid_scripted_field.json b/test/functional/fixtures/kbn_archiver/invalid_scripted_field.json new file mode 100644 index 0000000000000..23abe20855e3e --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/invalid_scripted_field.json @@ -0,0 +1,16 @@ +{ + "attributes": { + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"invalid_scripted_field\",\"type\":\"number\",\"count\":0,\"scripted\":true,\"script\":\"invalid\",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]", + "timeFieldName": "@timestamp", + "title": "log*" + }, + "coreMigrationVersion": "7.17.1", + "id": "18ea0c30-2d77-11e8-93f2-6f8a391f33ef", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2018-03-22T02:17:11.427Z", + "version": "WzMsMl0=" +} \ No newline at end of file diff --git a/x-pack/test/functional/apps/discover/error_handling.ts b/x-pack/test/functional/apps/discover/error_handling.ts index 19cedc8ecb555..194a9a592c1c2 100644 --- a/x-pack/test/functional/apps/discover/error_handling.ts +++ b/x-pack/test/functional/apps/discover/error_handling.ts @@ -10,19 +10,22 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); const toasts = getService('toasts'); const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); describe('errors', function describeIndexTests() { before(async function () { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); - await esArchiver.load('x-pack/test/functional/es_archives/invalid_scripted_field'); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/invalid_scripted_field' + ); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); }); after(async function () { - await esArchiver.unload('x-pack/test/functional/es_archives/invalid_scripted_field'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); // this is the same test as in OSS but it catches different error message issue in different licences diff --git a/x-pack/test/functional/es_archives/invalid_scripted_field/data.json.gz b/x-pack/test/functional/es_archives/invalid_scripted_field/data.json.gz deleted file mode 100644 index 380dd6049179a59865b91aef55ba5836c37dcea7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 956 zcmV;t14H~DiwFP!000026V;nRPunmQ$M1ZKD#wXNP0MJ>Y0@U7T{ulUY)sLs{gPNX zc4j*Rg!t~W(}XsxASz&eJyfcn9s8HRpP!vLzB?L?B6nM3l#U{e?T_Da_191 zDR{_bTIHfh=kX+-j6v2VByH(XKykbYW#TKb1O>g_>c+5jMWeow4U4xe8zK2cQ+ey+ zNf6h3i$+1^NNway4tv^J(2<-Bp?|6686 z?KSer9HhlyLNKg^r3@E3(*zq7g~0+`XYGp`1b%LG^+mJqK_J`b-5+lwiVa-9BUNYJ z1{Ja%F*ztKA&CMGEq#RVH3wBaBnl&HA3T}h`;lf#XJzf6q=RFbHjjq8YN{ogopE~O z>zp}Tg|Q*grg0BQD-I$(=3`-Kk4o@qaVQ0!<*h^eCJy}uFiZ+Bk9ZUZyYzo%!5fFl z3a#ik&jS)A2P#mO5Y&?r%1G@1^UG9o6EH>M0WQycFt+P{3(%DD_eWtP~1kO-Q6Q6Gf#A zR8&Gxg_Sn9bZ8vJzCuH$#{!T+32ifEygN`e7EPQBW8KP54^F~1w*7fmUDmYR-C&Le z$vAuG=byE5;T;4RCz!;v(p=;Mc^2M6(s%*+1ZmwYrLg58pju>()T@K%IVsJePmnq& z$gAlY2`j0K)IaOD%~E#FAtr4-MMY}!?+L&I&@e4g6s03CWyg64ie3xuO8SDfn6&k@ z!eK^h75)q)Z7rQ}lC+L3AaM=fcYpQu5_&A!3N}Vk7SQ7n*3Vsw@P$;$z;LoEZbBY_ zmWQw~-@!)l zYjS1Tthc>LLb$iEe+xoM?0VxZz61XiZ5)3J4tE~tFZ|7ggFNd~7sFzHxf8ObE&C|b diff --git a/x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json b/x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json deleted file mode 100644 index 0d41e0ce86c14..0000000000000 --- a/x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json +++ /dev/null @@ -1,212 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana": {} - }, - "index": ".kibana_1", - "mappings": { - "dynamic": "strict", - "properties": { - "config": { - "dynamic": "true", - "properties": { - "buildNum": { - "type": "keyword" - }, - "defaultIndex": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "dashboard": { - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "optionsJSON": { - "type": "text" - }, - "panelsJSON": { - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "type": "keyword" - }, - "pause": { - "type": "boolean" - }, - "section": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "timeFrom": { - "type": "keyword" - }, - "timeRestore": { - "type": "boolean" - }, - "timeTo": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "index-pattern": { - "properties": { - "fieldFormatMap": { - "type": "text" - }, - "fields": { - "type": "text" - }, - "intervalName": { - "type": "keyword" - }, - "notExpandable": { - "type": "boolean" - }, - "sourceFilters": { - "type": "text" - }, - "timeFieldName": { - "type": "keyword" - }, - "title": { - "type": "text" - } - } - }, - "search": { - "properties": { - "columns": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "sort": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "server": { - "properties": { - "uuid": { - "type": "keyword" - } - } - }, - "type": { - "type": "keyword" - }, - "updated_at": { - "type": "date" - }, - "url": { - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchId": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } - } - } - }, - "settings": { - "index": { - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} \ No newline at end of file From 68f475f0edfd75a58cdf37c539a5ff08124986a9 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 16 Feb 2022 17:08:59 +0100 Subject: [PATCH 011/104] retry clicking (#125768) --- test/functional/services/inspector.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/functional/services/inspector.ts b/test/functional/services/inspector.ts index 753d9b7b0b85e..b8dec2a2092fb 100644 --- a/test/functional/services/inspector.ts +++ b/test/functional/services/inspector.ts @@ -195,8 +195,12 @@ export class InspectorService extends FtrService { */ public async openInspectorView(viewId: string): Promise { this.log.debug(`Open Inspector view ${viewId}`); - await this.testSubjects.click('inspectorViewChooser'); - await this.testSubjects.click(viewId); + await this.retry.try(async () => { + await this.testSubjects.click('inspectorViewChooser'); + // check whether popover menu opens, if not, fail and retry opening + await this.testSubjects.existOrFail(viewId, { timeout: 2000 }); + await this.testSubjects.click(viewId); + }); } /** From 8757e965fcc0e5cee96fa8c1be8627b9d3c21966 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Wed, 16 Feb 2022 10:14:42 -0600 Subject: [PATCH 012/104] Revert "Remove ts refs build from bootstrap (#125314)" This reverts commit 680ef034834d9c55ec1a9abb789f0fb0677db698. --- packages/kbn-pm/dist/index.js | 7 +++++++ packages/kbn-pm/src/commands/bootstrap.ts | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index d390966a6a52f..607afa266da83 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -8987,6 +8987,13 @@ const BootstrapCommand = { }, { prefix: '[vscode]', debug: false + }); + await Object(_utils_child_process__WEBPACK_IMPORTED_MODULE_3__["spawnStreaming"])(process.execPath, ['scripts/build_ts_refs', '--ignore-type-failures'], { + cwd: kbn.getAbsolute(), + env: process.env + }, { + prefix: '[ts refs]', + debug: false }); // send timings await reporter.timings({ diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index 0b3141ab9a5a9..e7b8cad7ebc16 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -137,6 +137,16 @@ export const BootstrapCommand: ICommand = { { prefix: '[vscode]', debug: false } ); + await spawnStreaming( + process.execPath, + ['scripts/build_ts_refs', '--ignore-type-failures'], + { + cwd: kbn.getAbsolute(), + env: process.env, + }, + { prefix: '[ts refs]', debug: false } + ); + // send timings await reporter.timings({ upstreamBranch: kbn.kibanaProject.json.branch, From 2e3257c90cac9ed60b302a64689620e25eacd3dc Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Wed, 16 Feb 2022 11:25:34 -0500 Subject: [PATCH 013/104] [Security Solution] Change manifest check in policy test to improve test (#125784) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../security_solution_endpoint/apps/endpoint/policy_details.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts index 72b64f78319ef..3f057d198a25c 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts @@ -493,7 +493,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { version: policyInfo.packageInfo.version, }, }, - artifact_manifest: agentFullPolicy.inputs[0].artifact_manifest, + artifact_manifest: agentFullPolicyUpdated.inputs[0].artifact_manifest, }), ]); }); From 37dfc22c1a52931bd7bc0426c9fc13cd43250d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Wed, 16 Feb 2022 17:45:32 +0100 Subject: [PATCH 014/104] [Snapshot & Restore] Fix repository types on Cloud (#125656) * [Snapshot & Restore] Fix repository types on Cloud * [Snapshot & Restore] Move repo types tests into `on-prem` describe block Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../snapshot_restore/common/constants.ts | 9 +- .../server/routes/api/repositories.test.ts | 101 ++++++++++-------- .../server/routes/api/repositories.ts | 13 ++- .../apis/management/snapshot_restore/index.ts | 1 + .../snapshot_restore/repositories.ts | 34 ++++++ 5 files changed, 107 insertions(+), 51 deletions(-) create mode 100644 x-pack/test/api_integration/apis/management/snapshot_restore/repositories.ts diff --git a/x-pack/plugins/snapshot_restore/common/constants.ts b/x-pack/plugins/snapshot_restore/common/constants.ts index c4b64bb9395f8..d8b159fd01e96 100644 --- a/x-pack/plugins/snapshot_restore/common/constants.ts +++ b/x-pack/plugins/snapshot_restore/common/constants.ts @@ -35,12 +35,15 @@ export enum REPOSITORY_TYPES { } // Deliberately do not include `source` as a default repository since we treat it as a flag -export const DEFAULT_REPOSITORY_TYPES: RepositoryType[] = [ +export const ON_PREM_REPOSITORY_TYPES: RepositoryType[] = [ + REPOSITORY_TYPES.fs, + REPOSITORY_TYPES.url, +]; + +export const MODULE_REPOSITORY_TYPES: RepositoryType[] = [ REPOSITORY_TYPES.azure, REPOSITORY_TYPES.gcs, REPOSITORY_TYPES.s3, - REPOSITORY_TYPES.fs, - REPOSITORY_TYPES.url, ]; export const PLUGIN_REPOSITORY_TYPES: RepositoryType[] = [REPOSITORY_TYPES.hdfs]; diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/repositories.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/repositories.test.ts index 844be90f9b842..f29a84beaecf8 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/repositories.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/repositories.test.ts @@ -5,7 +5,11 @@ * 2.0. */ -import { DEFAULT_REPOSITORY_TYPES, REPOSITORY_PLUGINS_MAP } from '../../../common'; +import { + ON_PREM_REPOSITORY_TYPES, + MODULE_REPOSITORY_TYPES, + REPOSITORY_PLUGINS_MAP, +} from '../../../common'; import { addBasePath } from '../helpers'; import { registerRepositoriesRoutes } from './repositories'; import { RouterMock, routeDependencies, RequestMock } from '../../test/helpers'; @@ -253,52 +257,59 @@ describe('[Snapshot and Restore API Routes] Repositories', () => { path: addBasePath('repository_types'), }; - it('returns default types if no repository plugins returned from ES', async () => { - nodesInfoFn.mockResolvedValue({ nodes: { testNodeId: { plugins: [] } } }); - - const expectedResponse = [...DEFAULT_REPOSITORY_TYPES]; - await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); - }); - - it('returns default types with any repository plugins returned from ES', async () => { - const pluginNames = Object.keys(REPOSITORY_PLUGINS_MAP); - const pluginTypes = Object.entries(REPOSITORY_PLUGINS_MAP).map(([key, value]) => value); - - const mockEsResponse = { - nodes: { testNodeId: { plugins: [...pluginNames.map((key) => ({ name: key }))] } }, - }; - nodesInfoFn.mockResolvedValue(mockEsResponse); - - const expectedResponse = [...DEFAULT_REPOSITORY_TYPES, ...pluginTypes]; - await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); - }); - - it(`doesn't return non-repository plugins returned from ES`, async () => { - const pluginNames = ['foo-plugin', 'bar-plugin']; - const mockEsResponse = { - nodes: { testNodeId: { plugins: [...pluginNames.map((key) => ({ name: key }))] } }, - }; - nodesInfoFn.mockResolvedValue(mockEsResponse); - - const expectedResponse = [...DEFAULT_REPOSITORY_TYPES]; - - await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); - }); - - it(`doesn't return repository plugins that are not installed on all nodes`, async () => { - const dataNodePlugins = ['repository-hdfs']; - const masterNodePlugins: string[] = []; - const mockEsResponse = { - nodes: { - dataNode: { plugins: [...dataNodePlugins.map((key) => ({ name: key }))] }, - masterNode: { plugins: [...masterNodePlugins.map((key) => ({ name: key }))] }, - }, - }; - nodesInfoFn.mockResolvedValue(mockEsResponse); + // TODO add Cloud specific tests for repo types + describe('on prem', () => { + it('returns module types and on-prem types if no repository plugins returned from ES', async () => { + nodesInfoFn.mockResolvedValue({ nodes: { testNodeId: { plugins: [] } } }); + + const expectedResponse = [...MODULE_REPOSITORY_TYPES, ...ON_PREM_REPOSITORY_TYPES]; + await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); + }); + + it('returns module types and on-prem types with any repository plugins returned from ES', async () => { + const pluginNames = Object.keys(REPOSITORY_PLUGINS_MAP); + const pluginTypes = Object.entries(REPOSITORY_PLUGINS_MAP).map(([key, value]) => value); + + const mockEsResponse = { + nodes: { testNodeId: { plugins: [...pluginNames.map((key) => ({ name: key }))] } }, + }; + nodesInfoFn.mockResolvedValue(mockEsResponse); + + const expectedResponse = [ + ...MODULE_REPOSITORY_TYPES, + ...ON_PREM_REPOSITORY_TYPES, + ...pluginTypes, + ]; + await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); + }); + + it(`doesn't return non-repository plugins returned from ES`, async () => { + const pluginNames = ['foo-plugin', 'bar-plugin']; + const mockEsResponse = { + nodes: { testNodeId: { plugins: [...pluginNames.map((key) => ({ name: key }))] } }, + }; + nodesInfoFn.mockResolvedValue(mockEsResponse); + + const expectedResponse = [...MODULE_REPOSITORY_TYPES, ...ON_PREM_REPOSITORY_TYPES]; + + await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); + }); + + it(`doesn't return repository plugins that are not installed on all nodes`, async () => { + const dataNodePlugins = ['repository-hdfs']; + const masterNodePlugins: string[] = []; + const mockEsResponse = { + nodes: { + dataNode: { plugins: [...dataNodePlugins.map((key) => ({ name: key }))] }, + masterNode: { plugins: [...masterNodePlugins.map((key) => ({ name: key }))] }, + }, + }; + nodesInfoFn.mockResolvedValue(mockEsResponse); - const expectedResponse = [...DEFAULT_REPOSITORY_TYPES]; + const expectedResponse = [...MODULE_REPOSITORY_TYPES, ...ON_PREM_REPOSITORY_TYPES]; - await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); + await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); + }); }); it('should throw if ES error', async () => { diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts b/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts index 22c4d4a2b3e91..4666870133f1f 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts @@ -12,7 +12,11 @@ import type { PluginStats, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { DEFAULT_REPOSITORY_TYPES, REPOSITORY_PLUGINS_MAP } from '../../../common'; +import { + ON_PREM_REPOSITORY_TYPES, + REPOSITORY_PLUGINS_MAP, + MODULE_REPOSITORY_TYPES, +} from '../../../common'; import { Repository, RepositoryType } from '../../../common/types'; import { RouteDependencies } from '../../types'; import { addBasePath } from '../helpers'; @@ -154,8 +158,11 @@ export function registerRepositoriesRoutes({ { path: addBasePath('repository_types'), validate: false }, license.guardApiRoute(async (ctx, req, res) => { const { client: clusterClient } = ctx.core.elasticsearch; - // In ECE/ESS, do not enable the default types - const types: RepositoryType[] = isCloudEnabled ? [] : [...DEFAULT_REPOSITORY_TYPES]; + // module repo types are available everywhere out of the box + // on-prem repo types are not available on Cloud + const types: RepositoryType[] = isCloudEnabled + ? [...MODULE_REPOSITORY_TYPES] + : [...MODULE_REPOSITORY_TYPES, ...ON_PREM_REPOSITORY_TYPES]; try { const { nodes } = await clusterClient.asCurrentUser.nodes.info({ diff --git a/x-pack/test/api_integration/apis/management/snapshot_restore/index.ts b/x-pack/test/api_integration/apis/management/snapshot_restore/index.ts index db5dbc9735e66..debfb683cd883 100644 --- a/x-pack/test/api_integration/apis/management/snapshot_restore/index.ts +++ b/x-pack/test/api_integration/apis/management/snapshot_restore/index.ts @@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('Snapshot and Restore', () => { loadTestFile(require.resolve('./policies')); loadTestFile(require.resolve('./snapshots')); + loadTestFile(require.resolve('./repositories')); }); } diff --git a/x-pack/test/api_integration/apis/management/snapshot_restore/repositories.ts b/x-pack/test/api_integration/apis/management/snapshot_restore/repositories.ts new file mode 100644 index 0000000000000..982f32faf73ce --- /dev/null +++ b/x-pack/test/api_integration/apis/management/snapshot_restore/repositories.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +const API_BASE_PATH = '/api/snapshot_restore'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const deployment = getService('deployment'); + + describe('snapshot repositories', function () { + describe('repository types', () => { + it('returns a list of default repository types', async () => { + const { body } = await supertest.get(`${API_BASE_PATH}/repository_types`).expect(200); + + const isCloud = await deployment.isCloud(); + if (isCloud) { + // on Cloud there are only module repo types + expect(body).to.eql(['azure', 'gcs', 's3']); + } else { + // on prem there are module repo types and file system and url repo types + expect(body).to.eql(['azure', 'gcs', 's3', 'fs', 'url']); + } + }); + }); + }); +} From 3dd2d75bce2939b39e72b7ef60e32392b3fad876 Mon Sep 17 00:00:00 2001 From: Josh Dover <1813008+joshdover@users.noreply.github.com> Date: Wed, 16 Feb 2022 17:50:17 +0100 Subject: [PATCH 015/104] [Fleet] Use package policy version to determine managed policy upgrades (#125788) --- .../services/managed_package_policies.test.ts | 76 ++++--------------- .../services/managed_package_policies.ts | 22 ++---- 2 files changed, 19 insertions(+), 79 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts b/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts index 7ccfeb4fe7641..af3b3ef4dfccd 100644 --- a/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts +++ b/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts @@ -7,11 +7,11 @@ import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; -import type { Installation, PackageInfo } from '../../common'; +import type { Installation } from '../../common'; import { shouldUpgradePolicies, upgradeManagedPackagePolicies } from './managed_package_policies'; import { packagePolicyService } from './package_policy'; -import { getPackageInfo, getInstallation } from './epm/packages'; +import { getInstallation } from './epm/packages'; jest.mock('./package_policy'); jest.mock('./epm/packages'); @@ -30,7 +30,6 @@ describe('upgradeManagedPackagePolicies', () => { afterEach(() => { (packagePolicyService.get as jest.Mock).mockReset(); (packagePolicyService.getUpgradeDryRunDiff as jest.Mock).mockReset(); - (getPackageInfo as jest.Mock).mockReset(); (getInstallation as jest.Mock).mockReset(); (packagePolicyService.upgrade as jest.Mock).mockReset(); }); @@ -69,17 +68,10 @@ describe('upgradeManagedPackagePolicies', () => { } ); - (getPackageInfo as jest.Mock).mockImplementationOnce( - ({ savedObjectsClient, pkgName, pkgVersion }) => ({ - name: pkgName, - version: pkgVersion, - keepPoliciesUpToDate: false, - }) - ); - (getInstallation as jest.Mock).mockResolvedValueOnce({ id: 'test-installation', version: '0.0.1', + keep_policies_up_to_date: false, }); await upgradeManagedPackagePolicies(soClient, esClient, ['non-managed-package-id']); @@ -121,17 +113,10 @@ describe('upgradeManagedPackagePolicies', () => { } ); - (getPackageInfo as jest.Mock).mockImplementationOnce( - ({ savedObjectsClient, pkgName, pkgVersion }) => ({ - name: pkgName, - version: pkgVersion, - keepPoliciesUpToDate: true, - }) - ); - (getInstallation as jest.Mock).mockResolvedValueOnce({ id: 'test-installation', version: '1.0.0', + keep_policies_up_to_date: true, }); await upgradeManagedPackagePolicies(soClient, esClient, ['managed-package-id']); @@ -177,17 +162,10 @@ describe('upgradeManagedPackagePolicies', () => { } ); - (getPackageInfo as jest.Mock).mockImplementationOnce( - ({ savedObjectsClient, pkgName, pkgVersion }) => ({ - name: pkgName, - version: pkgVersion, - keepPoliciesUpToDate: true, - }) - ); - (getInstallation as jest.Mock).mockResolvedValueOnce({ id: 'test-installation', version: '1.0.0', + keep_policies_up_to_date: true, }); const result = await upgradeManagedPackagePolicies(soClient, esClient, [ @@ -229,19 +207,12 @@ describe('shouldUpgradePolicies', () => { describe('package policy is up-to-date', () => { describe('keep_policies_up_to_date is true', () => { it('returns false', () => { - const packageInfo = { - version: '1.0.0', - keepPoliciesUpToDate: true, - }; - const installedPackage = { version: '1.0.0', + keep_policies_up_to_date: true, }; - const result = shouldUpgradePolicies( - packageInfo as PackageInfo, - installedPackage as Installation - ); + const result = shouldUpgradePolicies('1.0.0', installedPackage as Installation); expect(result).toBe(false); }); @@ -249,19 +220,12 @@ describe('shouldUpgradePolicies', () => { describe('keep_policies_up_to_date is false', () => { it('returns false', () => { - const packageInfo = { - version: '1.0.0', - keepPoliciesUpToDate: false, - }; - const installedPackage = { version: '1.0.0', + keep_policies_up_to_date: false, }; - const result = shouldUpgradePolicies( - packageInfo as PackageInfo, - installedPackage as Installation - ); + const result = shouldUpgradePolicies('1.0.0', installedPackage as Installation); expect(result).toBe(false); }); @@ -271,19 +235,12 @@ describe('shouldUpgradePolicies', () => { describe('package policy is out-of-date', () => { describe('keep_policies_up_to_date is true', () => { it('returns true', () => { - const packageInfo = { - version: '1.0.0', - keepPoliciesUpToDate: true, - }; - const installedPackage = { version: '1.1.0', + keep_policies_up_to_date: true, }; - const result = shouldUpgradePolicies( - packageInfo as PackageInfo, - installedPackage as Installation - ); + const result = shouldUpgradePolicies('1.0.0', installedPackage as Installation); expect(result).toBe(true); }); @@ -291,19 +248,12 @@ describe('shouldUpgradePolicies', () => { describe('keep_policies_up_to_date is false', () => { it('returns false', () => { - const packageInfo = { - version: '1.0.0', - keepPoliciesUpToDate: false, - }; - const installedPackage = { version: '1.1.0', + keep_policies_up_to_date: false, }; - const result = shouldUpgradePolicies( - packageInfo as PackageInfo, - installedPackage as Installation - ); + const result = shouldUpgradePolicies('1.0.0', installedPackage as Installation); expect(result).toBe(false); }); diff --git a/x-pack/plugins/fleet/server/services/managed_package_policies.ts b/x-pack/plugins/fleet/server/services/managed_package_policies.ts index c702cfe96d986..77715ad488feb 100644 --- a/x-pack/plugins/fleet/server/services/managed_package_policies.ts +++ b/x-pack/plugins/fleet/server/services/managed_package_policies.ts @@ -8,14 +8,10 @@ import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import semverGte from 'semver/functions/gte'; -import type { - Installation, - PackageInfo, - UpgradePackagePolicyDryRunResponseItem, -} from '../../common'; +import type { Installation, UpgradePackagePolicyDryRunResponseItem } from '../../common'; import { appContextService } from './app_context'; -import { getInstallation, getPackageInfo } from './epm/packages'; +import { getInstallation } from './epm/packages'; import { packagePolicyService } from './package_policy'; export interface UpgradeManagedPackagePoliciesResult { @@ -42,12 +38,6 @@ export const upgradeManagedPackagePolicies = async ( continue; } - const packageInfo = await getPackageInfo({ - savedObjectsClient: soClient, - pkgName: packagePolicy.package.name, - pkgVersion: packagePolicy.package.version, - }); - const installedPackage = await getInstallation({ savedObjectsClient: soClient, pkgName: packagePolicy.package.name, @@ -62,7 +52,7 @@ export const upgradeManagedPackagePolicies = async ( continue; } - if (shouldUpgradePolicies(packageInfo, installedPackage)) { + if (shouldUpgradePolicies(packagePolicy.package.version, installedPackage)) { // Since upgrades don't report diffs/errors, we need to perform a dry run first in order // to notify the user of any granular policy upgrade errors that occur during Fleet's // preconfiguration check @@ -101,13 +91,13 @@ export const upgradeManagedPackagePolicies = async ( }; export function shouldUpgradePolicies( - packageInfo: PackageInfo, + packagePolicyPackageVersion: string, installedPackage: Installation ): boolean { const isPolicyVersionGteInstalledVersion = semverGte( - packageInfo.version, + packagePolicyPackageVersion, installedPackage.version ); - return !isPolicyVersionGteInstalledVersion && !!packageInfo.keepPoliciesUpToDate; + return !isPolicyVersionGteInstalledVersion && !!installedPackage.keep_policies_up_to_date; } From 82c21484b38f044ad6d2d389abca590671169766 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 16 Feb 2022 08:57:42 -0800 Subject: [PATCH 016/104] Add tooltip for Surrounding documents (#123890) Co-authored-by: Andrea Del Rio --- .../discover_grid/discover_grid_flyout.tsx | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx index 371eb014eab8f..bdf9268c73060 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx +++ b/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx @@ -15,6 +15,7 @@ import { EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, + EuiIconTip, EuiTitle, EuiButtonEmpty, EuiText, @@ -147,7 +148,8 @@ export function DiscoverGridFlyout({ {indexPattern.isTimeBased() && indexPattern.id && ( - - - {i18n.translate('discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple', { - defaultMessage: 'Surrounding documents', - })} - - + + + + {i18n.translate( + 'discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple', + { + defaultMessage: 'Surrounding documents', + } + )} + + + + + + )} {activePage !== -1 && ( From d68a0d390a34ce712815b78a97ca82d220c151b8 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Wed, 16 Feb 2022 18:03:29 +0100 Subject: [PATCH 017/104] [APM] Improve open transaction/span/error in Discover (#125431) --- docs/apm/transactions.asciidoc | 2 +- .../__snapshots__/index.test.tsx.snap | 6 +----- .../error_group_details/detail_view/index.tsx | 19 ++++++++----------- .../waterfall/span_flyout/index.tsx | 15 ++++++--------- .../transaction_action_menu/sections.test.ts | 6 +++--- .../transaction_action_menu/sections.ts | 2 +- .../transaction_action_menu.test.tsx | 2 +- .../columns/series_actions.test.tsx | 4 ++-- .../series_editor/columns/series_actions.tsx | 2 +- 9 files changed, 24 insertions(+), 34 deletions(-) diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index e7555a6c3e3d6..e8c5d6600c0bd 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -151,7 +151,7 @@ Learn more about a trace sample in the *Metadata* tab: * User - Requires additional configuration, but allows you to see which user experienced the current transaction. TIP: All of this data is stored in documents in Elasticsearch. -This means you can select "Actions - View sample document" to see the actual Elasticsearch document under the discover tab. +This means you can select "Actions - View transaction in Discover" to see the actual Elasticsearch document under the discover tab. *Trace sample logs* diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/__snapshots__/index.test.tsx.snap b/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/__snapshots__/index.test.tsx.snap index de13bf910ce0f..5f300b45de80a 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/__snapshots__/index.test.tsx.snap @@ -34,11 +34,7 @@ exports[`DetailView should render Discover button 1`] = ` } kuery="" > - - View 10 occurrences in Discover. - + View 10 occurrences in Discover. `; diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/index.tsx index 97118bf763d43..0a6b134275121 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_details/detail_view/index.tsx @@ -6,7 +6,6 @@ */ import { - EuiButtonEmpty, EuiIcon, EuiPanel, EuiSpacer, @@ -100,16 +99,14 @@ export function DetailView({ errorGroup, urlParams, kuery }: Props) { - - {i18n.translate( - 'xpack.apm.errorGroupDetails.viewOccurrencesInDiscoverButtonLabel', - { - defaultMessage: - 'View {occurrencesCount} {occurrencesCount, plural, one {occurrence} other {occurrences}} in Discover.', - values: { occurrencesCount }, - } - )} - + {i18n.translate( + 'xpack.apm.errorGroupDetails.viewOccurrencesInDiscoverButtonLabel', + { + defaultMessage: + 'View {occurrencesCount} {occurrencesCount, plural, one {occurrence} other {occurrences}} in Discover.', + values: { occurrencesCount }, + } + )} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx index 0f7a6a295601b..477098aa81d04 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx @@ -7,7 +7,6 @@ import { EuiBadge, - EuiButtonEmpty, EuiCallOut, EuiFlexGroup, EuiFlexItem, @@ -126,14 +125,12 @@ export function SpanFlyout({ - - {i18n.translate( - 'xpack.apm.transactionDetails.spanFlyout.viewSpanInDiscoverButtonLabel', - { - defaultMessage: 'View span in Discover', - } - )} - + {i18n.translate( + 'xpack.apm.transactionDetails.spanFlyout.viewSpanInDiscoverButtonLabel', + { + defaultMessage: 'View span in Discover', + } + )} diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts index bcb52f4721dd5..1d37dde6c6343 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts @@ -67,7 +67,7 @@ describe('Transaction action menu', () => { actions: [ { key: 'sampleDocument', - label: 'View sample document', + label: 'View transaction in Discover', href: 'some-basepath/app/discover#/?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-24h,to:now))&_a=(index:apm_static_index_pattern_id,interval:auto,query:(language:kuery,query:\'processor.event:"transaction" AND transaction.id:"123" AND trace.id:"123"\'))', condition: true, }, @@ -134,7 +134,7 @@ describe('Transaction action menu', () => { actions: [ { key: 'sampleDocument', - label: 'View sample document', + label: 'View transaction in Discover', href: 'some-basepath/app/discover#/?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-24h,to:now))&_a=(index:apm_static_index_pattern_id,interval:auto,query:(language:kuery,query:\'processor.event:"transaction" AND transaction.id:"123" AND trace.id:"123"\'))', condition: true, }, @@ -200,7 +200,7 @@ describe('Transaction action menu', () => { actions: [ { key: 'sampleDocument', - label: 'View sample document', + label: 'View transaction in Discover', href: 'some-basepath/app/discover#/?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-24h,to:now))&_a=(index:apm_static_index_pattern_id,interval:auto,query:(language:kuery,query:\'processor.event:"transaction" AND transaction.id:"123" AND trace.id:"123"\'))', condition: true, }, diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts index daf5cb0833b61..20c10b6d9557c 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts @@ -191,7 +191,7 @@ export const getSections = ({ label: i18n.translate( 'xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel', { - defaultMessage: 'View sample document', + defaultMessage: 'View transaction in Discover', } ), href: getDiscoverHref({ diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx index 4d82bb69ee9a5..851472cfedabe 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx @@ -74,7 +74,7 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithMinimalData ); - expect(queryByText('View sample document')).not.toBeNull(); + expect(queryByText('View transaction in Discover')).not.toBeNull(); }); it('always renders the trace logs link', async () => { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx index d855f648f5da2..3480662f13913 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx @@ -35,8 +35,8 @@ describe('SeriesActions', function () { expect(screen.getByLabelText('Series actions list')).toBeVisible(); }); - it('should display a view sample link', function () { - expect(screen.getByLabelText('View sample documents')).toBeVisible(); + it('should display a view transaction link', function () { + expect(screen.getByLabelText('View transaction in Discover')).toBeVisible(); }); it('should display a hide series link', function () { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx index 22d87e3977abc..b3430da2d35e2 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx @@ -182,7 +182,7 @@ const DELETE_SERIES_TOOLTIP_LABEL = i18n.translate( const VIEW_SAMPLE_DOCUMENTS_LABEL = i18n.translate( 'xpack.observability.seriesEditor.sampleDocuments', { - defaultMessage: 'View sample documents', + defaultMessage: 'View transaction in Discover', } ); From b8ae75b3f7e809474205661d011cad1377a85f7e Mon Sep 17 00:00:00 2001 From: Michael Dokolin Date: Wed, 16 Feb 2022 18:06:09 +0100 Subject: [PATCH 018/104] [Screenshotting] Simplify authentication headers handling (#125673) * Move stripping unsafe headers to the screenshotting plugin * Encapsulate conditional headers handling in the screenshotting plugin * Add KibanaRequest support on input --- .../reporting/common/constants/index.ts | 22 ---- .../common/get_conditional_headers.test.ts | 51 --------- .../common/get_conditional_headers.ts | 34 ------ .../common/get_custom_logo.test.ts | 16 +-- .../export_types/common/get_custom_logo.ts | 12 +- .../server/export_types/common/index.ts | 14 --- .../common/omit_blocked_headers.test.ts | 34 ------ .../common/omit_blocked_headers.ts | 25 ----- .../png/execute_job/index.test.ts | 5 +- .../export_types/png/execute_job/index.ts | 14 +-- .../export_types/png_v2/execute_job.test.ts | 5 +- .../server/export_types/png_v2/execute_job.ts | 13 +-- .../printable_pdf/execute_job/index.ts | 18 +-- .../printable_pdf_v2/execute_job.ts | 17 +-- .../server/routes/diagnostic/screenshot.ts | 17 +-- .../server/browsers/chromium/driver.ts | 106 +++++++----------- .../chromium/driver_factory/index.test.ts | 2 +- .../browsers/chromium/driver_factory/index.ts | 10 +- .../server/browsers/chromium/index.ts | 2 +- .../chromium/strip_unsafe_headers.test.ts | 37 ++++++ .../browsers/chromium/strip_unsafe_headers.ts | 40 +++++++ .../screenshotting/server/browsers/index.ts | 2 +- .../plugins/screenshotting/server/plugin.ts | 11 +- .../server/screenshots/index.test.ts | 2 +- .../server/screenshots/index.ts | 13 ++- .../server/screenshots/observable.test.ts | 6 +- .../server/screenshots/observable.ts | 8 +- .../server/screenshots/open_url.ts | 8 +- 28 files changed, 186 insertions(+), 358 deletions(-) delete mode 100644 x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.test.ts delete mode 100644 x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.ts delete mode 100644 x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.test.ts delete mode 100644 x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.ts create mode 100644 x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.test.ts create mode 100644 x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.ts diff --git a/x-pack/plugins/reporting/common/constants/index.ts b/x-pack/plugins/reporting/common/constants/index.ts index b8cf8a27d7fb4..f6b7efabe6449 100644 --- a/x-pack/plugins/reporting/common/constants/index.ts +++ b/x-pack/plugins/reporting/common/constants/index.ts @@ -32,28 +32,6 @@ export const ALLOWED_JOB_CONTENT_TYPES = [ 'text/plain', ]; -// See: -// https://github.com/chromium/chromium/blob/3611052c055897e5ebbc5b73ea295092e0c20141/services/network/public/cpp/header_util_unittest.cc#L50 -// For a list of headers that chromium doesn't like -export const KBN_SCREENSHOT_HEADER_BLOCK_LIST = [ - 'accept-encoding', - 'connection', - 'content-length', - 'content-type', - 'host', - 'referer', - // `Transfer-Encoding` is hop-by-hop header that is meaningful - // only for a single transport-level connection, and shouldn't - // be stored by caches or forwarded by proxies. - 'transfer-encoding', - 'trailer', - 'te', - 'upgrade', - 'keep-alive', -]; - -export const KBN_SCREENSHOT_HEADER_BLOCK_LIST_STARTS_WITH_PATTERN = ['proxy-']; - export const UI_SETTINGS_SEARCH_INCLUDE_FROZEN = 'search:includeFrozen'; export const UI_SETTINGS_CUSTOM_PDF_LOGO = 'xpackReporting:customPdfLogo'; export const UI_SETTINGS_CSV_SEPARATOR = 'csv:separator'; diff --git a/x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.test.ts b/x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.test.ts deleted file mode 100644 index 73b5875717d32..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.test.ts +++ /dev/null @@ -1,51 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ReportingConfig } from '../../'; -import { createMockConfig, createMockConfigSchema } from '../../test_helpers'; -import { getConditionalHeaders } from './'; - -let mockConfig: ReportingConfig; - -beforeEach(async () => { - const reportingConfig = { kibanaServer: { hostname: 'custom-hostname' } }; - const mockSchema = createMockConfigSchema(reportingConfig); - mockConfig = createMockConfig(mockSchema); -}); - -describe('conditions', () => { - test(`uses hostname from reporting config if set`, async () => { - const permittedHeaders = { - foo: 'bar', - baz: 'quix', - }; - - const conditionalHeaders = getConditionalHeaders(mockConfig, permittedHeaders); - - expect(conditionalHeaders.conditions.hostname).toEqual( - mockConfig.get('kibanaServer', 'hostname') - ); - expect(conditionalHeaders.conditions.port).toEqual(mockConfig.get('kibanaServer', 'port')); - expect(conditionalHeaders.conditions.protocol).toEqual( - mockConfig.get('kibanaServer', 'protocol') - ); - expect(conditionalHeaders.conditions.basePath).toEqual( - mockConfig.kbnConfig.get('server', 'basePath') - ); - }); -}); - -describe('config formatting', () => { - test(`lowercases kibanaServer.hostname`, async () => { - const reportingConfig = { kibanaServer: { hostname: 'GREAT-HOSTNAME' } }; - const mockSchema = createMockConfigSchema(reportingConfig); - mockConfig = createMockConfig(mockSchema); - - const conditionalHeaders = getConditionalHeaders(mockConfig, {}); - expect(conditionalHeaders.conditions.hostname).toEqual('great-hostname'); - }); -}); diff --git a/x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.ts b/x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.ts deleted file mode 100644 index 262d9733cb16a..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/common/get_conditional_headers.ts +++ /dev/null @@ -1,34 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ReportingConfig } from '../../'; -import { ConditionalHeaders } from './'; - -export const getConditionalHeaders = ( - config: ReportingConfig, - filteredHeaders: Record -) => { - const { kbnConfig } = config; - const [hostname, port, basePath, protocol] = [ - config.get('kibanaServer', 'hostname'), - config.get('kibanaServer', 'port'), - kbnConfig.get('server', 'basePath'), - config.get('kibanaServer', 'protocol'), - ] as [string, number, string, string]; - - const conditionalHeaders: ConditionalHeaders = { - headers: filteredHeaders, - conditions: { - hostname: hostname ? hostname.toLowerCase() : hostname, - port, - basePath, - protocol, - }, - }; - - return conditionalHeaders; -}; diff --git a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts b/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts index e21b7404f5ed5..f5675b50cfddd 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts +++ b/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts @@ -7,12 +7,10 @@ import { ReportingCore } from '../..'; import { - createMockConfig, createMockConfigSchema, createMockLevelLogger, createMockReportingCore, } from '../../test_helpers'; -import { getConditionalHeaders } from '.'; import { getCustomLogo } from './get_custom_logo'; let mockReportingPlugin: ReportingCore; @@ -24,7 +22,7 @@ beforeEach(async () => { }); test(`gets logo from uiSettings`, async () => { - const permittedHeaders = { + const headers = { foo: 'bar', baz: 'quix', }; @@ -40,17 +38,7 @@ test(`gets logo from uiSettings`, async () => { get: mockGet, }); - const conditionalHeaders = getConditionalHeaders( - createMockConfig(createMockConfigSchema()), - permittedHeaders - ); - - const { logo } = await getCustomLogo( - mockReportingPlugin, - conditionalHeaders, - 'spaceyMcSpaceIdFace', - logger - ); + const { logo } = await getCustomLogo(mockReportingPlugin, headers, 'spaceyMcSpaceIdFace', logger); expect(mockGet).toBeCalledWith('xpackReporting:customPdfLogo'); expect(logo).toBe('purple pony'); diff --git a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts b/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts index 983f6f41af8d9..fcabd34a642c8 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts +++ b/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts @@ -5,25 +5,21 @@ * 2.0. */ +import type { Headers } from 'src/core/server'; import { ReportingCore } from '../../'; import { UI_SETTINGS_CUSTOM_PDF_LOGO } from '../../../common/constants'; import { LevelLogger } from '../../lib'; -import { ConditionalHeaders } from '../common'; export const getCustomLogo = async ( reporting: ReportingCore, - conditionalHeaders: ConditionalHeaders, + headers: Headers, spaceId: string | undefined, logger: LevelLogger ) => { - const fakeRequest = reporting.getFakeRequest( - { headers: conditionalHeaders.headers }, - spaceId, - logger - ); + const fakeRequest = reporting.getFakeRequest({ headers }, spaceId, logger); const uiSettingsClient = await reporting.getUiSettingsClient(fakeRequest, logger); const logo: string = await uiSettingsClient.get(UI_SETTINGS_CUSTOM_PDF_LOGO); // continue the pipeline - return { conditionalHeaders, logo }; + return { headers, logo }; }; diff --git a/x-pack/plugins/reporting/server/export_types/common/index.ts b/x-pack/plugins/reporting/server/export_types/common/index.ts index 501de48e0450a..c9589d5262059 100644 --- a/x-pack/plugins/reporting/server/export_types/common/index.ts +++ b/x-pack/plugins/reporting/server/export_types/common/index.ts @@ -6,9 +6,7 @@ */ export { decryptJobHeaders } from './decrypt_job_headers'; -export { getConditionalHeaders } from './get_conditional_headers'; export { getFullUrls } from './get_full_urls'; -export { omitBlockedHeaders } from './omit_blocked_headers'; export { validateUrls } from './validate_urls'; export { generatePngObservable } from './generate_png'; export { getCustomLogo } from './get_custom_logo'; @@ -17,15 +15,3 @@ export interface TimeRangeParams { min?: Date | string | number | null; max?: Date | string | number | null; } - -export interface ConditionalHeadersConditions { - protocol: string; - hostname: string; - port: number; - basePath: string; -} - -export interface ConditionalHeaders { - headers: Record; - conditions: ConditionalHeadersConditions; -} diff --git a/x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.test.ts b/x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.test.ts deleted file mode 100644 index e7f4f984c2054..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.test.ts +++ /dev/null @@ -1,34 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { omitBlockedHeaders } from './index'; - -test(`omits blocked headers`, async () => { - const permittedHeaders = { - foo: 'bar', - baz: 'quix', - }; - - const blockedHeaders = { - 'accept-encoding': '', - connection: 'upgrade', - 'content-length': '', - 'content-type': '', - host: '', - 'transfer-encoding': '', - 'proxy-connection': 'bananas', - 'proxy-authorization': 'some-base64-encoded-thing', - trailer: 's are for trucks', - }; - - const filteredHeaders = omitBlockedHeaders({ - ...permittedHeaders, - ...blockedHeaders, - }); - - expect(filteredHeaders).toEqual(permittedHeaders); -}); diff --git a/x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.ts b/x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.ts deleted file mode 100644 index c2ad8fdb507f2..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/common/omit_blocked_headers.ts +++ /dev/null @@ -1,25 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { omitBy } from 'lodash'; -import { - KBN_SCREENSHOT_HEADER_BLOCK_LIST, - KBN_SCREENSHOT_HEADER_BLOCK_LIST_STARTS_WITH_PATTERN, -} from '../../../common/constants'; - -export const omitBlockedHeaders = (decryptedHeaders: Record) => { - const filteredHeaders: Record = omitBy( - decryptedHeaders, - (_value, header: string) => - header && - (KBN_SCREENSHOT_HEADER_BLOCK_LIST.includes(header) || - KBN_SCREENSHOT_HEADER_BLOCK_LIST_STARTS_WITH_PATTERN.some((pattern) => - header?.startsWith(pattern) - )) - ); - return filteredHeaders; -}; diff --git a/x-pack/plugins/reporting/server/export_types/png/execute_job/index.test.ts b/x-pack/plugins/reporting/server/export_types/png/execute_job/index.test.ts index bbdab4d75b7bf..9069ec63a8825 100644 --- a/x-pack/plugins/reporting/server/export_types/png/execute_job/index.test.ts +++ b/x-pack/plugins/reporting/server/export_types/png/execute_job/index.test.ts @@ -87,10 +87,7 @@ test(`passes browserTimezone to generatePng`, async () => { expect.objectContaining({ urls: ['localhost:80undefined/app/kibana#/something'], browserTimezone: 'UTC', - conditionalHeaders: expect.objectContaining({ - conditions: expect.any(Object), - headers: {}, - }), + headers: {}, }) ); }); diff --git a/x-pack/plugins/reporting/server/export_types/png/execute_job/index.ts b/x-pack/plugins/reporting/server/export_types/png/execute_job/index.ts index 20a2ea98e06d4..67d013740bedd 100644 --- a/x-pack/plugins/reporting/server/export_types/png/execute_job/index.ts +++ b/x-pack/plugins/reporting/server/export_types/png/execute_job/index.ts @@ -11,13 +11,7 @@ import { finalize, map, mergeMap, takeUntil, tap } from 'rxjs/operators'; import { PNG_JOB_TYPE, REPORTING_TRANSACTION_TYPE } from '../../../../common/constants'; import { TaskRunResult } from '../../../lib/tasks'; import { RunTaskFn, RunTaskFnFactory } from '../../../types'; -import { - decryptJobHeaders, - getConditionalHeaders, - getFullUrls, - omitBlockedHeaders, - generatePngObservable, -} from '../../common'; +import { decryptJobHeaders, getFullUrls, generatePngObservable } from '../../common'; import { TaskPayloadPNG } from '../types'; export const runTaskFnFactory: RunTaskFnFactory> = @@ -33,16 +27,14 @@ export const runTaskFnFactory: RunTaskFnFactory> = const jobLogger = parentLogger.clone([PNG_JOB_TYPE, 'execute', jobId]); const process$: Rx.Observable = Rx.of(1).pipe( mergeMap(() => decryptJobHeaders(encryptionKey, job.headers, jobLogger)), - map((decryptedHeaders) => omitBlockedHeaders(decryptedHeaders)), - map((filteredHeaders) => getConditionalHeaders(config, filteredHeaders)), - mergeMap((conditionalHeaders) => { + mergeMap((headers) => { const [url] = getFullUrls(config, job); apmGetAssets?.end(); apmGeneratePng = apmTrans?.startSpan('generate-png-pipeline', 'execute'); return generatePngObservable(reporting, jobLogger, { - conditionalHeaders, + headers, urls: [url], browserTimezone: job.browserTimezone, layout: job.layout, diff --git a/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.test.ts b/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.test.ts index f7c6b6138419c..1b1ad6878d78f 100644 --- a/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.test.ts +++ b/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.test.ts @@ -94,10 +94,7 @@ test(`passes browserTimezone to generatePng`, async () => { ], ], browserTimezone: 'UTC', - conditionalHeaders: expect.objectContaining({ - conditions: expect.any(Object), - headers: {}, - }), + headers: {}, }) ); }); diff --git a/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.ts b/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.ts index 1acce6e475630..51044aa324a1a 100644 --- a/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.ts +++ b/x-pack/plugins/reporting/server/export_types/png_v2/execute_job.ts @@ -11,12 +11,7 @@ import { finalize, map, mergeMap, takeUntil, tap } from 'rxjs/operators'; import { PNG_JOB_TYPE_V2, REPORTING_TRANSACTION_TYPE } from '../../../common/constants'; import { TaskRunResult } from '../../lib/tasks'; import { RunTaskFn, RunTaskFnFactory } from '../../types'; -import { - decryptJobHeaders, - getConditionalHeaders, - omitBlockedHeaders, - generatePngObservable, -} from '../common'; +import { decryptJobHeaders, generatePngObservable } from '../common'; import { getFullRedirectAppUrl } from '../common/v2/get_full_redirect_app_url'; import { TaskPayloadPNGV2 } from './types'; @@ -33,9 +28,7 @@ export const runTaskFnFactory: RunTaskFnFactory> = const jobLogger = parentLogger.clone([PNG_JOB_TYPE_V2, 'execute', jobId]); const process$: Rx.Observable = Rx.of(1).pipe( mergeMap(() => decryptJobHeaders(encryptionKey, job.headers, jobLogger)), - map((decryptedHeaders) => omitBlockedHeaders(decryptedHeaders)), - map((filteredHeaders) => getConditionalHeaders(config, filteredHeaders)), - mergeMap((conditionalHeaders) => { + mergeMap((headers) => { const url = getFullRedirectAppUrl(config, job.spaceId, job.forceNow); const [locatorParams] = job.locatorParams; @@ -43,7 +36,7 @@ export const runTaskFnFactory: RunTaskFnFactory> = apmGeneratePng = apmTrans?.startSpan('generate-png-pipeline', 'execute'); return generatePngObservable(reporting, jobLogger, { - conditionalHeaders, + headers, browserTimezone: job.browserTimezone, layout: job.layout, urls: [[url, locatorParams]], diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/execute_job/index.ts b/x-pack/plugins/reporting/server/export_types/printable_pdf/execute_job/index.ts index 02ba917ce329d..ab3793935e1d8 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/execute_job/index.ts +++ b/x-pack/plugins/reporting/server/export_types/printable_pdf/execute_job/index.ts @@ -11,13 +11,7 @@ import { catchError, map, mergeMap, takeUntil, tap } from 'rxjs/operators'; import { PDF_JOB_TYPE, REPORTING_TRANSACTION_TYPE } from '../../../../common/constants'; import { TaskRunResult } from '../../../lib/tasks'; import { RunTaskFn, RunTaskFnFactory } from '../../../types'; -import { - decryptJobHeaders, - getConditionalHeaders, - getFullUrls, - omitBlockedHeaders, - getCustomLogo, -} from '../../common'; +import { decryptJobHeaders, getFullUrls, getCustomLogo } from '../../common'; import { generatePdfObservable } from '../lib/generate_pdf'; import { TaskPayloadPDF } from '../types'; @@ -34,12 +28,8 @@ export const runTaskFnFactory: RunTaskFnFactory> = const process$: Rx.Observable = Rx.of(1).pipe( mergeMap(() => decryptJobHeaders(encryptionKey, job.headers, jobLogger)), - map((decryptedHeaders) => omitBlockedHeaders(decryptedHeaders)), - map((filteredHeaders) => getConditionalHeaders(config, filteredHeaders)), - mergeMap((conditionalHeaders) => - getCustomLogo(reporting, conditionalHeaders, job.spaceId, jobLogger) - ), - mergeMap(({ logo, conditionalHeaders }) => { + mergeMap((headers) => getCustomLogo(reporting, headers, job.spaceId, jobLogger)), + mergeMap(({ headers, logo }) => { const urls = getFullUrls(config, job); const { browserTimezone, layout, title } = job; @@ -53,7 +43,7 @@ export const runTaskFnFactory: RunTaskFnFactory> = { urls, browserTimezone, - conditionalHeaders, + headers, layout, }, logo diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/execute_job.ts b/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/execute_job.ts index de6f2ae70a756..85684bca66b86 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/execute_job.ts +++ b/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/execute_job.ts @@ -11,12 +11,7 @@ import { catchError, map, mergeMap, takeUntil, tap } from 'rxjs/operators'; import { PDF_JOB_TYPE_V2, REPORTING_TRANSACTION_TYPE } from '../../../common/constants'; import { TaskRunResult } from '../../lib/tasks'; import { RunTaskFn, RunTaskFnFactory } from '../../types'; -import { - decryptJobHeaders, - getConditionalHeaders, - omitBlockedHeaders, - getCustomLogo, -} from '../common'; +import { decryptJobHeaders, getCustomLogo } from '../common'; import { generatePdfObservable } from './lib/generate_pdf'; import { TaskPayloadPDFV2 } from './types'; @@ -33,12 +28,8 @@ export const runTaskFnFactory: RunTaskFnFactory> = const process$: Rx.Observable = Rx.of(1).pipe( mergeMap(() => decryptJobHeaders(encryptionKey, job.headers, jobLogger)), - map((decryptedHeaders) => omitBlockedHeaders(decryptedHeaders)), - map((filteredHeaders) => getConditionalHeaders(config, filteredHeaders)), - mergeMap((conditionalHeaders) => - getCustomLogo(reporting, conditionalHeaders, job.spaceId, jobLogger) - ), - mergeMap(({ logo, conditionalHeaders }) => { + mergeMap((headers) => getCustomLogo(reporting, headers, job.spaceId, jobLogger)), + mergeMap(({ logo, headers }) => { const { browserTimezone, layout, title, locatorParams } = job; apmGetAssets?.end(); @@ -51,7 +42,7 @@ export const runTaskFnFactory: RunTaskFnFactory> = locatorParams, { browserTimezone, - conditionalHeaders, + headers, layout, }, logo diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts b/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts index 2d5a254045104..90b4c9d9a30c6 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { ReportingCore } from '../..'; import { APP_WRAPPER_CLASS } from '../../../../../../src/core/server'; import { API_DIAGNOSE_URL } from '../../../common/constants'; -import { omitBlockedHeaders, generatePngObservable } from '../../export_types/common'; +import { generatePngObservable } from '../../export_types/common'; import { getAbsoluteUrlFactory } from '../../export_types/common/get_absolute_url'; import { LevelLogger as Logger } from '../../lib'; import { authorizedUserPreRouting } from '../lib/authorized_user_pre_routing'; @@ -24,9 +24,8 @@ export const registerDiagnoseScreenshot = (reporting: ReportingCore, logger: Log path: `${API_DIAGNOSE_URL}/screenshot`, validate: {}, }, - authorizedUserPreRouting(reporting, async (_user, _context, req, res) => { + authorizedUserPreRouting(reporting, async (_user, _context, request, res) => { const config = reporting.getConfig(); - const decryptedHeaders = req.headers as Record; const [basePath, protocol, hostname, port] = [ config.kbnConfig.get('server', 'basePath'), config.get('kibanaServer', 'protocol'), @@ -51,19 +50,9 @@ export const registerDiagnoseScreenshot = (reporting: ReportingCore, logger: Log }, }; - const conditionalHeaders = { - headers: omitBlockedHeaders(decryptedHeaders), - conditions: { - hostname, - port: +port, - basePath, - protocol, - }, - }; - return generatePngObservable(reporting, logger, { - conditionalHeaders, layout, + request, browserTimezone: 'America/Los_Angeles', urls: [hashUrl], }) diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/driver.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/driver.ts index 4e71194486d01..f9bf31ad35f6f 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/driver.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/driver.ts @@ -5,29 +5,18 @@ * 2.0. */ -import { map, truncate } from 'lodash'; +import { truncate } from 'lodash'; import open from 'opn'; import puppeteer, { ElementHandle, EvaluateFn, Page, SerializableOrJSHandle } from 'puppeteer'; import { parse as parseUrl } from 'url'; -import { Logger } from 'src/core/server'; +import { Headers, Logger } from 'src/core/server'; import { KBN_SCREENSHOT_MODE_HEADER, ScreenshotModePluginSetup, } from '../../../../../../src/plugins/screenshot_mode/server'; import { ConfigType } from '../../config'; import { allowRequest } from '../network_policy'; - -export interface ConditionalHeadersConditions { - protocol: string; - hostname: string; - port: number; - basePath: string; -} - -export interface ConditionalHeaders { - headers: Record; - conditions: ConditionalHeadersConditions; -} +import { stripUnsafeHeaders } from './strip_unsafe_headers'; export type Context = Record; @@ -52,8 +41,8 @@ export interface Viewport { } interface OpenOptions { - conditionalHeaders: ConditionalHeaders; context?: Context; + headers: Headers; waitForSelector: string; timeout: number; } @@ -104,6 +93,7 @@ export class HeadlessChromiumDriver { constructor( private screenshotMode: ScreenshotModePluginSetup, private config: ConfigType, + private basePath: string, private readonly page: Page ) {} @@ -123,7 +113,7 @@ export class HeadlessChromiumDriver { */ async open( url: string, - { conditionalHeaders, context, waitForSelector: pageLoadSelector, timeout }: OpenOptions, + { headers, context, waitForSelector: pageLoadSelector, timeout }: OpenOptions, logger: Logger ): Promise { logger.info(`opening url ${url}`); @@ -142,7 +132,7 @@ export class HeadlessChromiumDriver { } await this.page.setRequestInterception(true); - this.registerListeners(conditionalHeaders, logger); + this.registerListeners(url, headers, logger); await this.page.goto(url, { waitUntil: 'domcontentloaded' }); if (this.config.browser.chromium.inspect) { @@ -243,14 +233,13 @@ export class HeadlessChromiumDriver { }); } - private registerListeners(conditionalHeaders: ConditionalHeaders, logger: Logger) { + private registerListeners(url: string, customHeaders: Headers, logger: Logger) { if (this.listenersAttached) { return; } - // @ts-ignore // FIXME: retrieve the client in open() and pass in the client - const client = this.page._client; + const client = this.page.client(); // We have to reach into the Chrome Devtools Protocol to apply headers as using // puppeteer's API will cause map tile requests to hang indefinitely: @@ -277,19 +266,17 @@ export class HeadlessChromiumDriver { return; } - if (this._shouldUseCustomHeaders(conditionalHeaders.conditions, interceptedUrl)) { + if (this._shouldUseCustomHeaders(url, interceptedUrl)) { logger.trace(`Using custom headers for ${interceptedUrl}`); - const headers = map( - { - ...interceptedRequest.request.headers, - ...conditionalHeaders.headers, - [KBN_SCREENSHOT_MODE_HEADER]: 'true', - }, - (value, name) => ({ - name, - value, - }) - ); + const headers = Object.entries({ + ...interceptedRequest.request.headers, + ...stripUnsafeHeaders(customHeaders), + [KBN_SCREENSHOT_MODE_HEADER]: 'true', + }).flatMap(([name, rawValue]) => { + const values = Array.isArray(rawValue) ? rawValue : [rawValue ?? '']; + + return values.map((value) => ({ name, value })); + }); try { await client.send('Fetch.continueRequest', { @@ -353,13 +340,27 @@ export class HeadlessChromiumDriver { ); } - private _shouldUseCustomHeaders(conditions: ConditionalHeadersConditions, url: string) { - const { hostname, protocol, port, pathname } = parseUrl(url); + private _shouldUseCustomHeaders(sourceUrl: string, targetUrl: string) { + const { + hostname: sourceHostname, + protocol: sourceProtocol, + port: sourcePort, + } = parseUrl(sourceUrl); + const { + hostname: targetHostname, + protocol: targetProtocol, + port: targetPort, + pathname: targetPathname, + } = parseUrl(targetUrl); + + if (targetPathname === null) { + throw new Error(`URL missing pathname: ${targetUrl}`); + } // `port` is null in URLs that don't explicitly state it, // however we can derive the port from the protocol (http/https) // IE: https://feeds-staging.elastic.co/kibana/v8.0.0.json - const derivedPort = (() => { + const derivedPort = (protocol: string | null, port: string | null, url: string) => { if (port) { return port; } @@ -372,36 +373,15 @@ export class HeadlessChromiumDriver { return '443'; } - return null; - })(); - - if (derivedPort === null) throw new Error(`URL missing port: ${url}`); - if (pathname === null) throw new Error(`URL missing pathname: ${url}`); + throw new Error(`URL missing port: ${url}`); + }; return ( - hostname === conditions.hostname && - protocol === `${conditions.protocol}:` && - this._shouldUseCustomHeadersForPort(conditions, derivedPort) && - pathname.startsWith(`${conditions.basePath}/`) + sourceHostname === targetHostname && + sourceProtocol === targetProtocol && + derivedPort(sourceProtocol, sourcePort, sourceUrl) === + derivedPort(targetProtocol, targetPort, targetUrl) && + targetPathname.startsWith(`${this.basePath}/`) ); } - - private _shouldUseCustomHeadersForPort( - conditions: ConditionalHeadersConditions, - port: string | undefined - ) { - if (conditions.protocol === 'http' && conditions.port === 80) { - return ( - port === undefined || port === null || port === '' || port === conditions.port.toString() - ); - } - - if (conditions.protocol === 'https' && conditions.port === 443) { - return ( - port === undefined || port === null || port === '' || port === conditions.port.toString() - ); - } - - return port === conditions.port.toString(); - } } diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.test.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.test.ts index bf8a1786735eb..5c9136b272831 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.test.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.test.ts @@ -61,7 +61,7 @@ describe('HeadlessChromiumDriverFactory', () => { (puppeteer as jest.Mocked).launch.mockResolvedValue(mockBrowser); - factory = new HeadlessChromiumDriverFactory(screenshotMode, config, logger, path); + factory = new HeadlessChromiumDriverFactory(screenshotMode, config, logger, path, ''); jest.spyOn(factory, 'getBrowserLogger').mockReturnValue(Rx.EMPTY); jest.spyOn(factory, 'getProcessLogger').mockReturnValue(Rx.EMPTY); jest.spyOn(factory, 'getPageExit').mockReturnValue(Rx.EMPTY); diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts index 2f4c59707430e..4d1e0566f9943 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts @@ -108,7 +108,8 @@ export class HeadlessChromiumDriverFactory { private screenshotMode: ScreenshotModePluginSetup, private config: ConfigType, private logger: Logger, - private binaryPath: string + private binaryPath: string, + private basePath: string ) { if (this.config.browser.chromium.disableSandbox) { logger.warn(`Enabling the Chromium sandbox provides an additional layer of protection.`); @@ -243,7 +244,12 @@ export class HeadlessChromiumDriverFactory { this.getProcessLogger(browser, logger).subscribe(); // HeadlessChromiumDriver: object to "drive" a browser page - const driver = new HeadlessChromiumDriver(this.screenshotMode, this.config, page); + const driver = new HeadlessChromiumDriver( + this.screenshotMode, + this.config, + this.basePath, + page + ); // Rx.Observable: stream to interrupt page capture const unexpectedExit$ = this.getPageExit(browser, page); diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts index 88572081c5491..bc32e719e0f79 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts @@ -9,7 +9,7 @@ export const getChromiumDisconnectedError = () => new Error('Browser was closed unexpectedly! Check the server logs for more info.'); export { HeadlessChromiumDriver } from './driver'; -export type { ConditionalHeaders, Context } from './driver'; +export type { Context } from './driver'; export { DEFAULT_VIEWPORT, HeadlessChromiumDriverFactory } from './driver_factory'; export type { PerformanceMetrics } from './driver_factory'; export { ChromiumArchivePaths } from './paths'; diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.test.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.test.ts new file mode 100644 index 0000000000000..38feae0b2c026 --- /dev/null +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { stripUnsafeHeaders } from './strip_unsafe_headers'; + +describe('stripUnsafeHeaders', () => { + it.each` + header | value + ${'accept-encoding'} | ${''} + ${'connection'} | ${'upgrade'} + ${'content-length'} | ${''} + ${'content-type'} | ${''} + ${'host'} | ${''} + ${'transfer-encoding'} | ${''} + ${'proxy-connection'} | ${'bananas'} + ${'proxy-authorization'} | ${'some-base64-encoded-thing'} + ${'trailer'} | ${'s are for trucks'} + `('should strip unsafe header "$header"', ({ header, value }) => { + const headers = { [header]: value }; + + expect(stripUnsafeHeaders(headers)).toEqual({}); + }); + + it.each` + header | value + ${'foo'} | ${'bar'} + ${'baz'} | ${'quix'} + `('should keep safe header "$header"', ({ header, value }) => { + const headers = { [header]: value }; + + expect(stripUnsafeHeaders(headers)).toEqual(headers); + }); +}); diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.ts new file mode 100644 index 0000000000000..7e3f46775ea4e --- /dev/null +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/strip_unsafe_headers.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { omitBy } from 'lodash'; +import type { Headers } from 'src/core/server'; + +// @see https://github.com/chromium/chromium/blob/3611052c055897e5ebbc5b73ea295092e0c20141/services/network/public/cpp/header_util_unittest.cc#L50 +// For a list of headers that chromium doesn't like +const UNSAFE_HEADERS = [ + 'accept-encoding', + 'connection', + 'content-length', + 'content-type', + 'host', + 'referer', + // `Transfer-Encoding` is hop-by-hop header that is meaningful + // only for a single transport-level connection, and shouldn't + // be stored by caches or forwarded by proxies. + 'transfer-encoding', + 'trailer', + 'te', + 'upgrade', + 'keep-alive', +]; + +const UNSAFE_HEADERS_PATTERNS = [/^proxy-/i]; + +export function stripUnsafeHeaders(headers: Headers): Headers { + return omitBy( + headers, + (_value, header: string) => + header && + (UNSAFE_HEADERS.includes(header) || + UNSAFE_HEADERS_PATTERNS.some((pattern) => pattern.test(header))) + ); +} diff --git a/x-pack/plugins/screenshotting/server/browsers/index.ts b/x-pack/plugins/screenshotting/server/browsers/index.ts index 51687d74ff31d..15c8b2b2db06b 100644 --- a/x-pack/plugins/screenshotting/server/browsers/index.ts +++ b/x-pack/plugins/screenshotting/server/browsers/index.ts @@ -7,7 +7,7 @@ export { download } from './download'; export { install } from './install'; -export type { ConditionalHeaders, Context, PerformanceMetrics } from './chromium'; +export type { Context, PerformanceMetrics } from './chromium'; export { getChromiumDisconnectedError, ChromiumArchivePaths, diff --git a/x-pack/plugins/screenshotting/server/plugin.ts b/x-pack/plugins/screenshotting/server/plugin.ts index 138193815debe..e0c5d45f67d75 100755 --- a/x-pack/plugins/screenshotting/server/plugin.ts +++ b/x-pack/plugins/screenshotting/server/plugin.ts @@ -54,7 +54,7 @@ export class ScreenshottingPlugin implements Plugin { const paths = new ChromiumArchivePaths(); @@ -63,8 +63,15 @@ export class ScreenshottingPlugin implements Plugin { this.logger.error('Error in screenshotting setup, it may not function properly.'); diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts index ff5c910e9cc3e..b129d875f018d 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts @@ -37,7 +37,7 @@ describe('Screenshot Observable Pipeline', () => { } as unknown as jest.Mocked; options = { browserTimezone: 'UTC', - conditionalHeaders: {}, + headers: {}, layout: {}, timeouts: { loadDelay: 2000, diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.ts b/x-pack/plugins/screenshotting/server/screenshots/index.ts index e8a90145f77e6..b056e9a5450ed 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.ts @@ -18,7 +18,7 @@ import { tap, toArray, } from 'rxjs/operators'; -import type { Logger } from 'src/core/server'; +import type { KibanaRequest, Logger } from 'src/core/server'; import { LayoutParams } from '../../common'; import type { ConfigType } from '../config'; import type { HeadlessChromiumDriverFactory, PerformanceMetrics } from '../browsers'; @@ -30,6 +30,11 @@ import { Semaphore } from './semaphore'; export interface ScreenshotOptions extends ScreenshotObservableOptions { layout: LayoutParams; + + /** + * Source Kibana request object from where the headers will be extracted. + */ + request?: KibanaRequest; } export interface ScreenshotResult { @@ -77,6 +82,7 @@ export class Screenshots { browserTimezone, timeouts: { openUrl: openUrlTimeout }, } = options; + const headers = { ...(options.request?.headers ?? {}), ...(options.headers ?? {}) }; return this.browserDriverFactory .createPage( @@ -93,7 +99,10 @@ export class Screenshots { apmCreatePage?.end(); unexpectedExit$.subscribe({ error: () => apmTrans?.end() }); - const screen = new ScreenshotObservableHandler(driver, this.logger, layout, options); + const screen = new ScreenshotObservableHandler(driver, this.logger, layout, { + ...options, + headers, + }); return from(options.urls).pipe( concatMap((url, index) => diff --git a/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts b/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts index 5d5fbbde4e048..83800a168ddbe 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts @@ -8,7 +8,6 @@ import { interval, throwError, of } from 'rxjs'; import { map } from 'rxjs/operators'; import type { Logger } from 'src/core/server'; -import type { ConditionalHeaders } from '../browsers'; import { createMockBrowserDriver } from '../browsers/mock'; import { createMockLayout } from '../layouts/mock'; import { ScreenshotObservableHandler, ScreenshotObservableOptions } from './observable'; @@ -24,10 +23,7 @@ describe('ScreenshotObservableHandler', () => { layout = createMockLayout(); logger = { error: jest.fn() } as unknown as jest.Mocked; options = { - conditionalHeaders: { - headers: { testHeader: 'testHeadValue' }, - conditions: {} as unknown as ConditionalHeaders['conditions'], - }, + headers: { testHeader: 'testHeadValue' }, timeouts: { loadDelay: 5000, openUrl: 30000, diff --git a/x-pack/plugins/screenshotting/server/screenshots/observable.ts b/x-pack/plugins/screenshotting/server/screenshots/observable.ts index 5cfda2c841cb8..a743c206ef98d 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/observable.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/observable.ts @@ -8,8 +8,8 @@ import type { Transaction } from 'elastic-apm-node'; import { defer, forkJoin, throwError, Observable } from 'rxjs'; import { catchError, mergeMap, switchMapTo, timeoutWith } from 'rxjs/operators'; -import type { Logger } from 'src/core/server'; -import type { ConditionalHeaders, Context, HeadlessChromiumDriver } from '../browsers'; +import type { Headers, Logger } from 'src/core/server'; +import type { Context, HeadlessChromiumDriver } from '../browsers'; import { getChromiumDisconnectedError, DEFAULT_VIEWPORT } from '../browsers'; import type { Layout } from '../layouts'; import type { ElementsPositionAndAttribute } from './get_element_position_data'; @@ -60,7 +60,7 @@ export interface ScreenshotObservableOptions { /** * Custom headers to be sent with each request. */ - conditionalHeaders: ConditionalHeaders; + headers?: Headers; /** * Timeouts for each phase of the screenshot. @@ -177,7 +177,7 @@ export class ScreenshotObservableHandler { index, url, { ...(context ?? {}), layout: this.layout.id }, - this.options.conditionalHeaders + this.options.headers ?? {} ); }).pipe(this.waitUntil(this.options.timeouts.openUrl, 'open URL')); } diff --git a/x-pack/plugins/screenshotting/server/screenshots/open_url.ts b/x-pack/plugins/screenshotting/server/screenshots/open_url.ts index a4c4bd6217205..8b26f35961db4 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/open_url.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/open_url.ts @@ -6,9 +6,9 @@ */ import apm from 'elastic-apm-node'; -import type { Logger } from 'src/core/server'; +import type { Headers, Logger } from 'src/core/server'; import type { HeadlessChromiumDriver } from '../browsers'; -import type { ConditionalHeaders, Context } from '../browsers'; +import type { Context } from '../browsers'; import { DEFAULT_PAGELOAD_SELECTOR } from './constants'; export const openUrl = async ( @@ -18,7 +18,7 @@ export const openUrl = async ( index: number, url: string, context: Context, - conditionalHeaders: ConditionalHeaders + headers: Headers ): Promise => { // If we're moving to another page in the app, we'll want to wait for the app to tell us // it's loaded the next page. @@ -27,7 +27,7 @@ export const openUrl = async ( const span = apm.startSpan('open_url', 'wait'); try { - await browser.open(url, { conditionalHeaders, context, waitForSelector, timeout }, logger); + await browser.open(url, { context, headers, waitForSelector, timeout }, logger); } catch (err) { logger.error(err); throw new Error(`An error occurred when trying to open the Kibana URL: ${err.message}`); From 7126bc9cc13f8126a5c6bd507c62f7ae9d265d57 Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Wed, 16 Feb 2022 12:19:02 -0500 Subject: [PATCH 019/104] [Stack Monitoring] update rules queries to support metricbeat 8.0 [fixed PR] (#125748) * update queries to use metricset.name and fix paths * fix ccr query * fix cluster health query paths * update elasticsearch version mismatch * update fetchLicense paths * use ecs properties in fetch_index_shard_size * Clarified comment about createDatasetFilter * Re-editing a clarifying comment * Small comment edit * Revert "use ecs properties in fetch_index_shard_size" This reverts commit cdf8b2493eece825f3cfbdf206c8ff7cc6ef214e. * simplify fetch_index_shard_size document handling Co-authored-by: neptunian Co-authored-by: klacabane --- .../lib/alerts/create_dataset_query_filter.ts | 25 +++++++- .../alerts/fetch_ccr_read_exceptions.test.ts | 34 ++++++++++- .../lib/alerts/fetch_ccr_read_exceptions.ts | 59 ++++++++++++++----- .../lib/alerts/fetch_cluster_health.test.ts | 3 + .../server/lib/alerts/fetch_cluster_health.ts | 9 ++- .../server/lib/alerts/fetch_clusters.test.ts | 3 + .../server/lib/alerts/fetch_clusters.ts | 55 +++-------------- .../alerts/fetch_cpu_usage_node_stats.test.ts | 1 + .../lib/alerts/fetch_cpu_usage_node_stats.ts | 2 +- .../fetch_disk_usage_node_stats.test.ts | 1 + .../lib/alerts/fetch_disk_usage_node_stats.ts | 2 +- .../fetch_elasticsearch_versions.test.ts | 3 + .../alerts/fetch_elasticsearch_versions.ts | 11 +++- .../lib/alerts/fetch_index_shard_size.test.ts | 3 + .../lib/alerts/fetch_index_shard_size.ts | 10 ++-- .../lib/alerts/fetch_kibana_versions.test.ts | 1 + .../lib/alerts/fetch_kibana_versions.ts | 2 +- .../server/lib/alerts/fetch_licenses.test.ts | 3 + .../server/lib/alerts/fetch_licenses.ts | 9 ++- .../alerts/fetch_logstash_versions.test.ts | 1 + .../lib/alerts/fetch_logstash_versions.ts | 2 +- .../fetch_memory_usage_node_stats.test.ts | 1 + .../alerts/fetch_memory_usage_node_stats.ts | 2 +- .../fetch_missing_monitoring_data.test.ts | 7 ++- .../alerts/fetch_missing_monitoring_data.ts | 9 ++- .../fetch_nodes_from_cluster_stats.test.ts | 5 +- .../alerts/fetch_nodes_from_cluster_stats.ts | 12 ++-- .../fetch_thread_pool_rejections_stats.ts | 21 +++++-- 28 files changed, 193 insertions(+), 103 deletions(-) diff --git a/x-pack/plugins/monitoring/server/lib/alerts/create_dataset_query_filter.ts b/x-pack/plugins/monitoring/server/lib/alerts/create_dataset_query_filter.ts index 7d23240bc1e94..d4d02d4aec349 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/create_dataset_query_filter.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/create_dataset_query_filter.ts @@ -5,12 +5,33 @@ * 2.0. */ -export const createDatasetFilter = (legacyType: string, dataset: string) => ({ +/** + * We expect that metricset and dataset will be aligned where dataset + * is the full {product}.{metricset}, whereas metricset doesn't include + * the product, e.g. dataset is elasticsearch.cluster_stats and metricset is + * just cluster_stats. + * + * Unfortunately, this doesn't *always* seem to be the case, and sometimes + * the "metricset" value is different. For this reason, we've left these + * two as separate arguments to this function, at least until this is resolved. + * + * More info: https://github.com/elastic/kibana/pull/119112/files#r772605936 + * + * @param {string} type matches legacy data + * @param {string} metricset matches standalone beats + * @param {string} dataset matches agent integration data streams + */ +export const createDatasetFilter = (type: string, metricset: string, dataset: string) => ({ bool: { should: [ { term: { - type: legacyType, + type, + }, + }, + { + term: { + 'metricset.name': metricset, }, }, { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.test.ts index b399f6a876385..dbfebef6bfe42 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.test.ts @@ -47,15 +47,39 @@ describe('fetchCCReadExceptions', () => { bool: { filter: [ { - nested: { - path: 'ccr_stats.read_exceptions', - query: { exists: { field: 'ccr_stats.read_exceptions.exception' } }, + bool: { + should: [ + { + nested: { + ignore_unmapped: true, + path: 'ccr_stats.read_exceptions', + query: { + exists: { + field: 'ccr_stats.read_exceptions.exception', + }, + }, + }, + }, + { + nested: { + ignore_unmapped: true, + path: 'elasticsearch.ccr.read_exceptions', + query: { + exists: { + field: 'elasticsearch.ccr.read_exceptions.exception', + }, + }, + }, + }, + ], + minimum_should_match: 1, }, }, { bool: { should: [ { term: { type: 'ccr_stats' } }, + { term: { 'metricset.name': 'ccr' } }, { term: { 'data_stream.dataset': 'elasticsearch.ccr' } }, ], minimum_should_match: 1, @@ -82,9 +106,13 @@ describe('fetchCCReadExceptions', () => { _source: { includes: [ 'cluster_uuid', + 'elasticsearch.cluster.id', 'ccr_stats.read_exceptions', + 'elasticsearch.ccr.read_exceptions', 'ccr_stats.shard_id', + 'elasticsearch.ccr.shard_id', 'ccr_stats.leader_index', + 'elasticsearch.ccr.leader.index', ], }, size: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.ts index cdc136ffd5972..f6071d84f20d2 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_ccr_read_exceptions.ts @@ -35,16 +35,35 @@ export async function fetchCCRReadExceptions( bool: { filter: [ { - nested: { - path: 'ccr_stats.read_exceptions', - query: { - exists: { - field: 'ccr_stats.read_exceptions.exception', + bool: { + should: [ + { + nested: { + ignore_unmapped: true, + path: 'ccr_stats.read_exceptions', + query: { + exists: { + field: 'ccr_stats.read_exceptions.exception', + }, + }, + }, }, - }, + { + nested: { + ignore_unmapped: true, + path: 'elasticsearch.ccr.read_exceptions', + query: { + exists: { + field: 'elasticsearch.ccr.read_exceptions.exception', + }, + }, + }, + }, + ], + minimum_should_match: 1, }, }, - createDatasetFilter('ccr_stats', 'elasticsearch.ccr'), + createDatasetFilter('ccr_stats', 'ccr', 'elasticsearch.ccr'), { range: { timestamp: { @@ -83,9 +102,13 @@ export async function fetchCCRReadExceptions( _source: { includes: [ 'cluster_uuid', + 'elasticsearch.cluster.id', 'ccr_stats.read_exceptions', + 'elasticsearch.ccr.read_exceptions', 'ccr_stats.shard_id', + 'elasticsearch.ccr.shard_id', 'ccr_stats.leader_index', + 'elasticsearch.ccr.leader.index', ], }, size: 1, @@ -123,15 +146,19 @@ export async function fetchCCRReadExceptions( for (const followerIndexBucket of followerIndicesBuckets) { const followerIndex = followerIndexBucket.key; - const { - _index: monitoringIndexName, - _source: { ccr_stats: ccrStats, cluster_uuid: clusterUuid }, - } = get(followerIndexBucket, 'hits.hits.hits[0]'); - const { - read_exceptions: readExceptions, - leader_index: leaderIndex, - shard_id: shardId, - } = ccrStats; + const clusterUuid = + get(followerIndexBucket, 'hits.hits.hits[0]._source.cluster_uuid') || + get(followerIndexBucket, 'hits.hits.hits[0]_source.elasticsearch.cluster.id'); + + const monitoringIndexName = get(followerIndexBucket, 'hits.hits.hits[0]._index'); + const ccrStats = + get(followerIndexBucket, 'hits.hits.hits[0]._source.ccr_stats') || + get(followerIndexBucket, 'hits.hits.hits[0]._source.elasticsearch.ccr'); + + const { read_exceptions: readExceptions, shard_id: shardId } = ccrStats; + + const leaderIndex = ccrStats.leaderIndex || ccrStats.leader.index; + const { exception: lastReadException } = readExceptions[readExceptions.length - 1]; stats.push({ diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts index 596d95cff93f8..bb2513112af47 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts @@ -65,7 +65,9 @@ describe('fetchClusterHealth', () => { '*:.monitoring-es-*,.monitoring-es-*,*:metrics-elasticsearch.cluster_stats-*,metrics-elasticsearch.cluster_stats-*', filter_path: [ 'hits.hits._source.cluster_state.status', + 'hits.hits._source.elasticsearch.cluster.stats.status', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', 'hits.hits._index', ], body: { @@ -79,6 +81,7 @@ describe('fetchClusterHealth', () => { bool: { should: [ { term: { type: 'cluster_stats' } }, + { term: { 'metricset.name': 'cluster_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.cluster_stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.ts index 7103014cb199e..5156a865a80e8 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.ts @@ -27,7 +27,9 @@ export async function fetchClusterHealth( index: indexPatterns, filter_path: [ 'hits.hits._source.cluster_state.status', + 'hits.hits._source.elasticsearch.cluster.stats.status', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', 'hits.hits._index', ], body: { @@ -48,7 +50,7 @@ export async function fetchClusterHealth( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('cluster_stats', 'elasticsearch.cluster_stats'), + createDatasetFilter('cluster_stats', 'cluster_stats', 'elasticsearch.cluster_stats'), { range: { timestamp: { @@ -77,8 +79,9 @@ export async function fetchClusterHealth( const response = await esClient.search(params); return (response.hits?.hits ?? []).map((hit) => { return { - health: hit._source!.cluster_state?.status, - clusterUuid: hit._source!.cluster_uuid, + health: + hit._source!.cluster_state?.status || hit._source!.elasticsearch?.cluster?.stats?.status, + clusterUuid: hit._source!.cluster_uuid || hit._source!.elasticsearch?.cluster?.id, ccs: hit._index.includes(':') ? hit._index.split(':')[0] : undefined, } as AlertClusterHealth; }); 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 1eeedf3a7a574..85a027d9cde1d 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 @@ -87,7 +87,9 @@ describe('fetchClusters', () => { filter_path: [ 'hits.hits._source.cluster_settings.cluster.metadata.display_name', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', 'hits.hits._source.cluster_name', + 'hits.hits._source.elasticsearch.cluster.name', ], body: { size: 1000, @@ -98,6 +100,7 @@ describe('fetchClusters', () => { bool: { should: [ { term: { type: 'cluster_stats' } }, + { term: { 'metricset.name': 'cluster_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.cluster_stats' } }, ], minimum_should_match: 1, 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 ac6520eb3948d..81eb6b724834c 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts @@ -35,14 +35,16 @@ export async function fetchClusters( filter_path: [ 'hits.hits._source.cluster_settings.cluster.metadata.display_name', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', 'hits.hits._source.cluster_name', + 'hits.hits._source.elasticsearch.cluster.name', ], body: { size: 1000, query: { bool: { filter: [ - createDatasetFilter('cluster_stats', 'elasticsearch.cluster_stats'), + createDatasetFilter('cluster_stats', 'cluster_stats', 'elasticsearch.cluster_stats'), { range: rangeFilter, }, @@ -56,59 +58,16 @@ export async function fetchClusters( }; const response = await esClient.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, - }; - }); -} -export async function fetchClustersLegacy( - callCluster: any, - index: string, - rangeFilter: RangeFilter = { timestamp: { gte: 'now-2m' } } -): Promise { - const params = { - index, - filter_path: [ - 'hits.hits._source.cluster_settings.cluster.metadata.display_name', - 'hits.hits._source.cluster_uuid', - 'hits.hits._source.cluster_name', - ], - body: { - size: 1000, - query: { - bool: { - filter: [ - { - term: { - type: 'cluster_stats', - }, - }, - { - range: rangeFilter, - }, - ], - }, - }, - collapse: { - field: 'cluster_uuid', - }, - }, - }; - 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'); + get(hit, '_source.elasticsearch.cluster.name') || + get(hit, '_source.cluster_uuid') || + get(hit, '_source.elasticsearch.cluster.id'); return { - clusterUuid: get(hit, '_source.cluster_uuid'), + clusterUuid: get(hit, '_source.cluster_uuid') || get(hit, '_source.elasticsearch.cluster.id'), clusterName, }; }); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts index b77c2ff686ca8..028cff224afad 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts @@ -227,6 +227,7 @@ describe('fetchCpuUsageNodeStats', () => { bool: { should: [ { term: { type: 'node_stats' } }, + { term: { 'metricset.name': 'node_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.node_stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts index aef39d09e26b2..b831db2315e58 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts @@ -58,7 +58,7 @@ export async function fetchCpuUsageNodeStats( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('node_stats', 'elasticsearch.node_stats'), + createDatasetFilter('node_stats', 'node_stats', 'elasticsearch.node_stats'), { range: { timestamp: { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.test.ts index 9e53c85e743fe..5126e2d2c408d 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.test.ts @@ -101,6 +101,7 @@ describe('fetchDiskUsageNodeStats', () => { bool: { should: [ { term: { type: 'node_stats' } }, + { term: { 'metricset.name': 'node_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.node_stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts index 6ea9ad5140158..26512b88a08a9 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts @@ -40,7 +40,7 @@ export async function fetchDiskUsageNodeStats( cluster_uuid: clustersIds, }, }, - createDatasetFilter('node_stats', 'elasticsearch.node_stats'), + createDatasetFilter('node_stats', 'node_stats', 'elasticsearch.node_stats'), { range: { timestamp: { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts index 8f34136b70b68..b29dd722366e0 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts @@ -70,8 +70,10 @@ describe('fetchElasticsearchVersions', () => { '*:.monitoring-es-*,.monitoring-es-*,*:metrics-elasticsearch.cluster_stats-*,metrics-elasticsearch.cluster_stats-*', filter_path: [ 'hits.hits._source.cluster_stats.nodes.versions', + 'hits.hits._source.elasticsearch.cluster.stats.nodes.versions', 'hits.hits._index', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', ], body: { size: 1, @@ -84,6 +86,7 @@ describe('fetchElasticsearchVersions', () => { bool: { should: [ { term: { type: 'cluster_stats' } }, + { term: { 'metricset.name': 'cluster_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.cluster_stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.ts index fc5d0cf1cf056..9816b6facc43f 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.ts @@ -28,8 +28,10 @@ export async function fetchElasticsearchVersions( index: indexPatterns, filter_path: [ 'hits.hits._source.cluster_stats.nodes.versions', + 'hits.hits._source.elasticsearch.cluster.stats.nodes.versions', 'hits.hits._index', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', ], body: { size: clusters.length, @@ -49,7 +51,7 @@ export async function fetchElasticsearchVersions( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('cluster_stats', 'elasticsearch.cluster_stats'), + createDatasetFilter('cluster_stats', 'cluster_stats', 'elasticsearch.cluster_stats'), { range: { timestamp: { @@ -77,10 +79,13 @@ export async function fetchElasticsearchVersions( const response = await esClient.search(params); return (response.hits?.hits ?? []).map((hit) => { - const versions = hit._source!.cluster_stats?.nodes?.versions ?? []; + const versions = + hit._source!.cluster_stats?.nodes?.versions ?? + hit._source!.elasticsearch?.cluster?.stats?.nodes?.versions ?? + []; return { versions, - clusterUuid: hit._source!.cluster_uuid, + clusterUuid: hit._source!.elasticsearch?.cluster?.id || hit._source!.cluster_uuid, ccs: hit._index.includes(':') ? hit._index.split(':')[0] : undefined, }; }); diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.test.ts index e7020360113e8..41e84be80d2d5 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.test.ts @@ -161,6 +161,7 @@ describe('fetchIndexShardSize', () => { bool: { should: [ { term: { type: 'index_stats' } }, + { term: { 'metricset.name': 'index' } }, { term: { 'data_stream.dataset': 'elasticsearch.index' } }, ], minimum_should_match: 1, @@ -185,6 +186,8 @@ describe('fetchIndexShardSize', () => { '_index', 'index_stats.shards.primaries', 'index_stats.primaries.store.size_in_bytes', + 'elasticsearch.index.shards.primaries', + 'elasticsearch.index.primaries.store.size_in_bytes', ], }, size: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.ts index 539b6c20c1e37..5afa9ed007f66 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_index_shard_size.ts @@ -50,7 +50,7 @@ export async function fetchIndexShardSize( query: { bool: { filter: [ - createDatasetFilter('index_stats', 'elasticsearch.index'), + createDatasetFilter('index_stats', 'index', 'elasticsearch.index'), { range: { timestamp: { @@ -90,6 +90,8 @@ export async function fetchIndexShardSize( '_index', 'index_stats.shards.primaries', 'index_stats.primaries.store.size_in_bytes', + 'elasticsearch.index.shards.primaries', + 'elasticsearch.index.primaries.store.size_in_bytes', ], }, size: 1, @@ -131,10 +133,8 @@ export async function fetchIndexShardSize( if (!topHit || !ESGlobPatterns.isValid(shardIndex, validIndexPatterns)) { continue; } - const { - _index: monitoringIndexName, - _source: { index_stats: indexStats }, - } = topHit; + const { _index: monitoringIndexName, _source } = topHit; + const indexStats = _source.index_stats || _source.elasticsearch?.index; if (!indexStats || !indexStats.primaries) { continue; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.test.ts index 54a7f308fea67..07403388c96f8 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.test.ts @@ -102,6 +102,7 @@ describe('fetchKibanaVersions', () => { bool: { should: [ { term: { type: 'kibana_stats' } }, + { term: { 'metricset.name': 'stats' } }, { term: { 'data_stream.dataset': 'kibana.stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.ts index 886e96ae3331d..b5ef5d1ade372 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_kibana_versions.ts @@ -41,7 +41,7 @@ export async function fetchKibanaVersions( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('kibana_stats', 'kibana.stats'), + createDatasetFilter('kibana_stats', 'stats', 'kibana.stats'), { range: { timestamp: { 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 98f52188f0fb6..35fc50a6014b6 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 @@ -84,7 +84,9 @@ describe('fetchLicenses', () => { '*:.monitoring-es-*,.monitoring-es-*,*:metrics-elasticsearch.cluster_stats-*,metrics-elasticsearch.cluster_stats-*', filter_path: [ 'hits.hits._source.license.*', + 'hits.hits._source.elasticsearch.cluster.stats.license.*', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', 'hits.hits._index', ], body: { @@ -98,6 +100,7 @@ describe('fetchLicenses', () => { bool: { should: [ { term: { type: 'cluster_stats' } }, + { term: { 'metricset.name': 'cluster_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.cluster_stats' } }, ], minimum_should_match: 1, 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 10537fdbaacee..32bbe271da76f 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.ts @@ -27,7 +27,9 @@ export async function fetchLicenses( index: indexPatterns, filter_path: [ 'hits.hits._source.license.*', + 'hits.hits._source.elasticsearch.cluster.stats.license.*', 'hits.hits._source.cluster_uuid', + 'hits.hits._source.elasticsearch.cluster.id', 'hits.hits._index', ], body: { @@ -48,7 +50,7 @@ export async function fetchLicenses( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('cluster_stats', 'elasticsearch.cluster_stats'), + createDatasetFilter('cluster_stats', 'cluster_stats', 'elasticsearch.cluster_stats'), { range: { timestamp: { @@ -77,12 +79,13 @@ export async function fetchLicenses( const response = await esClient.search(params); return ( response?.hits?.hits.map((hit) => { - const rawLicense = hit._source!.license ?? {}; + const rawLicense = + hit._source!.license ?? hit._source?.elasticsearch?.cluster?.stats?.license ?? {}; const license: AlertLicense = { status: rawLicense.status ?? '', type: rawLicense.type ?? '', expiryDateMS: rawLicense.expiry_date_in_millis ?? 0, - clusterUuid: hit._source!.cluster_uuid, + clusterUuid: hit._source?.elasticsearch?.cluster?.id || hit._source!.cluster_uuid, ccs: hit._index, }; return license; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.test.ts index 00f48f1ac27c7..cdb7287ccb77c 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.test.ts @@ -107,6 +107,7 @@ describe('fetchLogstashVersions', () => { bool: { should: [ { term: { type: 'logstash_stats' } }, + { term: { 'metricset.name': 'node_stats' } }, { term: { 'data_stream.dataset': 'logstash.node_stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.ts index 7f36572326742..2a0a4a283a68d 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_logstash_versions.ts @@ -41,7 +41,7 @@ export async function fetchLogstashVersions( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('logstash_stats', 'logstash.node_stats'), + createDatasetFilter('logstash_stats', 'node_stats', 'logstash.node_stats'), { range: { timestamp: { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.test.ts index 488818b3167e4..64fbe542cd35b 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.test.ts @@ -130,6 +130,7 @@ describe('fetchMemoryUsageNodeStats', () => { bool: { should: [ { term: { type: 'node_stats' } }, + { term: { 'metricset.name': 'node_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.node_stats' } }, ], minimum_should_match: 1, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts index 01d2b97ebac75..644ef03bd3ec4 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts @@ -41,7 +41,7 @@ export async function fetchMemoryUsageNodeStats( cluster_uuid: clustersIds, }, }, - createDatasetFilter('node_stats', 'elasticsearch.node_stats'), + createDatasetFilter('node_stats', 'node_stats', 'elasticsearch.node_stats'), { range: { timestamp: { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.test.ts index 1d4f00e828c67..9b1f3f71e2a96 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.test.ts @@ -189,6 +189,7 @@ describe('fetchMissingMonitoringData', () => { bool: { should: [ { term: { type: 'node_stats' } }, + { term: { 'metricset.name': 'node_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.node_stats' } }, ], minimum_should_match: 1, @@ -210,7 +211,9 @@ describe('fetchMissingMonitoringData', () => { top_hits: { size: 1, sort: [{ timestamp: { order: 'desc', unmapped_type: 'long' } }], - _source: { includes: ['_index', 'source_node.name'] }, + _source: { + includes: ['source_node.name', 'elasticsearch.node.name'], + }, }, }, }, @@ -221,7 +224,7 @@ describe('fetchMissingMonitoringData', () => { }, }); }); - it('should call ES with correct query when ccs disabled', async () => { + it('should call ES with correct query when ccs disabled', async () => { const now = 10; const clusters = [ { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts index f97f0e749f420..60a5352b8e38f 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts @@ -74,7 +74,7 @@ export async function fetchMissingMonitoringData( cluster_uuid: clusters.map((cluster) => cluster.clusterUuid), }, }, - createDatasetFilter('node_stats', 'elasticsearch.node_stats'), + createDatasetFilter('node_stats', 'node_stats', 'elasticsearch.node_stats'), { range: { timestamp: { @@ -117,7 +117,7 @@ export async function fetchMissingMonitoringData( }, ], _source: { - includes: ['_index', 'source_node.name'], + includes: ['source_node.name', 'elasticsearch.node.name'], }, }, }, @@ -153,7 +153,10 @@ export async function fetchMissingMonitoringData( const nodeId = uuidBucket.key; const indexName = get(uuidBucket, `document.hits.hits[0]._index`); const differenceInMs = nowInMs - uuidBucket.most_recent.value; - const nodeName = get(uuidBucket, `document.hits.hits[0]._source.source_node.name`, nodeId); + const nodeName = + get(uuidBucket, `document.hits.hits[0]._source.source_node.name`) || + get(uuidBucket, `document.hits.hits[0]._source.elasticsearch.node.name`) || + nodeId; uniqueList[`${clusterUuid}${nodeId}`] = { nodeId, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.test.ts index 82b0c9910976f..328f8b12836f7 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.test.ts @@ -172,6 +172,7 @@ describe('fetchNodesFromClusterStats', () => { bool: { should: [ { term: { type: 'cluster_stats' } }, + { term: { 'metricset.name': 'cluster_stats' } }, { term: { 'data_stream.dataset': 'elasticsearch.cluster_stats' } }, ], minimum_should_match: 1, @@ -188,7 +189,9 @@ describe('fetchNodesFromClusterStats', () => { top: { top_hits: { sort: [{ timestamp: { order: 'desc', unmapped_type: 'long' } }], - _source: { includes: ['cluster_state.nodes_hash', 'cluster_state.nodes'] }, + _source: { + includes: ['cluster_state.nodes', 'elasticsearch.cluster.stats.nodes'], + }, size: 2, }, }, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.ts index 40de85226e1f9..0c367558732b5 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_nodes_from_cluster_stats.ts @@ -54,7 +54,7 @@ export async function fetchNodesFromClusterStats( query: { bool: { filter: [ - createDatasetFilter('cluster_stats', 'elasticsearch.cluster_stats'), + createDatasetFilter('cluster_stats', 'cluster_stats', 'elasticsearch.cluster_stats'), { range: { timestamp: { @@ -83,7 +83,7 @@ export async function fetchNodesFromClusterStats( }, ], _source: { - includes: ['cluster_state.nodes_hash', 'cluster_state.nodes'], + includes: ['cluster_state.nodes', 'elasticsearch.cluster.stats.nodes'], }, size: 2, }, @@ -116,8 +116,12 @@ export async function fetchNodesFromClusterStats( const indexName = hits[0]._index; nodes.push({ clusterUuid, - recentNodes: formatNode(hits[0]._source.cluster_state?.nodes), - priorNodes: formatNode(hits[1]._source.cluster_state?.nodes), + recentNodes: formatNode( + hits[0]._source.cluster_state?.nodes || hits[0]._source.elasticsearch.cluster.stats.nodes + ), + priorNodes: formatNode( + hits[1]._source.cluster_state?.nodes || hits[1]._source.elasticsearch.cluster.stats.nodes + ), ccs: indexName.includes(':') ? indexName.split(':')[0] : undefined, }); } diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts index 8c3ec15e15407..8226f0dd012fd 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts @@ -28,7 +28,12 @@ const getTopHits = (threadType: string, order: 'asc' | 'desc') => ({ }, ], _source: { - includes: [`node_stats.thread_pool.${threadType}.rejected`, 'source_node.name'], + includes: [ + `node_stats.thread_pool.${threadType}.rejected`, + `elasticsearch.node.stats.thread_pool.${threadType}.rejected.count`, + 'source_node.name', + 'elasticsearch.node.name', + ], }, size: 1, }, @@ -62,7 +67,7 @@ export async function fetchThreadPoolRejectionStats( cluster_uuid: clustersIds, }, }, - createDatasetFilter('node_stats', 'elasticsearch.node_stats'), + createDatasetFilter('node_stats', 'node_stats', 'elasticsearch.node_stats'), { range: { timestamp: { @@ -131,8 +136,11 @@ export async function fetchThreadPoolRejectionStats( } const rejectedPath = `_source.node_stats.thread_pool.${threadType}.rejected`; - const newRejectionCount = Number(get(mostRecentDoc, rejectedPath)); - const oldRejectionCount = Number(get(leastRecentDoc, rejectedPath)); + const rejectedPathEcs = `_source.elasticsearch.node.stats.thread_pool.${threadType}.rejected.count`; + const newRejectionCount = + Number(get(mostRecentDoc, rejectedPath)) || Number(get(mostRecentDoc, rejectedPathEcs)); + const oldRejectionCount = + Number(get(leastRecentDoc, rejectedPath)) || Number(get(leastRecentDoc, rejectedPathEcs)); if (invalidNumberValue(newRejectionCount) || invalidNumberValue(oldRejectionCount)) { continue; @@ -143,7 +151,10 @@ export async function fetchThreadPoolRejectionStats( ? newRejectionCount : newRejectionCount - oldRejectionCount; const indexName = mostRecentDoc._index; - const nodeName = get(mostRecentDoc, '_source.source_node.name') || node.key; + const nodeName = + get(mostRecentDoc, '_source.source_node.name') || + get(mostRecentDoc, '_source.elasticsearch.node.name') || + node.key; const nodeStat = { rejectionCount, type: threadType, From 2842ffd432340543d827763110788ab4f0bc4f6a Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 10:31:37 -0700 Subject: [PATCH 020/104] skip flaky suite (#125743) --- x-pack/test/functional_execution_context/tests/browser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional_execution_context/tests/browser.ts b/x-pack/test/functional_execution_context/tests/browser.ts index ca777e1d4acf3..e2578934cb00b 100644 --- a/x-pack/test/functional_execution_context/tests/browser.ts +++ b/x-pack/test/functional_execution_context/tests/browser.ts @@ -12,7 +12,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home']); const retry = getService('retry'); - describe('Browser apps', () => { + // FLAKY: https://github.com/elastic/kibana/issues/125743 + describe.skip('Browser apps', () => { before(async () => { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, From 4137dd8de3c7cfac6c85d7d22fefe032d8d5885a Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Wed, 16 Feb 2022 18:33:26 +0100 Subject: [PATCH 021/104] [Discover] Enable document explorer as default document table (#125485) * Enable document explorer in Discover as default document table * Fix lots of functional tests --- .../discover_grid/discover_grid.tsx | 9 ++++++++- .../public/embeddable/saved_search_grid.tsx | 8 +++++++- src/plugins/discover/server/ui_settings.ts | 2 +- test/functional/apps/context/_date_nanos.ts | 1 + .../context/_date_nanos_custom_timestamp.ts | 1 + test/functional/apps/context/_filters.ts | 9 +++++++++ test/functional/apps/context/_size.ts | 1 + .../apps/dashboard/dashboard_time_picker.ts | 4 ++-- .../apps/dashboard/saved_search_embeddable.ts | 2 +- .../apps/discover/_discover_fields_api.ts | 8 +++----- test/functional/page_objects/discover_page.ts | 7 ++++++- .../services/dashboard/expectations.ts | 19 ++++++++++++++----- .../apps/discover/value_suggestions.ts | 5 +++++ .../value_suggestions_non_timebased.ts | 5 +++++ 14 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx index 92ca4ce96bf72..34673310f2c6e 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx +++ b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx @@ -408,7 +408,14 @@ export const DiscoverGrid = ({ if (!rowCount) { return ( -
+
diff --git a/src/plugins/discover/public/embeddable/saved_search_grid.tsx b/src/plugins/discover/public/embeddable/saved_search_grid.tsx index ca750ca6fb976..ff72ed378aff3 100644 --- a/src/plugins/discover/public/embeddable/saved_search_grid.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_grid.tsx @@ -21,7 +21,13 @@ export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) { const [expandedDoc, setExpandedDoc] = useState(undefined); return ( - + {props.totalHitCount !== 0 && ( diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index c9c9692e6986b..afd70cc5bbee7 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -164,7 +164,7 @@ export const getUiSettings: (docLinks: DocLinksServiceSetup) => Record $(mark).text()); - expect(marks.length).to.above(10); + expect(marks.length).to.above(0); }); it('removing a filter removes highlights', async function () { diff --git a/test/functional/apps/discover/_discover_fields_api.ts b/test/functional/apps/discover/_discover_fields_api.ts index 700c865031cd6..fb3ee3b9858d3 100644 --- a/test/functional/apps/discover/_discover_fields_api.ts +++ b/test/functional/apps/discover/_discover_fields_api.ts @@ -11,7 +11,6 @@ import { FtrProviderContext } from './ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); - const docTable = getService('docTable'); const retry = getService('retry'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); @@ -19,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const defaultSettings = { defaultIndex: 'logstash-*', 'discover:searchFieldsFromSource': false, + 'doc_table:legacy': true, }; describe('discover uses fields API test', function describeIndexTests() { before(async function () { @@ -27,13 +27,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover.json'); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); await kibanaServer.uiSettings.replace(defaultSettings); - log.debug('discover'); await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setDefaultAbsoluteRange(); }); after(async () => { - await kibanaServer.uiSettings.replace({ 'discover:searchFieldsFromSource': true }); + await kibanaServer.uiSettings.replace({}); }); it('should correctly display documents', async function () { @@ -61,8 +60,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('displays _source viewer in doc viewer', async function () { - await docTable.clickRowToggle({ rowIndex: 0 }); - + await PageObjects.discover.clickDocTableRowToggle(0); await PageObjects.discover.isShowingDocViewer(); await PageObjects.discover.clickDocViewerTab(1); await PageObjects.discover.expectSourceViewerToExist(); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index effacb30bdc89..1583903be4991 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -240,7 +240,7 @@ export class DiscoverPageObject extends FtrService { } public async useLegacyTable() { - return (await this.kibanaServer.uiSettings.get('doc_table:legacy')) !== false; + return (await this.kibanaServer.uiSettings.get('doc_table:legacy')) === true; } public async getDocTableIndex(index: number) { @@ -276,6 +276,11 @@ export class DiscoverPageObject extends FtrService { return result[usedCellIdx]; } + public async clickDocTableRowToggle(rowIndex: number = 0) { + const docTable = await this.getDocTable(); + await docTable.clickRowToggle({ rowIndex }); + } + public async skipToEndOfDocTable() { // add the focus to the button to make it appear const skipButton = await this.testSubjects.find('discoverSkipTableButton'); diff --git a/test/functional/services/dashboard/expectations.ts b/test/functional/services/dashboard/expectations.ts index 75f60b1448eea..c56e7c1eae27e 100644 --- a/test/functional/services/dashboard/expectations.ts +++ b/test/functional/services/dashboard/expectations.ts @@ -226,11 +226,20 @@ export class DashboardExpectService extends FtrService { async savedSearchRowCount(expectedMinCount: number) { this.log.debug(`DashboardExpect.savedSearchRowCount(${expectedMinCount})`); await this.retry.try(async () => { - const savedSearchRows = await this.testSubjects.findAll( - 'docTableExpandToggleColumn', - this.findTimeout - ); - expect(savedSearchRows.length).to.be.above(expectedMinCount); + const gridExists = await this.find.existsByCssSelector('[data-document-number]'); + if (gridExists) { + const grid = await this.find.byCssSelector('[data-document-number]'); + // in this case it's the document explorer + const docNr = Number(await grid.getAttribute('data-document-number')); + expect(docNr).to.be.above(expectedMinCount); + } else { + // in this case it's the classic table + const savedSearchRows = await this.testSubjects.findAll( + 'docTableExpandToggleColumn', + this.findTimeout + ); + expect(savedSearchRows.length).to.be.above(expectedMinCount); + } }); } diff --git a/x-pack/test/functional/apps/discover/value_suggestions.ts b/x-pack/test/functional/apps/discover/value_suggestions.ts index 6cef272279548..e67d42bf27896 100644 --- a/x-pack/test/functional/apps/discover/value_suggestions.ts +++ b/x-pack/test/functional/apps/discover/value_suggestions.ts @@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { UI_SETTINGS } from '../../../../../src/plugins/data/common'; export default function ({ getService, getPageObjects }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); const queryBar = getService('queryBar'); const filterBar = getService('filterBar'); @@ -28,10 +29,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { before(async function () { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await esArchiver.load('x-pack/test/functional/es_archives/dashboard/drilldowns'); + await kibanaServer.uiSettings.update({ + 'doc_table:legacy': true, + }); }); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/dashboard/drilldowns'); + await kibanaServer.uiSettings.unset('doc_table:legacy'); }); describe('useTimeRange enabled', () => { diff --git a/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts b/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts index b95cbea20cf82..2a763014c7eb6 100644 --- a/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts +++ b/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts @@ -11,18 +11,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const queryBar = getService('queryBar'); const PageObjects = getPageObjects(['common', 'settings', 'context', 'header']); + const kibanaServer = getService('kibanaServer'); describe('value suggestions non time based', function describeIndexTests() { before(async function () { await esArchiver.loadIfNeeded( 'test/functional/fixtures/es_archiver/index_pattern_without_timefield' ); + await kibanaServer.uiSettings.update({ + 'doc_table:legacy': true, + }); }); after(async () => { await esArchiver.unload( 'test/functional/fixtures/es_archiver/index_pattern_without_timefield' ); + await kibanaServer.uiSettings.unset('doc_table:legacy'); }); it('shows all autosuggest options for a filter in discover context app', async () => { From bcfed9fed352a40c705a9a424d9cc16d5f098925 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Wed, 16 Feb 2022 12:38:50 -0500 Subject: [PATCH 022/104] [Uptime] implement monitor management telemetry (#124473) * uptime - implement monitor management telemetry * adjust log level * adjust types * add telemetry dependency * remove extra log * update locationsCount * add current channel * adjust types * update location errors * enhance uptime telemetry adapter for synthetics use case * fix test * update xpack_plugins.json * fix tests * fix tests * update snapshots * remove telemetry collectors implementation * update tests and mappings * Update x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts * Update x-pack/plugins/uptime/server/lib/telemetry/sender.ts * move telemetry setup to service conditional Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../monitor_management/config_key.ts | 1 + .../monitor_management/locations.ts | 36 +-- .../monitor_management/monitor_types.ts | 6 +- x-pack/plugins/uptime/kibana.json | 2 +- .../fleet_package/common/formatters.ts | 1 + .../fleet_package/common/normalizers.ts | 1 + .../lib/adapters/framework/adapter_types.ts | 5 + .../synthetics_service/formatters/common.ts | 1 + .../get_service_locations.test.ts | 1 + .../get_service_locations.ts | 5 +- .../server/lib/telemetry/__mocks__/index.ts | 26 +++ .../uptime/server/lib/telemetry/constants.ts | 9 + .../uptime/server/lib/telemetry/queue.test.ts | 39 ++++ .../uptime/server/lib/telemetry/queue.ts | 40 ++++ .../server/lib/telemetry/sender.test.ts | 148 ++++++++++++ .../uptime/server/lib/telemetry/sender.ts | 195 ++++++++++++++++ .../uptime/server/lib/telemetry/types.ts | 32 +++ x-pack/plugins/uptime/server/plugin.ts | 6 + .../synthetics_service/add_monitor.ts | 17 +- .../synthetics_service/delete_monitor.ts | 10 + .../synthetics_service/edit_monitor.ts | 25 +- .../telemetry/monitor_upgrade_sender.test.ts | 215 ++++++++++++++++++ .../telemetry/monitor_upgrade_sender.ts | 147 ++++++++++++ .../apis/uptime/rest/edit_monitor.ts | 2 +- .../uptime/rest/fixtures/http_monitor.json | 3 +- .../apis/uptime/rest/helper/make_checks.ts | 26 +-- .../apis/uptime/rest/helper/make_ping.ts | 5 +- .../uptime/rest/telemetry_collectors_fleet.ts | 10 +- 28 files changed, 960 insertions(+), 54 deletions(-) create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/__mocks__/index.ts create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/constants.ts create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/queue.test.ts create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/queue.ts create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/sender.test.ts create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/sender.ts create mode 100644 x-pack/plugins/uptime/server/lib/telemetry/types.ts create mode 100644 x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts create mode 100644 x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts diff --git a/x-pack/plugins/uptime/common/runtime_types/monitor_management/config_key.ts b/x-pack/plugins/uptime/common/runtime_types/monitor_management/config_key.ts index f001cbbc10bbd..595dd1a3e7721 100644 --- a/x-pack/plugins/uptime/common/runtime_types/monitor_management/config_key.ts +++ b/x-pack/plugins/uptime/common/runtime_types/monitor_management/config_key.ts @@ -37,6 +37,7 @@ export enum ConfigKey { REQUEST_HEADERS_CHECK = 'check.request.headers', REQUEST_METHOD_CHECK = 'check.request.method', REQUEST_SEND_CHECK = 'check.send', + REVISION = 'revision', SCHEDULE = 'schedule', SCREENSHOTS = 'screenshots', SOURCE_INLINE = 'source.inline.script', diff --git a/x-pack/plugins/uptime/common/runtime_types/monitor_management/locations.ts b/x-pack/plugins/uptime/common/runtime_types/monitor_management/locations.ts index 26e3d726a10c0..56bc00290eecf 100644 --- a/x-pack/plugins/uptime/common/runtime_types/monitor_management/locations.ts +++ b/x-pack/plugins/uptime/common/runtime_types/monitor_management/locations.ts @@ -30,27 +30,34 @@ export const ServiceLocationCodec = t.interface({ }); export const ServiceLocationErrors = t.array( - t.intersection([ - t.interface({ - locationId: t.string, - error: t.interface({ + t.interface({ + locationId: t.string, + error: t.intersection([ + t.interface({ reason: t.string, status: t.number, }), - }), - t.partial({ - failed_monitors: t.array( - t.interface({ - id: t.string, - message: t.string, - }) - ), - }), - ]) + t.partial({ + failed_monitors: t.array( + t.interface({ + id: t.string, + message: t.string, + }) + ), + }), + ]), + }) ); export const ServiceLocationsCodec = t.array(ServiceLocationCodec); +export const LocationCodec = t.intersection([ + ServiceLocationCodec, + t.partial({ isServiceManaged: t.boolean }), +]); + +export const LocationsCodec = t.array(LocationCodec); + export const isServiceLocationInvalid = (location: ServiceLocation) => isLeft(ServiceLocationCodec.decode(location)); @@ -63,3 +70,4 @@ export type ServiceLocation = t.TypeOf; export type ServiceLocations = t.TypeOf; export type ServiceLocationsApiResponse = t.TypeOf; export type ServiceLocationErrors = t.TypeOf; +export type Locations = t.TypeOf; diff --git a/x-pack/plugins/uptime/common/runtime_types/monitor_management/monitor_types.ts b/x-pack/plugins/uptime/common/runtime_types/monitor_management/monitor_types.ts index 7117852800811..12791edc676a3 100644 --- a/x-pack/plugins/uptime/common/runtime_types/monitor_management/monitor_types.ts +++ b/x-pack/plugins/uptime/common/runtime_types/monitor_management/monitor_types.ts @@ -7,7 +7,7 @@ import * as t from 'io-ts'; import { ConfigKey } from './config_key'; -import { ServiceLocationsCodec } from './locations'; +import { LocationsCodec } from './locations'; import { DataStreamCodec, ModeCodec, @@ -55,13 +55,13 @@ export const CommonFieldsCodec = t.intersection([ [ConfigKey.MONITOR_TYPE]: DataStreamCodec, [ConfigKey.ENABLED]: t.boolean, [ConfigKey.SCHEDULE]: Schedule, - [ConfigKey.LOCATIONS]: t.array(t.string), [ConfigKey.APM_SERVICE_NAME]: t.string, [ConfigKey.TAGS]: t.array(t.string), - [ConfigKey.LOCATIONS]: ServiceLocationsCodec, + [ConfigKey.LOCATIONS]: LocationsCodec, }), t.partial({ [ConfigKey.TIMEOUT]: t.union([t.string, t.null]), + [ConfigKey.REVISION]: t.number, }), ]); diff --git a/x-pack/plugins/uptime/kibana.json b/x-pack/plugins/uptime/kibana.json index 461358c27fe3b..28a49067b6698 100644 --- a/x-pack/plugins/uptime/kibana.json +++ b/x-pack/plugins/uptime/kibana.json @@ -2,7 +2,7 @@ "configPath": ["xpack", "uptime"], "id": "uptime", "kibanaVersion": "kibana", - "optionalPlugins": ["cloud", "data", "fleet", "home", "ml"], + "optionalPlugins": ["cloud", "data", "fleet", "home", "ml", "telemetry"], "requiredPlugins": [ "alerting", "cases", diff --git a/x-pack/plugins/uptime/public/components/fleet_package/common/formatters.ts b/x-pack/plugins/uptime/public/components/fleet_package/common/formatters.ts index 72e9cbaa8a03a..a86894c3d7a48 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/common/formatters.ts +++ b/x-pack/plugins/uptime/public/components/fleet_package/common/formatters.ts @@ -24,6 +24,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.TAGS]: (fields) => arrayToJsonFormatter(fields[ConfigKey.TAGS]), [ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT] || undefined), [ConfigKey.NAMESPACE]: null, + [ConfigKey.REVISION]: null, }; export const arrayToJsonFormatter = (value: string[] = []) => diff --git a/x-pack/plugins/uptime/public/components/fleet_package/common/normalizers.ts b/x-pack/plugins/uptime/public/components/fleet_package/common/normalizers.ts index a7992b3f935b5..e71a0511cbaf1 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/common/normalizers.ts +++ b/x-pack/plugins/uptime/public/components/fleet_package/common/normalizers.ts @@ -82,4 +82,5 @@ export const commonNormalizers: CommonNormalizerMap = { [ConfigKey.TIMEOUT]: getCommonCronToSecondsNormalizer(ConfigKey.TIMEOUT), [ConfigKey.NAMESPACE]: (fields) => fields?.[ConfigKey.NAMESPACE]?.value ?? DEFAULT_NAMESPACE_STRING, + [ConfigKey.REVISION]: getCommonNormalizer(ConfigKey.REVISION), }; diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index b9dfd61e91b70..9efb7e36ebab9 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -7,6 +7,7 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import type { SavedObjectsClientContract, IScopedClusterClient, Logger } from 'src/core/server'; +import type { TelemetryPluginSetup, TelemetryPluginStart } from 'src/plugins/telemetry/server'; import { ObservabilityPluginSetup } from '../../../../../observability/server'; import { EncryptedSavedObjectsPluginSetup, @@ -21,6 +22,7 @@ import { PluginSetupContract } from '../../../../../features/server'; import { MlPluginSetup as MlSetup } from '../../../../../ml/server'; import { RuleRegistryPluginSetupContract } from '../../../../../rule_registry/server'; import { UptimeESClient } from '../../lib'; +import type { TelemetryEventsSender } from '../../telemetry/sender'; import type { UptimeRouter } from '../../../types'; import { SecurityPluginStart } from '../../../../../security/server'; import { CloudSetup } from '../../../../../cloud/server'; @@ -52,6 +54,7 @@ export interface UptimeServerSetup { syntheticsService: SyntheticsService; kibanaVersion: string; logger: Logger; + telemetry: TelemetryEventsSender; uptimeEsClient: UptimeESClient; } @@ -65,6 +68,7 @@ export interface UptimeCorePluginsSetup { ruleRegistry: RuleRegistryPluginSetupContract; encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; taskManager: TaskManagerSetupContract; + telemetry: TelemetryPluginSetup; } export interface UptimeCorePluginsStart { @@ -72,6 +76,7 @@ export interface UptimeCorePluginsStart { fleet: FleetStartContract; encryptedSavedObjects: EncryptedSavedObjectsPluginStart; taskManager: TaskManagerStartContract; + telemetry: TelemetryPluginStart; } export interface UMBackendFrameworkAdapter { diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts index 73386578618bb..9aee65e6fa14c 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts @@ -25,6 +25,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.TAGS]: (fields) => arrayFormatter(fields[ConfigKey.TAGS]), [ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT] || undefined), [ConfigKey.NAMESPACE]: null, + [ConfigKey.REVISION]: null, }; export const arrayFormatter = (value: string[] = []) => (value.length ? value : null); diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.test.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.test.ts index b2644d53e49d9..1da192ab24058 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.test.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.test.ts @@ -49,6 +49,7 @@ describe('getServiceLocations', function () { id: 'us_central', label: 'US Central', url: 'https://local.dev', + isServiceManaged: true, }, ], }); diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.ts index ffec06259f4e7..e746dafdb55d5 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/get_service_locations.ts @@ -8,13 +8,13 @@ import axios from 'axios'; import { ManifestLocation, - ServiceLocations, + Locations, ServiceLocationsApiResponse, } from '../../../common/runtime_types'; import { UptimeServerSetup } from '../adapters/framework'; export async function getServiceLocations(server: UptimeServerSetup) { - const locations: ServiceLocations = []; + const locations: Locations = []; if (!server.config.service?.manifestUrl) { return { locations }; @@ -31,6 +31,7 @@ export async function getServiceLocations(server: UptimeServerSetup) { label: location.geo.name, geo: location.geo.location, url: location.url, + isServiceManaged: true, }); }); diff --git a/x-pack/plugins/uptime/server/lib/telemetry/__mocks__/index.ts b/x-pack/plugins/uptime/server/lib/telemetry/__mocks__/index.ts new file mode 100644 index 0000000000000..2070aeca20861 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/__mocks__/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { TelemetryEventsSender } from '../sender'; + +/** + * Creates a mocked Telemetry Events Sender + */ +export const createMockTelemetryEventsSender = ( + enableTelemetry?: boolean +): jest.Mocked => { + return { + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + fetchTelemetryUrl: jest.fn(), + queueTelemetryEvents: jest.fn(), + isTelemetryOptedIn: jest.fn().mockReturnValue(enableTelemetry ?? jest.fn()), + sendIfDue: jest.fn(), + sendEvents: jest.fn(), + } as unknown as jest.Mocked; +}; diff --git a/x-pack/plugins/uptime/server/lib/telemetry/constants.ts b/x-pack/plugins/uptime/server/lib/telemetry/constants.ts new file mode 100644 index 0000000000000..11b5785031149 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/constants.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const MONITOR_UPDATE_CHANNEL = 'synthetics-monitor-update'; +export const MONITOR_CURRENT_CHANNEL = 'synthetics-monitor-current'; diff --git a/x-pack/plugins/uptime/server/lib/telemetry/queue.test.ts b/x-pack/plugins/uptime/server/lib/telemetry/queue.test.ts new file mode 100644 index 0000000000000..510b898387036 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/queue.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +/* eslint-disable dot-notation */ +import { TelemetryQueue } from './queue'; + +describe('TelemetryQueue', () => { + describe('queueTelemetryEvents', () => { + it('queues two events', () => { + const queue = new TelemetryQueue(); + queue.addEvents([{ 'event.kind': '1' }, { 'event.kind': '2' }]); + expect(queue['queue'].length).toBe(2); + }); + + it('queues more than maxQueueSize events', () => { + const queue = new TelemetryQueue(); + queue.addEvents([{ 'event.kind': '1' }, { 'event.kind': '2' }]); + queue['maxQueueSize'] = 5; + queue.addEvents([{ 'event.kind': '3' }, { 'event.kind': '4' }]); + queue.addEvents([{ 'event.kind': '5' }, { 'event.kind': '6' }]); + queue.addEvents([{ 'event.kind': '7' }, { 'event.kind': '8' }]); + expect(queue['queue'].length).toBe(5); + }); + + it('get and clear events', async () => { + const queue = new TelemetryQueue(); + queue.addEvents([{ 'event.kind': '1' }, { 'event.kind': '2' }]); + + expect(queue.getEvents().length).toBe(2); + + queue.clearEvents(); + + expect(queue['queue'].length).toBe(0); + }); + }); +}); diff --git a/x-pack/plugins/uptime/server/lib/telemetry/queue.ts b/x-pack/plugins/uptime/server/lib/telemetry/queue.ts new file mode 100644 index 0000000000000..3496cfb94915d --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/queue.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const TELEMETRY_MAX_QUEUE_SIZE = 100; + +export class TelemetryQueue { + private maxQueueSize = TELEMETRY_MAX_QUEUE_SIZE; + private queue: T[] = []; + + public addEvents(events: T[]) { + const qlength = this.queue.length; + + if (events.length === 0) { + return; + } + + if (qlength >= this.maxQueueSize) { + // we're full already + return; + } + + if (events.length > this.maxQueueSize - qlength) { + this.queue.push(...events.slice(0, this.maxQueueSize - qlength)); + } else { + this.queue.push(...events); + } + } + + public clearEvents() { + this.queue = []; + } + + public getEvents(): T[] { + return this.queue; + } +} diff --git a/x-pack/plugins/uptime/server/lib/telemetry/sender.test.ts b/x-pack/plugins/uptime/server/lib/telemetry/sender.test.ts new file mode 100644 index 0000000000000..91caf31883c51 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/sender.test.ts @@ -0,0 +1,148 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* eslint-disable dot-notation */ + +import { URL } from 'url'; + +import axios from 'axios'; + +import type { InfoResponse } from '@elastic/elasticsearch/lib/api/types'; + +import { loggingSystemMock } from 'src/core/server/mocks'; + +import { MONITOR_UPDATE_CHANNEL } from './constants'; + +import { TelemetryEventsSender } from './sender'; + +jest.mock('axios', () => { + return { + post: jest.fn(), + }; +}); + +describe('TelemetryEventsSender', () => { + let logger: ReturnType; + let sender: TelemetryEventsSender; + const sampleEvent = { + configId: '12345', + stackVersion: '8.1.0', + type: 'http', + locations: ['us_central'], + locationsCount: 1, + monitorNameLength: 8, + monitorInterval: 180000, + revision: 1, + }; + + beforeEach(() => { + logger = loggingSystemMock.createLogger(); + sender = new TelemetryEventsSender(logger); + sender['fetchClusterInfo'] = jest.fn(async () => { + return { + cluster_uuid: '1', + cluster_name: 'name', + version: { + number: '8.0.0', + }, + } as InfoResponse; + }); + sender.start(undefined, { + elasticsearch: { client: { asInternalUser: { info: jest.fn(async () => ({})) } } }, + } as any); + }); + + describe('queueTelemetryEvents', () => { + it('queues two events', () => { + sender.queueTelemetryEvents(MONITOR_UPDATE_CHANNEL, [sampleEvent]); + expect(sender['queuesPerChannel'][MONITOR_UPDATE_CHANNEL]).toBeDefined(); + }); + + it('should send events when due', async () => { + sender['telemetryStart'] = { + getIsOptedIn: jest.fn(async () => true), + }; + sender['telemetrySetup'] = { + getTelemetryUrl: jest.fn( + async () => new URL('https://telemetry-staging.elastic.co/v3/send/snapshot') + ), + }; + + sender.queueTelemetryEvents(MONITOR_UPDATE_CHANNEL, [sampleEvent]); + sender['sendEvents'] = jest.fn(); + + await sender['sendIfDue'](); + + expect(sender['sendEvents']).toHaveBeenCalledWith( + `https://telemetry-staging.elastic.co/v3-dev/send/${MONITOR_UPDATE_CHANNEL}`, + { cluster_name: 'name', cluster_uuid: '1', version: { number: '8.0.0' } }, + expect.anything() + ); + }); + + it("shouldn't send when telemetry is disabled", async () => { + const telemetryStart = { + getIsOptedIn: jest.fn(async () => false), + }; + sender['telemetryStart'] = telemetryStart; + + sender.queueTelemetryEvents(MONITOR_UPDATE_CHANNEL, [sampleEvent]); + sender['sendEvents'] = jest.fn(); + + await sender['sendIfDue'](); + + expect(sender['sendEvents']).toBeCalledTimes(0); + }); + + it('should send events to separate channels', async () => { + sender['telemetryStart'] = { + getIsOptedIn: jest.fn(async () => true), + }; + sender['telemetrySetup'] = { + getTelemetryUrl: jest.fn( + async () => new URL('https://telemetry.elastic.co/v3/send/snapshot') + ), + }; + + const myChannelEvents = [{ 'event.kind': '1' }, { 'event.kind': '2' }]; + // @ts-ignore + sender.queueTelemetryEvents('my-channel', myChannelEvents); + sender['queuesPerChannel']['my-channel']['getEvents'] = jest.fn(() => myChannelEvents); + + expect(sender['queuesPerChannel']['my-channel']['queue'].length).toBe(2); + + const myChannel2Events = [{ 'event.kind': '3' }]; + // @ts-ignore + sender.queueTelemetryEvents('my-channel2', myChannel2Events); + sender['queuesPerChannel']['my-channel2']['getEvents'] = jest.fn(() => myChannel2Events); + + expect(sender['queuesPerChannel']['my-channel2']['queue'].length).toBe(1); + + await sender['sendIfDue'](); + + expect(sender['queuesPerChannel']['my-channel']['getEvents']).toBeCalledTimes(1); + expect(sender['queuesPerChannel']['my-channel2']['getEvents']).toBeCalledTimes(1); + const headers = { + headers: { + 'Content-Type': 'application/x-ndjson', + 'X-Elastic-Cluster-ID': '1', + 'X-Elastic-Stack-Version': '8.0.0', + }, + }; + expect(axios.post).toHaveBeenCalledWith( + 'https://telemetry.elastic.co/v3/send/my-channel', + '{"event.kind":"1"}\n{"event.kind":"2"}\n', + headers + ); + expect(axios.post).toHaveBeenCalledWith( + 'https://telemetry.elastic.co/v3/send/my-channel2', + '{"event.kind":"3"}\n', + headers + ); + }); + }); +}); diff --git a/x-pack/plugins/uptime/server/lib/telemetry/sender.ts b/x-pack/plugins/uptime/server/lib/telemetry/sender.ts new file mode 100644 index 0000000000000..f1c86b14e50c8 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/sender.ts @@ -0,0 +1,195 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CoreStart, ElasticsearchClient, Logger } from 'src/core/server'; +import type { TelemetryPluginStart, TelemetryPluginSetup } from 'src/plugins/telemetry/server'; + +import { cloneDeep } from 'lodash'; + +import axios from 'axios'; + +import type { InfoResponse } from '@elastic/elasticsearch/lib/api/types'; + +import { TelemetryQueue } from './queue'; + +import type { MonitorUpdateTelemetryChannel, MonitorUpdateTelemetryChannelEvents } from './types'; + +/** + * Simplified version of https://github.com/elastic/kibana/blob/master/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts + * Sends batched events to telemetry v3 api + */ +export class TelemetryEventsSender { + private readonly initialCheckDelayMs = 10 * 1000; + private readonly checkIntervalMs = 30 * 1000; + private readonly logger: Logger; + + private telemetryStart?: TelemetryPluginStart; + private telemetrySetup?: TelemetryPluginSetup; + private intervalId?: NodeJS.Timeout; + private isSending = false; + private queuesPerChannel: { [channel: string]: TelemetryQueue } = {}; + private isOptedIn?: boolean = true; // Assume true until the first check + private esClient?: ElasticsearchClient; + private clusterInfo?: InfoResponse; + + constructor(logger: Logger) { + this.logger = logger; + } + + public setup(telemetrySetup?: TelemetryPluginSetup) { + this.telemetrySetup = telemetrySetup; + } + + public async start(telemetryStart?: TelemetryPluginStart, core?: CoreStart) { + this.telemetryStart = telemetryStart; + this.esClient = core?.elasticsearch.client.asInternalUser; + this.clusterInfo = await this.fetchClusterInfo(); + + this.logger.debug(`Starting local task`); + setTimeout(() => { + this.sendIfDue(); + this.intervalId = setInterval(() => this.sendIfDue(), this.checkIntervalMs); + }, this.initialCheckDelayMs); + } + + public stop() { + if (this.intervalId) { + clearInterval(this.intervalId); + } + } + + public queueTelemetryEvents( + channel: T, + events: Array + ) { + if (!this.queuesPerChannel[channel]) { + this.queuesPerChannel[channel] = new TelemetryQueue(); + } + this.queuesPerChannel[channel].addEvents(cloneDeep(events)); + } + + public async isTelemetryOptedIn() { + this.isOptedIn = await this.telemetryStart?.getIsOptedIn(); + return this.isOptedIn === true; + } + + private async sendIfDue() { + if (this.isSending) { + return; + } + + this.isSending = true; + + this.isOptedIn = await this.isTelemetryOptedIn(); + if (!this.isOptedIn) { + this.logger.debug(`Telemetry is not opted-in.`); + for (const channel of Object.keys(this.queuesPerChannel)) { + this.queuesPerChannel[channel].clearEvents(); + } + this.isSending = false; + return; + } + + for (const channel of Object.keys(this.queuesPerChannel)) { + await this.sendEvents( + await this.fetchTelemetryUrl(channel), + this.clusterInfo, + this.queuesPerChannel[channel] + ); + } + + this.isSending = false; + } + + private async fetchClusterInfo(): Promise { + if (this.esClient === undefined || this.esClient === null) { + throw Error('elasticsearch client is unavailable: cannot retrieve cluster infomation'); + } + + return await this.esClient.info(); + } + + public async sendEvents( + telemetryUrl: string, + clusterInfo: InfoResponse | undefined, + queue: TelemetryQueue + ) { + const events = queue.getEvents(); + if (events.length === 0) { + return; + } + + try { + this.logger.debug(`Telemetry URL: ${telemetryUrl}`); + + queue.clearEvents(); + + this.logger.debug(JSON.stringify(events)); + + await this.send( + events, + telemetryUrl, + clusterInfo?.cluster_uuid, + clusterInfo?.version?.number + ); + } catch (err) { + this.logger.debug(`Error sending telemetry events data: ${err}`); + queue.clearEvents(); + } + } + + // Forms URLs like: + // https://telemetry.elastic.co/v3/send/my-channel-name or + // https://telemetry-staging.elastic.co/v3/send/my-channel-name + private async fetchTelemetryUrl(channel: string): Promise { + const telemetryUrl = await this.telemetrySetup?.getTelemetryUrl(); + if (!telemetryUrl) { + throw Error("Couldn't get telemetry URL"); + } + if (!telemetryUrl.hostname.includes('staging')) { + telemetryUrl.pathname = `/v3/send/${channel}`; + } else { + telemetryUrl.pathname = `/v3-dev/send/${channel}`; + } + return telemetryUrl.toString(); + } + + private async send( + events: unknown[], + telemetryUrl: string, + clusterUuid: string | undefined, + clusterVersionNumber: string | undefined + ) { + // using ndjson so that each line will be wrapped in json envelope on server side + // see https://github.com/elastic/infra/blob/master/docs/telemetry/telemetry-next-dataflow.md#json-envelope + const ndjson = this.transformDataToNdjson(events); + + try { + const resp = await axios.post(telemetryUrl, ndjson, { + headers: { + 'Content-Type': 'application/x-ndjson', + 'X-Elastic-Cluster-ID': clusterUuid, + 'X-Elastic-Stack-Version': clusterVersionNumber ? clusterVersionNumber : '8.2.0', + }, + }); + this.logger.debug(`Events sent!. Response: ${resp.status} ${JSON.stringify(resp.data)}`); + } catch (err) { + this.logger.debug( + `Error sending events: ${err.response.status} ${JSON.stringify(err.response.data)}` + ); + } + } + + private transformDataToNdjson = (data: unknown[]): string => { + if (data.length !== 0) { + const dataString = data.map((dataItem) => JSON.stringify(dataItem)).join('\n'); + return `${dataString}\n`; + } else { + return ''; + } + }; +} diff --git a/x-pack/plugins/uptime/server/lib/telemetry/types.ts b/x-pack/plugins/uptime/server/lib/telemetry/types.ts new file mode 100644 index 0000000000000..59d060c2f3a76 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/telemetry/types.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ServiceLocationErrors } from '../../../common/runtime_types/monitor_management'; + +export interface MonitorUpdateEvent { + updatedAt?: string; + lastUpdatedAt?: string; + durationSinceLastUpdated?: number; + deletedAt?: string; + type: string; + stackVersion: string; + monitorNameLength: number; + monitorInterval: number; + locations: string[]; + locationsCount: number; + scriptType?: 'inline' | 'recorder' | 'zip'; + revision?: number; + errors?: ServiceLocationErrors; + configId: string; +} + +export interface MonitorUpdateTelemetryChannelEvents { + // channel name => event type + 'synthetics-monitor-update': MonitorUpdateEvent; + 'synthetics-monitor-current': MonitorUpdateEvent; +} + +export type MonitorUpdateTelemetryChannel = keyof MonitorUpdateTelemetryChannelEvents; diff --git a/x-pack/plugins/uptime/server/plugin.ts b/x-pack/plugins/uptime/server/plugin.ts index 4dc8437cbbcb6..d2afb3f16fb6a 100644 --- a/x-pack/plugins/uptime/server/plugin.ts +++ b/x-pack/plugins/uptime/server/plugin.ts @@ -21,6 +21,7 @@ import { UptimeCorePluginsStart, UptimeServerSetup, } from './lib/adapters'; +import { TelemetryEventsSender } from './lib/telemetry/sender'; import { registerUptimeSavedObjects, savedObjectsAdapter } from './lib/saved_objects/saved_objects'; import { mappingFromFieldMap } from '../../rule_registry/common/mapping_from_field_map'; import { experimentalRuleFieldMap } from '../../rule_registry/common/assets/field_maps/experimental_rule_field_map'; @@ -37,11 +38,13 @@ export class Plugin implements PluginType { private logger: Logger; private server?: UptimeServerSetup; private syntheticService?: SyntheticsService; + private readonly telemetryEventsSender: TelemetryEventsSender; private readonly isServiceEnabled?: boolean; constructor(initializerContext: PluginInitializerContext) { this.initContext = initializerContext; this.logger = initializerContext.logger.get(); + this.telemetryEventsSender = new TelemetryEventsSender(this.logger); const config = this.initContext.config.get(); this.isServiceEnabled = config?.ui?.monitorManagement?.enabled && Boolean(config.service); } @@ -76,6 +79,7 @@ export class Plugin implements PluginType { cloud: plugins.cloud, kibanaVersion: this.initContext.env.packageInfo.version, logger: this.logger, + telemetry: this.telemetryEventsSender, } as UptimeServerSetup; if (this.isServiceEnabled && this.server.config.service) { @@ -86,6 +90,7 @@ export class Plugin implements PluginType { ); this.syntheticService.registerSyncTask(plugins.taskManager); + this.telemetryEventsSender.setup(plugins.telemetry); } initServerWithKibana(this.server, plugins, ruleDataClient, this.logger); @@ -130,6 +135,7 @@ export class Plugin implements PluginType { if (this.server && this.syntheticService) { this.server.syntheticsService = this.syntheticService; } + this.telemetryEventsSender.start(plugins.telemetry, coreStart); } } diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts index 38def648f6e5c..29c2210efd20a 100644 --- a/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/add_monitor.ts @@ -5,11 +5,13 @@ * 2.0. */ import { schema } from '@kbn/config-schema'; +import { SavedObject } from 'kibana/server'; import { MonitorFields, SyntheticsMonitor } from '../../../common/runtime_types'; import { UMRestApiRouteFactory } from '../types'; import { API_URLS } from '../../../common/constants'; import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor'; import { validateMonitor } from './monitor_validation'; +import { sendTelemetryEvents, formatTelemetryEvent } from './telemetry/monitor_upgrade_sender'; export const addSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ method: 'POST', @@ -27,10 +29,11 @@ export const addSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ return response.badRequest({ body: { message, attributes: { details, ...payload } } }); } - const newMonitor = await savedObjectsClient.create( - syntheticsMonitorType, - monitor - ); + const newMonitor: SavedObject = + await savedObjectsClient.create(syntheticsMonitorType, { + ...monitor, + revision: 1, + }); const { syntheticsService } = server; @@ -45,6 +48,12 @@ export const addSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ }, ]); + sendTelemetryEvents( + server.logger, + server.telemetry, + formatTelemetryEvent({ monitor: newMonitor, errors, kibanaVersion: server.kibanaVersion }) + ); + if (errors) { return errors; } diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts index c1a1ea8945606..bbdb6818b3f6a 100644 --- a/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/delete_monitor.ts @@ -11,6 +11,10 @@ import { UMRestApiRouteFactory } from '../types'; import { API_URLS } from '../../../common/constants'; import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor'; import { getMonitorNotFoundResponse } from './service_errors'; +import { + sendTelemetryEvents, + formatTelemetryDeleteEvent, +} from './telemetry/monitor_upgrade_sender'; export const deleteSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ method: 'DELETE', @@ -36,6 +40,12 @@ export const deleteSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ { ...monitor.attributes, id: monitorId }, ]); + sendTelemetryEvents( + server.logger, + server.telemetry, + formatTelemetryDeleteEvent(monitor, server.kibanaVersion, new Date().toISOString(), errors) + ); + if (errors) { return errors; } diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts index 62a542b2b2037..d8a6ec85e770e 100644 --- a/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/edit_monitor.ts @@ -6,14 +6,18 @@ */ import { schema } from '@kbn/config-schema'; -import { SavedObjectsUpdateResponse } from 'kibana/server'; +import { SavedObjectsUpdateResponse, SavedObject } from 'kibana/server'; import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; -import { MonitorFields, SyntheticsMonitor } from '../../../common/runtime_types'; +import { MonitorFields, SyntheticsMonitor, ConfigKey } from '../../../common/runtime_types'; import { UMRestApiRouteFactory } from '../types'; import { API_URLS } from '../../../common/constants'; import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor'; import { validateMonitor } from './monitor_validation'; import { getMonitorNotFoundResponse } from './service_errors'; +import { + sendTelemetryEvents, + formatTelemetryUpdateEvent, +} from './telemetry/monitor_upgrade_sender'; // Simplify return promise type and type it with runtime_types export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ @@ -40,11 +44,20 @@ export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ const { syntheticsService } = server; try { + const previousMonitor: SavedObject = await savedObjectsClient.get( + syntheticsMonitorType, + monitorId + ); + const monitorWithRevision = { + ...monitor, + revision: (previousMonitor.attributes[ConfigKey.REVISION] || 0) + 1, + }; + const editMonitor: SavedObjectsUpdateResponse = await savedObjectsClient.update( syntheticsMonitorType, monitorId, - monitor.type === 'browser' ? { ...monitor, urls: '' } : monitor + monitor.type === 'browser' ? { ...monitorWithRevision, urls: '' } : monitorWithRevision ); const errors = await syntheticsService.pushConfigs(request, [ @@ -58,6 +71,12 @@ export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({ }, ]); + sendTelemetryEvents( + server.logger, + server.telemetry, + formatTelemetryUpdateEvent(editMonitor, previousMonitor, server.kibanaVersion, errors) + ); + // Return service sync errors in OK response if (errors) { return errors; diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts new file mode 100644 index 0000000000000..24734c88301f1 --- /dev/null +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.test.ts @@ -0,0 +1,215 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { sha256 } from 'js-sha256'; +import type { Logger } from 'src/core/server'; +import { loggingSystemMock } from 'src/core/server/mocks'; +import { SavedObject } from 'kibana/server'; +import { + SyntheticsMonitor, + ConfigKey, + DataStream, + ScheduleUnit, +} from '../../../../common/runtime_types/monitor_management'; + +import type { TelemetryEventsSender } from '../../../lib/telemetry/sender'; +import { createMockTelemetryEventsSender } from '../../../lib/telemetry/__mocks__'; + +import { MONITOR_UPDATE_CHANNEL, MONITOR_CURRENT_CHANNEL } from '../../../lib/telemetry/constants'; + +import { + formatTelemetryEvent, + formatTelemetryUpdateEvent, + formatTelemetryDeleteEvent, + sendTelemetryEvents, +} from './monitor_upgrade_sender'; + +const kibanaVersion = '8.2.0'; +const id = '123456'; +const errors = [ + { + locationId: 'us_central', + error: { + reason: 'my reason', + status: 400, + }, + }, +]; +const testConfig: SavedObject = { + updated_at: '2011-10-05T14:48:00.000Z', + id, + attributes: { + [ConfigKey.MONITOR_TYPE]: DataStream.HTTP, + [ConfigKey.LOCATIONS]: [ + { + id: 'us_central', + label: 'US Central', + url: 'testurl.com', + geo: { + lat: 0, + lon: 0, + }, + isServiceManaged: true, + }, + { + id: 'custom', + label: 'Custom US Central', + url: 'testurl.com', + geo: { + lat: 0, + lon: 0, + }, + }, + ], + [ConfigKey.SCHEDULE]: { number: '3', unit: ScheduleUnit.MINUTES }, + [ConfigKey.URLS]: 'https://elastic.co', + [ConfigKey.NAME]: 'Test', + [ConfigKey.REVISION]: 1, + } as SyntheticsMonitor, +} as SavedObject; +const createTestConfig = (extraConfigs: Record, updatedAt?: string) => { + return { + ...testConfig, + updated_at: updatedAt || testConfig.updated_at, + attributes: { + ...testConfig.attributes, + ...extraConfigs, + }, + } as SavedObject; +}; + +describe('monitor upgrade telemetry helpers', () => { + it('formats telemetry events', () => { + const actual = formatTelemetryEvent({ monitor: testConfig, kibanaVersion, errors }); + expect(actual).toEqual({ + stackVersion: kibanaVersion, + configId: sha256.create().update(testConfig.id).hex(), + locations: ['us_central', 'other'], + locationsCount: 2, + monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, + updatedAt: testConfig.updated_at, + type: testConfig.attributes[ConfigKey.MONITOR_TYPE], + scriptType: undefined, + monitorInterval: 180000, + lastUpdatedAt: undefined, + deletedAt: undefined, + errors, + durationSinceLastUpdated: undefined, + revision: 1, + }); + }); + + it.each([ + [ConfigKey.SOURCE_INLINE, 'recorder', true], + [ConfigKey.SOURCE_INLINE, 'inline', false], + [ConfigKey.SOURCE_ZIP_URL, 'zip', false], + ])('handles formatting scriptType for browser monitors', (config, scriptType, isRecorder) => { + const actual = formatTelemetryEvent({ + monitor: createTestConfig({ + [config]: 'test', + [ConfigKey.METADATA]: { + script_source: { + is_generated_script: isRecorder, + }, + }, + }), + kibanaVersion, + errors, + }); + expect(actual).toEqual({ + stackVersion: kibanaVersion, + configId: sha256.create().update(testConfig.id).hex(), + locations: ['us_central', 'other'], + locationsCount: 2, + monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, + updatedAt: testConfig.updated_at, + type: testConfig.attributes[ConfigKey.MONITOR_TYPE], + scriptType, + monitorInterval: 180000, + lastUpdatedAt: undefined, + deletedAt: undefined, + errors, + durationSinceLastUpdated: undefined, + revision: 1, + }); + }); + + it('handles formatting update events', () => { + const actual = formatTelemetryUpdateEvent( + createTestConfig({}, '2011-10-05T16:48:00.000Z'), + testConfig, + kibanaVersion, + errors + ); + expect(actual).toEqual({ + stackVersion: kibanaVersion, + configId: sha256.create().update(testConfig.id).hex(), + locations: ['us_central', 'other'], + locationsCount: 2, + monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, + updatedAt: '2011-10-05T16:48:00.000Z', + type: testConfig.attributes[ConfigKey.MONITOR_TYPE], + scriptType: undefined, + monitorInterval: 180000, + lastUpdatedAt: testConfig.updated_at, + deletedAt: undefined, + errors, + durationSinceLastUpdated: 7200000, + revision: 1, + }); + }); + + it('handles formatting delete events', () => { + const actual = formatTelemetryDeleteEvent( + testConfig, + kibanaVersion, + '2011-10-05T16:48:00.000Z', + errors + ); + expect(actual).toEqual({ + stackVersion: kibanaVersion, + configId: sha256.create().update(testConfig.id).hex(), + locations: ['us_central', 'other'], + locationsCount: 2, + monitorNameLength: testConfig.attributes[ConfigKey.NAME].length, + updatedAt: '2011-10-05T16:48:00.000Z', + type: testConfig.attributes[ConfigKey.MONITOR_TYPE], + scriptType: undefined, + monitorInterval: 180000, + lastUpdatedAt: testConfig.updated_at, + deletedAt: '2011-10-05T16:48:00.000Z', + errors, + durationSinceLastUpdated: 7200000, + revision: 1, + }); + }); +}); + +describe('sendTelemetryEvents', () => { + let eventsTelemetryMock: jest.Mocked; + let loggerMock: jest.Mocked; + + beforeEach(() => { + eventsTelemetryMock = createMockTelemetryEventsSender(); + loggerMock = loggingSystemMock.createLogger(); + }); + + it('should queue telemetry events with generic error', () => { + const event = formatTelemetryEvent({ monitor: testConfig, kibanaVersion, errors }); + sendTelemetryEvents( + loggerMock, + eventsTelemetryMock, + formatTelemetryEvent({ monitor: testConfig, kibanaVersion, errors }) + ); + + expect(eventsTelemetryMock.queueTelemetryEvents).toHaveBeenCalledWith(MONITOR_UPDATE_CHANNEL, [ + event, + ]); + expect(eventsTelemetryMock.queueTelemetryEvents).toHaveBeenCalledWith(MONITOR_CURRENT_CHANNEL, [ + event, + ]); + }); +}); diff --git a/x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts b/x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts new file mode 100644 index 0000000000000..d4ac7c85c9586 --- /dev/null +++ b/x-pack/plugins/uptime/server/rest_api/synthetics_service/telemetry/monitor_upgrade_sender.ts @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { sha256 } from 'js-sha256'; +import type { Logger } from 'src/core/server'; +import { SavedObjectsUpdateResponse, SavedObject } from 'kibana/server'; +import { + MonitorFields, + SyntheticsMonitor, + ConfigKey, + ServiceLocationErrors, +} from '../../../../common/runtime_types'; +import type { MonitorUpdateEvent } from '../../../lib/telemetry/types'; + +import { TelemetryEventsSender } from '../../../lib/telemetry/sender'; +import { MONITOR_UPDATE_CHANNEL, MONITOR_CURRENT_CHANNEL } from '../../../lib/telemetry/constants'; + +export interface UpgradeError { + key?: string; + message: string | string[]; +} + +export function sendTelemetryEvents( + logger: Logger, + eventsTelemetry: TelemetryEventsSender | undefined, + updateEvent: MonitorUpdateEvent +) { + if (eventsTelemetry === undefined) { + return; + } + + try { + eventsTelemetry.queueTelemetryEvents(MONITOR_UPDATE_CHANNEL, [updateEvent]); + eventsTelemetry.queueTelemetryEvents(MONITOR_CURRENT_CHANNEL, [updateEvent]); + } catch (exc) { + logger.error(`queing telemetry events failed ${exc}`); + } +} + +export function formatTelemetryEvent({ + monitor, + kibanaVersion, + lastUpdatedAt, + durationSinceLastUpdated, + deletedAt, + errors, +}: { + monitor: SavedObject; + kibanaVersion: string; + lastUpdatedAt?: string; + durationSinceLastUpdated?: number; + deletedAt?: string; + errors?: ServiceLocationErrors; +}) { + const { attributes } = monitor; + + return { + updatedAt: deletedAt || monitor.updated_at, + lastUpdatedAt, + durationSinceLastUpdated, + deletedAt, + type: attributes[ConfigKey.MONITOR_TYPE], + locations: attributes[ConfigKey.LOCATIONS].map((location) => + location.isServiceManaged ? location.id : 'other' + ), // mark self-managed locations as other + locationsCount: attributes[ConfigKey.LOCATIONS].length, + monitorNameLength: attributes[ConfigKey.NAME].length, + monitorInterval: parseInt(attributes[ConfigKey.SCHEDULE].number, 10) * 60 * 1000, + stackVersion: kibanaVersion, + scriptType: getScriptType(attributes as MonitorFields), + errors: + errors && errors?.length + ? errors.map((e) => ({ + locationId: e.locationId, + error: { + // don't expose failed_monitors on error object + status: e.error?.status, + reason: e.error?.reason, + }, + })) + : undefined, + configId: sha256.create().update(monitor.id).hex(), + revision: attributes[ConfigKey.REVISION], + }; +} + +export function formatTelemetryUpdateEvent( + currentMonitor: SavedObjectsUpdateResponse, + previousMonitor: SavedObject, + kibanaVersion: string, + errors?: ServiceLocationErrors +) { + let durationSinceLastUpdated: number = 0; + if (currentMonitor.updated_at && previousMonitor.updated_at) { + durationSinceLastUpdated = + new Date(currentMonitor.updated_at).getTime() - + new Date(previousMonitor.updated_at).getTime(); + } + + return formatTelemetryEvent({ + monitor: currentMonitor as SavedObject, + kibanaVersion, + durationSinceLastUpdated, + lastUpdatedAt: previousMonitor.updated_at, + errors, + }); +} + +export function formatTelemetryDeleteEvent( + previousMonitor: SavedObject, + kibanaVersion: string, + deletedAt: string, + errors?: ServiceLocationErrors +) { + let durationSinceLastUpdated: number = 0; + if (deletedAt && previousMonitor.updated_at) { + durationSinceLastUpdated = + new Date(deletedAt).getTime() - new Date(previousMonitor.updated_at).getTime(); + } + + return formatTelemetryEvent({ + monitor: previousMonitor as SavedObject, + kibanaVersion, + durationSinceLastUpdated, + lastUpdatedAt: previousMonitor.updated_at, + deletedAt, + errors, + }); +} + +function getScriptType(attributes: MonitorFields): 'inline' | 'recorder' | 'zip' | undefined { + if (attributes[ConfigKey.SOURCE_ZIP_URL]) { + return 'zip'; + } else if ( + attributes[ConfigKey.SOURCE_INLINE] && + attributes[ConfigKey.METADATA].script_source?.is_generated_script + ) { + return 'recorder'; + } else if (attributes[ConfigKey.SOURCE_INLINE]) { + return 'inline'; + } + + return undefined; +} diff --git a/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts index 13581bcfc3e7f..c453d28259a2c 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts @@ -53,7 +53,7 @@ export default function ({ getService }: FtrProviderContext) { [ConfigKey.NAME]: 'Modified name', }; - const modifiedMonitor = { ...savedMonitor, ...updates }; + const modifiedMonitor = { ...savedMonitor, ...updates, revision: 2 }; const editResponse = await supertest .put(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId) diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json index 01a8ecd409fb3..cd75c25a07798 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json @@ -58,5 +58,6 @@ }, "url": "https://example-url.com" }], - "namespace": "testnamespace" + "namespace": "testnamespace", + "revision": 1 } diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts index b9e913524cb1f..a6ff54ccc7eb2 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts @@ -19,7 +19,7 @@ interface CheckProps { mogrify?: (doc: any) => any; refresh?: boolean; tls?: boolean | TlsProps; - isFleetManaged?: boolean; + customIndex?: string; } const getRandomMonitorId = () => { @@ -33,11 +33,11 @@ export const makeCheck = async ({ mogrify = (d) => d, refresh = true, tls = false, - isFleetManaged = false, + customIndex, }: CheckProps): Promise<{ monitorId: string; docs: any }> => { const cgFields = { monitor: { - check_group: uuid.v4(), + check_group: fields.monitor?.check_group || uuid.v4(), }, }; @@ -52,18 +52,10 @@ export const makeCheck = async ({ ip: `127.0.0.${i}`, }, }); - if (i === numIps - 1) { + if (i === numIps - 1 && fields.summary !== null) { pingFields.summary = summary; } - const doc = await makePing( - es, - monitorId, - pingFields, - mogrify, - false, - tls as any, - isFleetManaged - ); + const doc = await makePing(es, monitorId, pingFields, mogrify, false, tls as any, customIndex); docs.push(doc); // @ts-ignore summary[doc.monitor.status]++; @@ -85,7 +77,7 @@ export const makeChecks = async ( fields: { [key: string]: any } = {}, mogrify: (doc: any) => any = (d) => d, refresh: boolean = true, - isFleetManaged: boolean = false + customIndex?: string ) => { const checks = []; const oldestTime = new Date().getTime() - numChecks * every; @@ -109,7 +101,7 @@ export const makeChecks = async ( fields, mogrify, refresh: false, - isFleetManaged, + customIndex, }); checks.push(docs); } @@ -131,7 +123,7 @@ export const makeChecksWithStatus = async ( status: 'up' | 'down', mogrify: (doc: any) => any = (d) => d, refresh: boolean = true, - isFleetManaged: boolean = false + customIndex?: string ) => { const oppositeStatus = status === 'up' ? 'down' : 'up'; @@ -152,7 +144,7 @@ export const makeChecksWithStatus = async ( return mogrify(d); }, refresh, - isFleetManaged + customIndex ); }; diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts index 29421345393a8..e663aa36cadc5 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts @@ -11,7 +11,6 @@ import type { Client } from '@elastic/elasticsearch'; import { makeTls, TlsProps } from './make_tls'; const DEFAULT_INDEX_NAME = 'heartbeat-8-generated-test'; -const DATA_STREAM_INDEX_NAME = 'synthetics-http-default'; export const makePing = async ( es: Client, @@ -20,7 +19,7 @@ export const makePing = async ( mogrify: (doc: any) => any, refresh: boolean = true, tls: boolean | TlsProps = false, - isFleetManaged: boolean | undefined = false + customIndex?: string ) => { const timestamp = new Date(); const baseDoc: any = { @@ -118,7 +117,7 @@ export const makePing = async ( const doc = mogrify(merge(baseDoc, fields)); await es.index({ - index: isFleetManaged ? DATA_STREAM_INDEX_NAME : DEFAULT_INDEX_NAME, + index: customIndex || DEFAULT_INDEX_NAME, refresh, body: doc, }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors_fleet.ts b/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors_fleet.ts index 84d6d71a4ab6d..ff257c152daa9 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors_fleet.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors_fleet.ts @@ -81,7 +81,7 @@ export default function ({ getService }: FtrProviderContext) { 'up', undefined, undefined, - true + testDataStreamName ); await makeChecksWithStatus( @@ -100,7 +100,7 @@ export default function ({ getService }: FtrProviderContext) { 'down', undefined, undefined, - true + testDataStreamName ); await makeChecksWithStatus( @@ -118,7 +118,7 @@ export default function ({ getService }: FtrProviderContext) { 'down', undefined, undefined, - true + testDataStreamName ); await makeChecksWithStatus( @@ -137,7 +137,7 @@ export default function ({ getService }: FtrProviderContext) { 'down', undefined, undefined, - true + testDataStreamName ); await makeChecksWithStatus( @@ -150,7 +150,7 @@ export default function ({ getService }: FtrProviderContext) { 'down', undefined, undefined, - true + testDataStreamName ); await client.indices.refresh(); }); From 09f8eefe918ccf38b9857a4ccc6681572a89383d Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Wed, 16 Feb 2022 12:45:53 -0500 Subject: [PATCH 023/104] [Fleet] Remove unused api_key property from the output model (#125801) --- x-pack/plugins/fleet/common/openapi/bundled.json | 3 --- x-pack/plugins/fleet/common/openapi/bundled.yaml | 2 -- .../fleet/common/openapi/components/schemas/output.yaml | 2 -- x-pack/plugins/fleet/common/types/models/agent_policy.ts | 2 +- x-pack/plugins/fleet/common/types/models/output.ts | 1 - .../__snapshots__/full_agent_policy.test.ts.snap | 6 ------ .../services/agent_policies/full_agent_policy.test.ts | 7 ------- .../server/services/agent_policies/full_agent_policy.ts | 4 +--- x-pack/plugins/fleet/server/types/models/output.ts | 1 - 9 files changed, 2 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 432e72db05e8c..bc6fd8bff0da0 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -4226,9 +4226,6 @@ "ca_trusted_fingerprint": { "type": "string" }, - "api_key": { - "type": "string" - }, "config": { "type": "object" }, diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 439f56da63e5e..50a7463029f98 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -2664,8 +2664,6 @@ components: type: string ca_trusted_fingerprint: type: string - api_key: - type: string config: type: object config_yaml: diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml index a91ec2cb14e94..75823d02af865 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml @@ -20,8 +20,6 @@ properties: type: string ca_trusted_fingerprint: type: string - api_key: - type: string config: type: object config_yaml: diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index d8dec7e64a6af..6fbb423507c3b 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -75,7 +75,7 @@ export interface FullAgentPolicyOutputPermissions { }; } -export type FullAgentPolicyOutput = Pick & { +export type FullAgentPolicyOutput = Pick & { [key: string]: any; }; diff --git a/x-pack/plugins/fleet/common/types/models/output.ts b/x-pack/plugins/fleet/common/types/models/output.ts index 2ff50c0fc7bdb..ba09d41d2874f 100644 --- a/x-pack/plugins/fleet/common/types/models/output.ts +++ b/x-pack/plugins/fleet/common/types/models/output.ts @@ -18,7 +18,6 @@ export interface NewOutput { hosts?: string[]; ca_sha256?: string; ca_trusted_fingerprint?: string; - api_key?: string; config_yaml?: string; is_preconfigured?: boolean; } diff --git a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap index 585eca4919eaf..eccd218b42447 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap +++ b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap @@ -46,7 +46,6 @@ Object { }, "outputs": Object { "data-output-id": Object { - "api_key": undefined, "ca_sha256": undefined, "hosts": Array [ "http://es-data.co:9201", @@ -54,7 +53,6 @@ Object { "type": "elasticsearch", }, "default": Object { - "api_key": undefined, "ca_sha256": undefined, "hosts": Array [ "http://127.0.0.1:9201", @@ -112,7 +110,6 @@ Object { }, "outputs": Object { "default": Object { - "api_key": undefined, "ca_sha256": undefined, "hosts": Array [ "http://127.0.0.1:9201", @@ -120,7 +117,6 @@ Object { "type": "elasticsearch", }, "monitoring-output-id": Object { - "api_key": undefined, "ca_sha256": undefined, "hosts": Array [ "http://es-monitoring.co:9201", @@ -178,7 +174,6 @@ Object { }, "outputs": Object { "data-output-id": Object { - "api_key": undefined, "ca_sha256": undefined, "hosts": Array [ "http://es-data.co:9201", @@ -186,7 +181,6 @@ Object { "type": "elasticsearch", }, "monitoring-output-id": Object { - "api_key": undefined, "ca_sha256": undefined, "hosts": Array [ "http://es-monitoring.co:9201", diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts index 1bc1919226248..67be0b6914537 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts @@ -145,7 +145,6 @@ describe('getFullAgentPolicy', () => { type: 'elasticsearch', hosts: ['http://127.0.0.1:9201'], ca_sha256: undefined, - api_key: undefined, }, }, inputs: [], @@ -178,7 +177,6 @@ describe('getFullAgentPolicy', () => { type: 'elasticsearch', hosts: ['http://127.0.0.1:9201'], ca_sha256: undefined, - api_key: undefined, }, }, inputs: [], @@ -213,7 +211,6 @@ describe('getFullAgentPolicy', () => { type: 'elasticsearch', hosts: ['http://127.0.0.1:9201'], ca_sha256: undefined, - api_key: undefined, }, }, inputs: [], @@ -315,12 +312,10 @@ describe('transformOutputToFullPolicyOutput', () => { is_default_monitoring: false, name: 'test output', type: 'elasticsearch', - api_key: 'apikey123', }); expect(policyOutput).toMatchInlineSnapshot(` Object { - "api_key": "apikey123", "ca_sha256": undefined, "hosts": Array [ "http://host.fr", @@ -337,7 +332,6 @@ describe('transformOutputToFullPolicyOutput', () => { is_default_monitoring: false, name: 'test output', type: 'elasticsearch', - api_key: 'apikey123', ca_trusted_fingerprint: 'fingerprint123', config_yaml: ` test: 1234 @@ -347,7 +341,6 @@ ssl.test: 123 expect(policyOutput).toMatchInlineSnapshot(` Object { - "api_key": "apikey123", "ca_sha256": undefined, "hosts": Array [ "http://host.fr", diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts index 0bb6b4a33f6a3..17762ad5ada83 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts @@ -171,19 +171,17 @@ export function transformOutputToFullPolicyOutput( standalone = false ): FullAgentPolicyOutput { // eslint-disable-next-line @typescript-eslint/naming-convention - const { config_yaml, type, hosts, ca_sha256, ca_trusted_fingerprint, api_key } = output; + const { config_yaml, type, hosts, ca_sha256, ca_trusted_fingerprint } = output; const configJs = config_yaml ? safeLoad(config_yaml) : {}; const newOutput: FullAgentPolicyOutput = { ...configJs, type, hosts, ca_sha256, - api_key, ...(ca_trusted_fingerprint ? { 'ssl.ca_trusted_fingerprint': ca_trusted_fingerprint } : {}), }; if (standalone) { - delete newOutput.api_key; newOutput.username = '{ES_USERNAME}'; newOutput.password = '{ES_PASSWORD}'; } diff --git a/x-pack/plugins/fleet/server/types/models/output.ts b/x-pack/plugins/fleet/server/types/models/output.ts index 83119657ac209..7d9232862092e 100644 --- a/x-pack/plugins/fleet/server/types/models/output.ts +++ b/x-pack/plugins/fleet/server/types/models/output.ts @@ -13,7 +13,6 @@ const OutputBaseSchema = { name: schema.string(), type: schema.oneOf([schema.literal(outputType.Elasticsearch)]), hosts: schema.maybe(schema.arrayOf(schema.string())), - api_key: schema.maybe(schema.string()), config: schema.maybe(schema.recordOf(schema.string(), schema.any())), config_yaml: schema.maybe(schema.string()), }; From 148674177df9b4352b6d7db7204c884c26a7fd9a Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Wed, 16 Feb 2022 11:53:10 -0700 Subject: [PATCH 024/104] [Reporting] Public API Documentation (#125141) * [Reporting] Public API Documentation * clean up --- x-pack/plugins/reporting/common/index.ts | 19 ++++++ x-pack/plugins/reporting/common/types/base.ts | 14 +++- .../types/export_types/printable_pdf.ts | 8 ++- x-pack/plugins/reporting/common/types/url.ts | 8 +++ x-pack/plugins/reporting/public/index.ts | 29 +++++++-- .../public/lib/reporting_api_client/index.ts | 2 +- .../reporting_api_client.ts | 1 - .../reporting_panel_content.tsx | 6 ++ .../public/shared/get_shared_components.tsx | 65 +++++++++++++++---- .../plugins/reporting/public/shared/index.ts | 1 + x-pack/plugins/reporting/server/index.ts | 18 ++--- x-pack/plugins/reporting/server/types.ts | 37 ++++------- 12 files changed, 154 insertions(+), 54 deletions(-) create mode 100644 x-pack/plugins/reporting/common/index.ts diff --git a/x-pack/plugins/reporting/common/index.ts b/x-pack/plugins/reporting/common/index.ts new file mode 100644 index 0000000000000..36c9f99628778 --- /dev/null +++ b/x-pack/plugins/reporting/common/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * Common types that are documented in the Public API + */ +export type { + BaseParams, + BaseParamsV2, + BasePayload, + BasePayloadV2, + JobAppParamsPDF, + JobAppParamsPDFV2, + LocatorParams, +} from './types'; diff --git a/x-pack/plugins/reporting/common/types/base.ts b/x-pack/plugins/reporting/common/types/base.ts index 234467a16921e..6d5e6c1479da0 100644 --- a/x-pack/plugins/reporting/common/types/base.ts +++ b/x-pack/plugins/reporting/common/types/base.ts @@ -11,6 +11,9 @@ import { LocatorParams } from './url'; export type JobId = string; +/** + * @deprecated + */ export type BaseParams = Ensure< { layout?: LayoutParams; @@ -22,17 +25,26 @@ export type BaseParams = Ensure< SerializableRecord >; +/** + * Report job parameters that an application must return from its + * getSharingData function. + */ export type BaseParamsV2 = BaseParams & { locatorParams: LocatorParams[]; }; -// base params decorated with encrypted headers that come into runJob functions +/** + * @deprecated + */ export interface BasePayload extends BaseParams { headers: string; spaceId?: string; isDeprecated?: boolean; } +/** + * Report job parameters, after they are processed in the request handler. + */ export interface BasePayloadV2 extends BaseParamsV2 { headers: string; spaceId?: string; diff --git a/x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts b/x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts index d5b8ec21cc13b..e22b45f021b9e 100644 --- a/x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts +++ b/x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts @@ -15,14 +15,20 @@ interface BaseParamsPDF { } // Job params: structure of incoming user request data, after being parsed from RISON + /** * @deprecated */ export type JobParamsPDFDeprecated = BaseParamsPDF & BaseParams; +/** + * @deprecated + */ export type JobAppParamsPDF = Omit; -// Job payload: structure of stored job data provided by create_job +/** + * Structure of stored job data provided by create_job + */ export interface TaskPayloadPDF extends BasePayload { layout: LayoutParams; forceNow?: string; diff --git a/x-pack/plugins/reporting/common/types/url.ts b/x-pack/plugins/reporting/common/types/url.ts index 28e935713c45e..2445e210b89b7 100644 --- a/x-pack/plugins/reporting/common/types/url.ts +++ b/x-pack/plugins/reporting/common/types/url.ts @@ -16,7 +16,15 @@ export type ManagementLinkFn = () => ManagementLink; export interface LocatorParams

{ id: string; + + /** + * Kibana version used to create the params + */ version: string; + + /** + * Data to recreate the user's state in the application + */ params: P; } diff --git a/x-pack/plugins/reporting/public/index.ts b/x-pack/plugins/reporting/public/index.ts index fdd5769ab3e00..1026a718b95ea 100644 --- a/x-pack/plugins/reporting/public/index.ts +++ b/x-pack/plugins/reporting/public/index.ts @@ -5,22 +5,41 @@ * 2.0. */ -import { PluginInitializerContext } from 'src/core/public'; -import { ReportingAPIClient } from './lib/reporting_api_client'; +import type { PluginInitializerContext } from 'src/core/public'; import { ReportingPublicPlugin } from './plugin'; -import { getSharedComponents } from './shared'; +import type { ReportingPublicComponents } from './shared/get_shared_components'; +/** + * Setup contract for the Reporting plugin. + */ export interface ReportingSetup { + /** + * Used to inform plugins if Reporting config is compatible with UI Capabilities / Application Sub-Feature Controls + * + * @returns boolean + */ usesUiCapabilities: () => boolean; - components: ReturnType; + + /** + * A set of React components for displaying a Reporting share menu in an application + */ + components: ReportingPublicComponents; } +/** + * Start contract for the Reporting plugin. + */ export type ReportingStart = ReportingSetup; -export { ReportingAPIClient, ReportingPublicPlugin as Plugin }; +/** + * Public interface needed for shared components + */ +export type { ApplicationProps } from './shared'; +export type { ReportingPublicComponents }; /** * @internal + * * @param {PluginInitializerContext} initializerContext * @returns {ReportingPublicPlugin} */ diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client/index.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client/index.ts index ed39eaff144bd..742c5af80f705 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client/index.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client/index.ts @@ -7,5 +7,5 @@ export { InternalApiClientProvider, useInternalApiClient } from './context'; export { useCheckIlmPolicyStatus } from './hooks'; -export type { DiagnoseResponse } from './reporting_api_client'; export { ReportingAPIClient } from './reporting_api_client'; +export type { DiagnoseResponse } from './reporting_api_client'; diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts index dab62ea97b7e8..d76f06e00586f 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts @@ -71,7 +71,6 @@ interface IReportingAPI { /** * Client class for interacting with Reporting APIs * @implements IReportingAPI - * @internal */ export class ReportingAPIClient implements IReportingAPI { private http: HttpSetup; diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx index e1fa1198cf1f8..1925bf377a370 100644 --- a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx @@ -33,6 +33,10 @@ import { ReportingAPIClient } from '../../lib/reporting_api_client'; import { ErrorUnsavedWorkPanel, ErrorUrlTooLongPanel } from './components'; import { getMaxUrlLength } from './constants'; +/** + * Properties for displaying a share menu with Reporting features, including + * internally-derived fields. + */ export interface ReportingPanelProps { apiClient: ReportingAPIClient; toasts: ToastsSetup; @@ -42,7 +46,9 @@ export interface ReportingPanelProps { requiresSavedState: boolean; // Whether the report to be generated requires saved state that is not captured in the URL submitted to the report generator. layoutId?: string; objectId?: string; + getJobParams: (forShareUrl?: boolean) => Omit; + options?: ReactElement | null; isDirty?: boolean; onClose?: () => void; diff --git a/x-pack/plugins/reporting/public/shared/get_shared_components.tsx b/x-pack/plugins/reporting/public/shared/get_shared_components.tsx index 0906bf85c9538..3a0374a957832 100644 --- a/x-pack/plugins/reporting/public/shared/get_shared_components.tsx +++ b/x-pack/plugins/reporting/public/shared/get_shared_components.tsx @@ -7,29 +7,70 @@ import { CoreSetup } from 'kibana/public'; import React from 'react'; -import { ReportingAPIClient } from '../'; import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2, PNG_REPORT_TYPE_V2 } from '../../common/constants'; -import type { Props as PanelPropsScreenCapture } from '../share_context_menu/screen_capture_panel_content'; +import { ReportingAPIClient } from '../lib/reporting_api_client'; +import { ReportingPanelProps } from '../share_context_menu/reporting_panel_content'; import { ScreenCapturePanelContent } from '../share_context_menu/screen_capture_panel_content_lazy'; -interface IncludeOnCloseFn { +/** + * Properties for displaying a share menu with Reporting features. + */ +export interface ApplicationProps { + /** + * A function that Reporting calls to get the sharing data from the application. + */ + getJobParams: ReportingPanelProps['getJobParams']; + + /** + * Option to control how the screenshot(s) is/are placed in the PDF + */ + layoutOption?: 'canvas' | 'print'; + + /** + * Saved object ID + */ + objectId?: string; + + /** + * A function to callback when the Reporting panel should be closed + */ onClose: () => void; } -type Props = Pick & - IncludeOnCloseFn; +/** + * React components used to display share menus with Reporting features in an application. + */ +export interface ReportingPublicComponents { + /** + * An element to display a form to export the page as PDF + * @deprecated + */ + ReportingPanelPDF(props: ApplicationProps): JSX.Element; -/* + /** + * An element to display a form to export the page as PDF + */ + ReportingPanelPDFV2(props: ApplicationProps): JSX.Element; + + /** + * An element to display a form to export the page as PNG + */ + ReportingPanelPNGV2(props: ApplicationProps): JSX.Element; +} + +/** * As of 7.14, the only shared component is a PDF report that is suited for Canvas integration. * This is not planned to expand, as work is to be done on moving the export-type implementations out of Reporting * Related Discuss issue: https://github.com/elastic/kibana/issues/101422 */ -export function getSharedComponents(core: CoreSetup, apiClient: ReportingAPIClient) { +export function getSharedComponents( + core: CoreSetup, + apiClient: ReportingAPIClient +): ReportingPublicComponents { return { - ReportingPanelPDF(props: Props) { + ReportingPanelPDF(props: ApplicationProps) { return ( ); }, - ReportingPanelPDFV2(props: Props) { + ReportingPanelPDFV2(props: ApplicationProps) { return ( ); }, - ReportingPanelPNGV2(props: Props) { + ReportingPanelPNGV2(props: ApplicationProps) { return ( ) => new ReportingPlugin(initContext); -export { config } from './config'; +// @internal export type { ReportingConfig } from './config/config'; -// internal imports +// @internal export { ReportingCore } from './core'; -export type { - ReportingSetup, - ReportingSetupDeps as PluginSetup, - ReportingStartDeps as PluginStart, -} from './types'; -export { ReportingPlugin as Plugin }; diff --git a/x-pack/plugins/reporting/server/types.ts b/x-pack/plugins/reporting/server/types.ts index cd28972f5941a..fa69509d16be8 100644 --- a/x-pack/plugins/reporting/server/types.ts +++ b/x-pack/plugins/reporting/server/types.ts @@ -32,26 +32,28 @@ import type { ReportingCore } from './core'; import type { LevelLogger } from './lib'; import type { ReportTaskParams } from './lib/tasks'; -/* - * Plugin Contract +/** + * Plugin Setup Contract */ - export interface ReportingSetup { + /** + * Used to inform plugins if Reporting config is compatible with UI Capabilities / Application Sub-Feature Controls + */ usesUiCapabilities: () => boolean; } -export type ReportingStart = ReportingSetup; - -/* - * Internal Types +/** + * Plugin Start Contract */ - +export type ReportingStart = ReportingSetup; export type ReportingUser = { username: AuthenticatedUser['username'] } | false; export type CaptureConfig = ReportingConfigType['capture']; export type ScrollConfig = ReportingConfigType['csv']['scroll']; -export type { BaseParams, BasePayload }; +/** + * Internal Types + */ // default fn type for CreateJobFnFactory export type CreateJobFn = ( @@ -91,9 +93,6 @@ export interface ExportTypeDefinition< validLicenses: string[]; } -/* - * @internal - */ export interface ReportingSetupDeps { features: FeaturesPluginSetup; screenshotMode: ScreenshotModePluginSetup; @@ -103,9 +102,6 @@ export interface ReportingSetupDeps { usageCollection?: UsageCollectionSetup; } -/* - * @internal - */ export interface ReportingStartDeps { data: DataPluginStart; fieldFormats: FieldFormatsStart; @@ -115,22 +111,15 @@ export interface ReportingStartDeps { taskManager: TaskManagerStartContract; } -/** - * @internal - */ export interface ReportingRequestHandlerContext { reporting: ReportingStart | null; core: RequestHandlerContext['core']; } -/** - * @internal - */ export type ReportingPluginRouter = IRouter; -/** - * @internal - */ export interface ScreenshotOptions extends Omit { urls: UrlOrUrlLocatorTuple[]; } + +export type { BaseParams, BasePayload }; From ba8c339d84c1d26441f049650296ab4072147128 Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Wed, 16 Feb 2022 14:39:15 -0500 Subject: [PATCH 025/104] [Fleet] Allow bundled installs to occur even if EPR is unreachable (#125127) * Allow bundled installs to occur even if EPR is unreachable * Fix type errors in test * Fix failing test * fixup! Fix failing test * Remove unused object in mock * Make creation of preconfigured agent policy functional * Always fall back to bundled packages if available * Remove unused import * Use packageInfo object instead of RegistryPackage where possible * Fix type error in assets test * Fix test timeouts * Fix promise logic for registry fetch fallback * Use archive package as default in create package policy * Always install from bundled package if it exists - regardless of installation context * Clean up + refactor a bit * Default to cached package archive for policy updates * Update mock in get.test.ts * Add test for install from bundled package logic * Delete timeout call in security solution tests * Fix unused var in endpoint test * Fix another unused var in endpoint test * [Debug] Add some logging to test installation times in CI * Revert "[Debug] Add some logging to test installation times in CI" This reverts commit 513dcc121e4ab52e2d482ebb54a45af06c6f6b6c. * Update docker images for registry * Update docker image digest again * Refactor latest package fetching to fix broken logic/tests * Fix a bunch of type errors around renamed fetch latest package version methods * Remove unused import * Bump docker version to latest snapshot (again) * Revert changes to endpoint tests * Pass experimental flag in synthetics tests * Fix endpoint version in fleet api integration test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts | 2 +- .../plugins/fleet/common/types/models/epm.ts | 8 +- x-pack/plugins/fleet/server/errors/index.ts | 1 + .../docker_registry_helper.ts | 2 +- .../agent_policies/full_agent_policy.ts | 2 +- .../epm/elasticsearch/template/install.ts | 13 ++- .../fleet/server/services/epm/fields/field.ts | 4 +- .../services/epm/package_service.test.ts | 2 +- .../server/services/epm/package_service.ts | 8 +- .../services/epm/packages/assets.test.ts | 4 +- .../server/services/epm/packages/assets.ts | 6 +- .../epm/packages/bulk_install_packages.ts | 80 ++++--------------- ...undled_packages.ts => bundled_packages.ts} | 21 +++-- .../server/services/epm/packages/get.test.ts | 8 +- .../fleet/server/services/epm/packages/get.ts | 5 +- .../services/epm/packages/install.test.ts | 39 ++++++++- .../server/services/epm/packages/install.ts | 30 ++++++- .../server/services/epm/registry/index.ts | 78 +++++++++++++----- .../server/services/epm/registry/requests.ts | 15 ++-- .../fleet/server/services/package_policy.ts | 50 ++++++++---- .../server/services/preconfiguration.test.ts | 16 ++-- .../fleet/server/services/preconfiguration.ts | 3 - x-pack/plugins/fleet/server/types/index.tsx | 1 + .../apis/package_policy/create.ts | 4 +- x-pack/test/fleet_api_integration/config.ts | 2 +- x-pack/test/functional/config.js | 2 +- x-pack/test/functional_synthetics/config.js | 2 +- .../services/uptime/synthetics_package.ts | 1 + 28 files changed, 253 insertions(+), 156 deletions(-) rename x-pack/plugins/fleet/server/services/epm/packages/{get_bundled_packages.ts => bundled_packages.ts} (69%) diff --git a/x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts b/x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts index 8fc87b49a6607..6a4c2e03fac08 100644 --- a/x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts +++ b/x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts @@ -13,7 +13,7 @@ import { packageRegistryPort } from './ftr_config'; import { FtrProviderContext } from './ftr_provider_context'; export const dockerImage = - 'docker.elastic.co/package-registry/distribution@sha256:de952debe048d903fc73e8a4472bb48bb95028d440cba852f21b863d47020c61'; + 'docker.elastic.co/package-registry/distribution@sha256:c5bf8e058727de72e561b228f4b254a14a6f880e582190d01bd5ff74318e1d0b'; async function ftrConfigRun({ readConfigFile }: FtrConfigProviderContext) { const kibanaConfig = await readConfigFile(require.resolve('./ftr_config.ts')); diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 983ee7fff3db1..64ea5665241e1 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -107,7 +107,13 @@ export type InstallablePackage = RegistryPackage | ArchivePackage; export type ArchivePackage = PackageSpecManifest & // should an uploaded package be able to specify `internal`? - Pick; + Pick; + +export interface BundledPackage { + name: string; + version: string; + buffer: Buffer; +} export type RegistryPackage = PackageSpecManifest & Partial & diff --git a/x-pack/plugins/fleet/server/errors/index.ts b/x-pack/plugins/fleet/server/errors/index.ts index 380862d36fe01..0d8627c13b3dc 100644 --- a/x-pack/plugins/fleet/server/errors/index.ts +++ b/x-pack/plugins/fleet/server/errors/index.ts @@ -43,6 +43,7 @@ export class ConcurrentInstallOperationError extends IngestManagerError {} export class AgentReassignmentError extends IngestManagerError {} export class PackagePolicyIneligibleForUpgradeError extends IngestManagerError {} export class PackagePolicyValidationError extends IngestManagerError {} +export class BundledPackageNotFoundError extends IngestManagerError {} export class HostedAgentPolicyRestrictionRelatedError extends IngestManagerError { constructor(message = 'Cannot perform that action') { super( diff --git a/x-pack/plugins/fleet/server/integration_tests/docker_registry_helper.ts b/x-pack/plugins/fleet/server/integration_tests/docker_registry_helper.ts index 31b0831d7f3e5..ccea6d4bd919b 100644 --- a/x-pack/plugins/fleet/server/integration_tests/docker_registry_helper.ts +++ b/x-pack/plugins/fleet/server/integration_tests/docker_registry_helper.ts @@ -24,7 +24,7 @@ export function useDockerRegistry() { let dockerProcess: ChildProcess | undefined; async function startDockerRegistryServer() { - const dockerImage = `docker.elastic.co/package-registry/distribution@sha256:de952debe048d903fc73e8a4472bb48bb95028d440cba852f21b863d47020c61`; + const dockerImage = `docker.elastic.co/package-registry/distribution@sha256:c5bf8e058727de72e561b228f4b254a14a6f880e582190d01bd5ff74318e1d0b`; const args = ['run', '--rm', '-p', `${packageRegistryPort}:8080`, dockerImage]; diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts index 17762ad5ada83..9f522875544e1 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts @@ -34,7 +34,7 @@ export async function getFullAgentPolicy( options?: { standalone: boolean } ): Promise { let agentPolicy; - const standalone = options?.standalone; + const standalone = options?.standalone ?? false; try { agentPolicy = await agentPolicyService.get(soClient, id); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index 6bd346f3aff89..1303db1a36c0e 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -16,6 +16,7 @@ import type { RegistryElasticsearch, InstallablePackage, IndexTemplate, + PackageInfo, } from '../../../../types'; import { loadFieldsFromYaml, processFields } from '../../fields/field'; import type { Field } from '../../fields/field'; @@ -31,6 +32,8 @@ import type { ESAssetMetadata } from '../meta'; import { getESAssetMetadata } from '../meta'; import { retryTransientEsErrors } from '../retry'; +import { getPackageInfo } from '../../packages'; + import { generateMappings, generateTemplateName, @@ -62,10 +65,16 @@ export const installTemplates = async ( const dataStreams = installablePackage.data_streams; if (!dataStreams) return []; + const packageInfo = await getPackageInfo({ + savedObjectsClient, + pkgName: installablePackage.name, + pkgVersion: installablePackage.version, + }); + const installedTemplatesNested = await Promise.all( dataStreams.map((dataStream) => installTemplateForDataStream({ - pkg: installablePackage, + pkg: packageInfo, esClient, logger, dataStream, @@ -177,7 +186,7 @@ export async function installTemplateForDataStream({ logger, dataStream, }: { - pkg: InstallablePackage; + pkg: PackageInfo; esClient: ElasticsearchClient; logger: Logger; dataStream: RegistryDataStream; diff --git a/x-pack/plugins/fleet/server/services/epm/fields/field.ts b/x-pack/plugins/fleet/server/services/epm/fields/field.ts index d854a0fe8e74d..06ff858df6786 100644 --- a/x-pack/plugins/fleet/server/services/epm/fields/field.ts +++ b/x-pack/plugins/fleet/server/services/epm/fields/field.ts @@ -7,7 +7,7 @@ import { safeLoad } from 'js-yaml'; -import type { InstallablePackage } from '../../../types'; +import type { PackageInfo } from '../../../types'; import { getAssetsData } from '../packages/assets'; // This should become a copy of https://github.com/elastic/beats/blob/d9a4c9c240a9820fab15002592e5bb6db318543b/libbeat/mapping/field.go#L39 @@ -261,7 +261,7 @@ const isFields = (path: string) => { */ export const loadFieldsFromYaml = async ( - pkg: InstallablePackage, + pkg: PackageInfo, datasetName?: string ): Promise => { // Fetch all field definition files diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.test.ts b/x-pack/plugins/fleet/server/services/epm/package_service.test.ts index 97ee5acc71023..5c48ddb050ff2 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.test.ts @@ -91,7 +91,7 @@ function getTest( test = { method: mocks.packageClient.fetchFindLatestPackage.bind(mocks.packageClient), args: ['package name'], - spy: jest.spyOn(epmRegistry, 'fetchFindLatestPackage'), + spy: jest.spyOn(epmRegistry, 'fetchFindLatestPackageOrThrow'), spyArgs: ['package name'], spyResponse: { name: 'fetchFindLatestPackage test' }, }; diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.ts b/x-pack/plugins/fleet/server/services/epm/package_service.ts index 0d9b8cb74b503..cac69fe4bd3b8 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.ts @@ -19,13 +19,13 @@ import type { InstallablePackage, Installation, RegistryPackage, - RegistrySearchResult, + BundledPackage, } from '../../types'; import { checkSuperuser } from '../../routes/security'; import { FleetUnauthorizedError } from '../../errors'; import { installTransform, isTransform } from './elasticsearch/transform/install'; -import { fetchFindLatestPackage, getRegistryPackage } from './registry'; +import { fetchFindLatestPackageOrThrow, getRegistryPackage } from './registry'; import { ensureInstalledPackage, getInstallation } from './packages'; export type InstalledAssetType = EsAssetReference; @@ -44,7 +44,7 @@ export interface PackageClient { spaceId?: string; }): Promise; - fetchFindLatestPackage(packageName: string): Promise; + fetchFindLatestPackage(packageName: string): Promise; getRegistryPackage( packageName: string, @@ -117,7 +117,7 @@ class PackageClientImpl implements PackageClient { public async fetchFindLatestPackage(packageName: string) { await this.#runPreflight(); - return fetchFindLatestPackage(packageName); + return fetchFindLatestPackageOrThrow(packageName); } public async getRegistryPackage(packageName: string, packageVersion: string) { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts index c5b104696aaf4..b019729b65eb1 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { InstallablePackage } from '../../../types'; +import type { PackageInfo } from '../../../types'; import { getArchiveFilelist } from '../archive/cache'; @@ -66,7 +66,7 @@ const tests = [ test('testGetAssets', () => { for (const value of tests) { // as needed to pretend it is an InstallablePackage - const assets = getAssets(value.package as InstallablePackage, value.filter, value.dataset); + const assets = getAssets(value.package as PackageInfo, value.filter, value.dataset); expect(assets).toStrictEqual(value.expected); } }); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/assets.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.ts index c28c982f4ea4c..c939ce093a65c 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/assets.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/assets.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { InstallablePackage } from '../../../types'; +import type { PackageInfo } from '../../../types'; import { getArchiveFilelist, getAsset } from '../archive'; import type { ArchiveEntry } from '../archive'; @@ -17,7 +17,7 @@ import type { ArchiveEntry } from '../archive'; // and different package and version structure export function getAssets( - packageInfo: InstallablePackage, + packageInfo: PackageInfo, filter = (path: string): boolean => true, datasetName?: string ): string[] { @@ -52,7 +52,7 @@ export function getAssets( // ASK: Does getAssetsData need an installSource now? // if so, should it be an Installation vs InstallablePackage or add another argument? export async function getAssetsData( - packageInfo: InstallablePackage, + packageInfo: PackageInfo, filter = (path: string): boolean => true, datasetName?: string ): Promise { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts index a32809672e1b4..d68b2f67e3295 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts @@ -14,7 +14,6 @@ import type { InstallResult } from '../../../types'; import { installPackage, isPackageVersionOrLaterInstalled } from './install'; import type { BulkInstallResponse, IBulkInstallPackageError } from './install'; -import { getBundledPackages } from './get_bundled_packages'; interface BulkInstallPackagesParams { savedObjectsClient: SavedObjectsClientContract; @@ -31,23 +30,23 @@ export async function bulkInstallPackages({ esClient, spaceId, force, - preferredSource = 'registry', }: BulkInstallPackagesParams): Promise { const logger = appContextService.getLogger(); - const bundledPackages = await getBundledPackages(); - const packagesResults = await Promise.allSettled( - packagesToInstall.map((pkg) => { - if (typeof pkg === 'string') return Registry.fetchFindLatestPackage(pkg); - return Promise.resolve(pkg); + packagesToInstall.map(async (pkg) => { + if (typeof pkg !== 'string') { + return Promise.resolve(pkg); + } + + return Registry.fetchFindLatestPackageOrThrow(pkg); }) ); logger.debug( - `kicking off bulk install of ${packagesToInstall.join( - ', ' - )} with preferred source of "${preferredSource}"` + `kicking off bulk install of ${packagesToInstall + .map((pkg) => (typeof pkg === 'string' ? pkg : pkg.name)) + .join(', ')}` ); const bulkInstallResults = await Promise.allSettled( @@ -83,61 +82,16 @@ export async function bulkInstallPackages({ }; } - let installResult: InstallResult; const pkgkey = Registry.pkgToPkgKey(pkgKeyProps); - const bundledPackage = bundledPackages.find((pkg) => pkg.name === pkgkey); - - // If preferred source is bundled packages on disk, attempt to install from disk first, then fall back to registry - if (preferredSource === 'bundled') { - if (bundledPackage) { - logger.debug( - `kicking off install of ${pkgKeyProps.name}-${pkgKeyProps.version} from bundled package on disk` - ); - installResult = await installPackage({ - savedObjectsClient, - esClient, - installSource: 'upload', - archiveBuffer: bundledPackage.buffer, - contentType: 'application/zip', - spaceId, - }); - } else { - installResult = await installPackage({ - savedObjectsClient, - esClient, - pkgkey, - installSource: 'registry', - spaceId, - force, - }); - } - } else { - // If preferred source is registry, attempt to install from registry first, then fall back to bundled packages on disk - installResult = await installPackage({ - savedObjectsClient, - esClient, - pkgkey, - installSource: 'registry', - spaceId, - force, - }); - - // If we initially errored, try to install from bundled package on disk - if (installResult.error && bundledPackage) { - logger.debug( - `kicking off install of ${pkgKeyProps.name}-${pkgKeyProps.version} from bundled package on disk` - ); - installResult = await installPackage({ - savedObjectsClient, - esClient, - installSource: 'upload', - archiveBuffer: bundledPackage.buffer, - contentType: 'application/zip', - spaceId, - }); - } - } + const installResult = await installPackage({ + savedObjectsClient, + esClient, + pkgkey, + installSource: 'registry', + spaceId, + force, + }); if (installResult.error) { return { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get_bundled_packages.ts b/x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts similarity index 69% rename from x-pack/plugins/fleet/server/services/epm/packages/get_bundled_packages.ts rename to x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts index a9f9b754640cb..8ccd2006ad846 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get_bundled_packages.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts @@ -5,18 +5,15 @@ * 2.0. */ -import path from 'path'; import fs from 'fs/promises'; +import path from 'path'; +import type { BundledPackage } from '../../../types'; import { appContextService } from '../../app_context'; +import { splitPkgKey } from '../registry'; const BUNDLED_PACKAGE_DIRECTORY = path.join(__dirname, '../../../bundled_packages'); -interface BundledPackage { - name: string; - buffer: Buffer; -} - export async function getBundledPackages(): Promise { try { const dirContents = await fs.readdir(BUNDLED_PACKAGE_DIRECTORY); @@ -26,8 +23,11 @@ export async function getBundledPackages(): Promise { zipFiles.map(async (zipFile) => { const file = await fs.readFile(path.join(BUNDLED_PACKAGE_DIRECTORY, zipFile)); + const { pkgName, pkgVersion } = splitPkgKey(zipFile.replace(/\.zip$/, '')); + return { - name: zipFile.replace(/\.zip$/, ''), + name: pkgName, + version: pkgVersion, buffer: file, }; }) @@ -41,3 +41,10 @@ export async function getBundledPackages(): Promise { return []; } } + +export async function getBundledPackageByName(name: string): Promise { + const bundledPackages = await getBundledPackages(); + const bundledPackage = bundledPackages.find((pkg) => pkg.name === name); + + return bundledPackage; +} diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts index 53b4d341beec2..b15c61cebd778 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts @@ -186,7 +186,7 @@ describe('When using EPM `get` services', () => { beforeEach(() => { const mockContract = createAppContextStartContractMock(); appContextService.start(mockContract); - MockRegistry.fetchFindLatestPackage.mockResolvedValue({ + MockRegistry.fetchFindLatestPackageOrUndefined.mockResolvedValue({ name: 'my-package', version: '1.0.0', } as RegistryPackage); @@ -283,8 +283,8 @@ describe('When using EPM `get` services', () => { }); describe('registry fetch errors', () => { - it('throws when a package that is not installed is not available in the registry', async () => { - MockRegistry.fetchFindLatestPackage.mockResolvedValue(undefined); + it('throws when a package that is not installed is not available in the registry and not bundled', async () => { + MockRegistry.fetchFindLatestPackageOrUndefined.mockResolvedValue(undefined); const soClient = savedObjectsClientMock.create(); soClient.get.mockRejectedValue(SavedObjectsErrorHelpers.createGenericNotFoundError()); @@ -298,7 +298,7 @@ describe('When using EPM `get` services', () => { }); it('sets the latestVersion to installed version when an installed package is not available in the registry', async () => { - MockRegistry.fetchFindLatestPackage.mockResolvedValue(undefined); + MockRegistry.fetchFindLatestPackageOrUndefined.mockResolvedValue(undefined); const soClient = savedObjectsClientMock.create(); soClient.get.mockResolvedValue({ id: 'my-package', diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index c78f107cce715..fd24b3f438319 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -106,7 +106,7 @@ export async function getPackageInfoFromRegistry(options: { const { savedObjectsClient, pkgName, pkgVersion } = options; const [savedObject, latestPackage] = await Promise.all([ getInstallationObject({ savedObjectsClient, pkgName }), - Registry.fetchFindLatestPackage(pkgName), + Registry.fetchFindLatestPackageOrThrow(pkgName), ]); // If no package version is provided, use the installed version in the response @@ -143,9 +143,10 @@ export async function getPackageInfo(options: { pkgVersion: string; }): Promise { const { savedObjectsClient, pkgName, pkgVersion } = options; + const [savedObject, latestPackage] = await Promise.all([ getInstallationObject({ savedObjectsClient, pkgName }), - Registry.fetchFindLatestPackage(pkgName, { throwIfNotFound: false }), + Registry.fetchFindLatestPackageOrUndefined(pkgName), ]); if (!savedObject && !latestPackage) { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts index b74466bc6271a..1a1f1aa617f54 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts @@ -20,6 +20,7 @@ import { licenseService } from '../../license'; import { installPackage } from './install'; import * as install from './_install_package'; import * as obj from './index'; +import { getBundledPackages } from './bundled_packages'; jest.mock('../../app_context', () => { return { @@ -40,6 +41,7 @@ jest.mock('../../upgrade_sender'); jest.mock('../../license'); jest.mock('../../upgrade_sender'); jest.mock('./cleanup'); +jest.mock('./bundled_packages'); jest.mock('./_install_package', () => { return { _installPackage: jest.fn(() => Promise.resolve()), @@ -60,6 +62,8 @@ jest.mock('../archive', () => { }; }); +const mockGetBundledPackages = getBundledPackages as jest.MockedFunction; + describe('install', () => { beforeEach(() => { jest.spyOn(Registry, 'splitPkgKey').mockImplementation((pkgKey: string) => { @@ -67,14 +71,25 @@ describe('install', () => { return { pkgName, pkgVersion }; }); jest - .spyOn(Registry, 'fetchFindLatestPackage') + .spyOn(Registry, 'pkgToPkgKey') + .mockImplementation((pkg: { name: string; version: string }) => { + return `${pkg.name}-${pkg.version}`; + }); + jest + .spyOn(Registry, 'fetchFindLatestPackageOrThrow') .mockImplementation(() => Promise.resolve({ version: '1.3.0' } as any)); jest .spyOn(Registry, 'getRegistryPackage') .mockImplementation(() => Promise.resolve({ packageInfo: { license: 'basic' } } as any)); + + mockGetBundledPackages.mockReset(); }); describe('registry', () => { + beforeEach(() => { + mockGetBundledPackages.mockResolvedValue([]); + }); + it('should send telemetry on install failure, out of date', async () => { await installPackage({ spaceId: DEFAULT_SPACE_ID, @@ -187,6 +202,28 @@ describe('install', () => { status: 'failure', }); }); + + it('should install from bundled package if one exists', async () => { + mockGetBundledPackages.mockResolvedValue([ + { + name: 'test_package', + version: '1.0.0', + buffer: Buffer.from('test_package'), + }, + ]); + + await installPackage({ + spaceId: DEFAULT_SPACE_ID, + installSource: 'registry', + pkgkey: 'test_package-1.0.0', + savedObjectsClient: savedObjectsClientMock.create(), + esClient: {} as ElasticsearchClient, + }); + + expect(install._installPackage).toHaveBeenCalledWith( + expect.objectContaining({ installSource: 'upload' }) + ); + }); }); describe('upload', () => { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index 9ffae48cb02d8..107b906a969c8 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -44,6 +44,7 @@ import { removeInstallation } from './remove'; import { getPackageSavedObjects } from './get'; import { _installPackage } from './_install_package'; import { removeOldAssets } from './cleanup'; +import { getBundledPackages } from './bundled_packages'; export async function isPackageInstalled(options: { savedObjectsClient: SavedObjectsClientContract; @@ -88,7 +89,7 @@ export async function ensureInstalledPackage(options: { // If pkgVersion isn't specified, find the latest package version const pkgKeyProps = pkgVersion ? { name: pkgName, version: pkgVersion } - : await Registry.fetchFindLatestPackage(pkgName); + : await Registry.fetchFindLatestPackageOrThrow(pkgName); const installedPackageResult = await isPackageVersionOrLaterInstalled({ savedObjectsClient, @@ -251,7 +252,9 @@ async function installPackageFromRegistry({ installType = getInstallType({ pkgVersion, installedPkg }); // get latest package version - const latestPackage = await Registry.fetchFindLatestPackage(pkgName, { ignoreConstraints }); + const latestPackage = await Registry.fetchFindLatestPackageOrThrow(pkgName, { + ignoreConstraints, + }); // let the user install if using the force flag or needing to reinstall or install a previous version due to failed update const installOutOfDateVersionOk = @@ -470,8 +473,31 @@ export async function installPackage(args: InstallPackageParams) { const logger = appContextService.getLogger(); const { savedObjectsClient, esClient } = args; + const bundledPackages = await getBundledPackages(); + if (args.installSource === 'registry') { const { pkgkey, force, ignoreConstraints, spaceId } = args; + + const matchingBundledPackage = bundledPackages.find( + (pkg) => Registry.pkgToPkgKey(pkg) === pkgkey + ); + + if (matchingBundledPackage) { + logger.debug( + `found bundled package for requested install of ${pkgkey} - installing from bundled package archive` + ); + + const response = installPackageByUpload({ + savedObjectsClient, + esClient, + archiveBuffer: matchingBundledPackage.buffer, + contentType: 'application/zip', + spaceId, + }); + + return response; + } + logger.debug(`kicking off install of ${pkgkey} from registry`); const response = installPackageFromRegistry({ savedObjectsClient, diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.ts index 12712905b1d36..c70b064684a96 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.ts @@ -21,7 +21,6 @@ import type { InstallSource, RegistryPackage, RegistrySearchResults, - RegistrySearchResult, GetCategoriesRequest, } from '../../../types'; import { @@ -35,6 +34,8 @@ import { streamToBuffer } from '../streams'; import { appContextService } from '../..'; import { PackageNotFoundError, PackageCacheError, RegistryResponseError } from '../../../errors'; +import { getBundledPackageByName } from '../packages/bundled_packages'; + import { fetchUrl, getResponse, getResponseStream } from './requests'; import { getRegistryUrl } from './registry_url'; @@ -65,20 +66,16 @@ export async function fetchList(params?: SearchParams): Promise; -export async function fetchFindLatestPackage( - packageName: string, - options: { ignoreConstraints?: boolean; throwIfNotFound: false } -): Promise; -export async function fetchFindLatestPackage( +interface FetchFindLatestPackageOptions { + ignoreConstraints?: boolean; +} + +async function _fetchFindLatestPackage( packageName: string, - options?: { ignoreConstraints?: boolean; throwIfNotFound?: boolean } -): Promise { - const { ignoreConstraints = false, throwIfNotFound = true } = options ?? {}; + options?: FetchFindLatestPackageOptions +) { + const { ignoreConstraints = false } = options ?? {}; + const registryUrl = getRegistryUrl(); const url = new URL(`${registryUrl}/search?package=${packageName}&experimental=true`); @@ -86,12 +83,55 @@ export async function fetchFindLatestPackage( setKibanaVersion(url); } - const res = await fetchUrl(url.toString()); - const searchResults = JSON.parse(res); - if (searchResults.length) { + const res = await fetchUrl(url.toString(), 1); + const searchResults: RegistryPackage[] = JSON.parse(res); + + return searchResults; +} + +export async function fetchFindLatestPackageOrThrow( + packageName: string, + options?: FetchFindLatestPackageOptions +) { + try { + const searchResults = await _fetchFindLatestPackage(packageName, options); + + if (!searchResults.length) { + throw new PackageNotFoundError(`[${packageName}] package not found in registry`); + } + + return searchResults[0]; + } catch (error) { + const bundledPackage = await getBundledPackageByName(packageName); + + if (!bundledPackage) { + throw error; + } + + return bundledPackage; + } +} + +export async function fetchFindLatestPackageOrUndefined( + packageName: string, + options?: FetchFindLatestPackageOptions +) { + try { + const searchResults = await _fetchFindLatestPackage(packageName, options); + + if (!searchResults.length) { + return undefined; + } + return searchResults[0]; - } else if (throwIfNotFound) { - throw new PackageNotFoundError(`[${packageName}] package not found in registry`); + } catch (error) { + const bundledPackage = await getBundledPackageByName(packageName); + + if (!bundledPackage) { + return undefined; + } + + return bundledPackage; } } diff --git a/x-pack/plugins/fleet/server/services/epm/registry/requests.ts b/x-pack/plugins/fleet/server/services/epm/registry/requests.ts index f5cabadc5c60d..47084b601a27e 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/requests.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/requests.ts @@ -34,13 +34,13 @@ async function registryFetch(url: string) { } } -export async function getResponse(url: string): Promise { +export async function getResponse(url: string, retries: number = 5): Promise { try { // we only want to retry certain failures like network issues // the rest should only try the one time then fail as they do now const response = await pRetry(() => registryFetch(url), { factor: 2, - retries: 5, + retries, onFailedAttempt: (error) => { // we only want to retry certain types of errors, like `ECONNREFUSED` and other operational errors // and let the others through without retrying @@ -67,13 +67,16 @@ export async function getResponse(url: string): Promise { } } -export async function getResponseStream(url: string): Promise { - const res = await getResponse(url); +export async function getResponseStream( + url: string, + retries?: number +): Promise { + const res = await getResponse(url, retries); return res.body; } -export async function fetchUrl(url: string): Promise { - return getResponseStream(url).then(streamToString); +export async function fetchUrl(url: string, retries?: number): Promise { + return getResponseStream(url, retries).then(streamToString); } // node-fetch throws a FetchError for those types of errors and diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 641136b89fb30..13a0f452fe9f5 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -41,6 +41,7 @@ import type { ListResult, UpgradePackagePolicyDryRunResponseItem, RegistryDataStream, + InstallablePackage, } from '../../common'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../constants'; import { @@ -55,7 +56,6 @@ import type { UpdatePackagePolicy, PackagePolicy, PackagePolicySOAttributes, - RegistryPackage, DryRunPackagePolicy, } from '../types'; import type { ExternalCallback } from '..'; @@ -71,6 +71,7 @@ import { appContextService } from '.'; import { removeOldAssets } from './epm/packages/cleanup'; import type { PackageUpdateEvent, UpdateEventType } from './upgrade_sender'; import { sendTelemetryEvents } from './upgrade_sender'; +import { getArchivePackage } from './epm/archive'; export type InputsOverride = Partial & { vars?: Array; @@ -134,7 +135,8 @@ class PackagePolicyService { pkgVersion: packagePolicy.package.version, }); - let pkgInfo; + let pkgInfo: PackageInfo; + if (options?.skipEnsureInstalled) pkgInfo = await pkgInfoPromise; else { const [, packageInfo] = await Promise.all([ @@ -162,16 +164,21 @@ class PackagePolicyService { } validatePackagePolicyOrThrow(packagePolicy, pkgInfo); - const registryPkgInfo = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version); + let installablePackage: InstallablePackage | undefined = + getArchivePackage(pkgInfo)?.packageInfo; + + if (!installablePackage) { + installablePackage = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version); + } inputs = await this._compilePackagePolicyInputs( - registryPkgInfo, + installablePackage, pkgInfo, packagePolicy.vars || {}, inputs ); - elasticsearch = registryPkgInfo.elasticsearch; + elasticsearch = installablePackage.elasticsearch; } const isoDate = new Date().toISOString(); @@ -400,14 +407,20 @@ class PackagePolicyService { validatePackagePolicyOrThrow(packagePolicy, pkgInfo); - const registryPkgInfo = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version); + let installablePackage: InstallablePackage | undefined = + getArchivePackage(pkgInfo)?.packageInfo; + + if (!installablePackage) { + installablePackage = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version); + } + inputs = await this._compilePackagePolicyInputs( - registryPkgInfo, + installablePackage, pkgInfo, packagePolicy.vars || {}, inputs ); - elasticsearch = registryPkgInfo.elasticsearch; + elasticsearch = installablePackage.elasticsearch; } await soClient.update( @@ -799,14 +812,19 @@ class PackagePolicyService { } public async _compilePackagePolicyInputs( - registryPkgInfo: RegistryPackage, + installablePackage: InstallablePackage, pkgInfo: PackageInfo, vars: PackagePolicy['vars'], inputs: PackagePolicyInput[] ): Promise { const inputsPromises = inputs.map(async (input) => { - const compiledInput = await _compilePackagePolicyInput(registryPkgInfo, pkgInfo, vars, input); - const compiledStreams = await _compilePackageStreams(registryPkgInfo, pkgInfo, vars, input); + const compiledInput = await _compilePackagePolicyInput(pkgInfo, vars, input); + const compiledStreams = await _compilePackageStreams( + installablePackage, + pkgInfo, + vars, + input + ); return { ...input, compiled_input: compiledInput, @@ -917,7 +935,6 @@ function assignStreamIdToInput(packagePolicyId: string, input: NewPackagePolicyI } async function _compilePackagePolicyInput( - registryPkgInfo: RegistryPackage, pkgInfo: PackageInfo, vars: PackagePolicy['vars'], input: PackagePolicyInput @@ -942,7 +959,7 @@ async function _compilePackagePolicyInput( return undefined; } - const [pkgInputTemplate] = await getAssetsData(registryPkgInfo, (path: string) => + const [pkgInputTemplate] = await getAssetsData(pkgInfo, (path: string) => path.endsWith(`/agent/input/${packageInput.template_path!}`) ); @@ -958,13 +975,13 @@ async function _compilePackagePolicyInput( } async function _compilePackageStreams( - registryPkgInfo: RegistryPackage, + installablePackage: InstallablePackage, pkgInfo: PackageInfo, vars: PackagePolicy['vars'], input: PackagePolicyInput ) { const streamsPromises = input.streams.map((stream) => - _compilePackageStream(registryPkgInfo, pkgInfo, vars, input, stream) + _compilePackageStream(pkgInfo, vars, input, stream) ); return await Promise.all(streamsPromises); @@ -1007,7 +1024,6 @@ export function _applyIndexPrivileges( } async function _compilePackageStream( - registryPkgInfo: RegistryPackage, pkgInfo: PackageInfo, vars: PackagePolicy['vars'], input: PackagePolicyInput, @@ -1050,7 +1066,7 @@ async function _compilePackageStream( const datasetPath = packageDataStream.path; const [pkgStreamTemplate] = await getAssetsData( - registryPkgInfo, + pkgInfo, (path: string) => path.endsWith(streamFromPkg.template_path), datasetPath ); diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts index 6d6d641381da2..518b79b9e8547 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts @@ -33,12 +33,12 @@ import { } from './preconfiguration'; import { outputService } from './output'; import { packagePolicyService } from './package_policy'; -import { getBundledPackages } from './epm/packages/get_bundled_packages'; +import { getBundledPackages } from './epm/packages/bundled_packages'; import type { InstallPackageParams } from './epm/packages/install'; jest.mock('./agent_policy_update'); jest.mock('./output'); -jest.mock('./epm/packages/get_bundled_packages'); +jest.mock('./epm/packages/bundled_packages'); jest.mock('./epm/archive'); const mockedOutputService = outputService as jest.Mocked; @@ -121,7 +121,7 @@ function getPutPreconfiguredPackagesMock() { jest.mock('./epm/registry', () => ({ ...jest.requireActual('./epm/registry'), - async fetchFindLatestPackage(packageName: string): Promise { + async fetchFindLatestPackageOrThrow(packageName: string): Promise { return { name: packageName, version: '1.0.0', @@ -164,12 +164,6 @@ jest.mock('./epm/packages/install', () => ({ // Treat the buffer value passed in tests as the package's name for simplicity const pkgName = archiveBuffer.toString('utf8'); - const installedPackage = mockInstalledPackages.get(pkgName); - - if (installedPackage) { - return installedPackage; - } - // Just install every bundled package at version '1.0.0' const packageInstallation = { name: pkgName, version: '1.0.0', title: pkgName }; mockInstalledPackages.set(pkgName, packageInstallation); @@ -743,11 +737,13 @@ describe('policy preconfiguration', () => { mockedGetBundledPackages.mockResolvedValue([ { name: 'test_package', + version: '1.0.0', buffer: Buffer.from('test_package'), }, { name: 'test_package_2', + version: '1.0.0', buffer: Buffer.from('test_package_2'), }, ]); @@ -784,6 +780,7 @@ describe('policy preconfiguration', () => { mockedGetBundledPackages.mockResolvedValue([ { name: 'test_package', + version: '1.0.0', buffer: Buffer.from('test_package'), }, ]); @@ -823,6 +820,7 @@ describe('policy preconfiguration', () => { mockedGetBundledPackages.mockResolvedValue([ { name: 'test_package', + version: '1.0.0', buffer: Buffer.from('test_package'), }, ]); diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index e9d97856a926f..e9c079d435e7e 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -181,9 +181,6 @@ export async function ensurePreconfiguredPackagesAndPolicies( packagesToInstall, force: true, // Always force outdated packages to be installed if a later version isn't installed spaceId, - // During setup, we'll try to install preconfigured packages from the versions bundled with Kibana - // whenever possible - preferredSource: 'bundled', }); const fulfilledPackages = []; diff --git a/x-pack/plugins/fleet/server/types/index.tsx b/x-pack/plugins/fleet/server/types/index.tsx index 9d3e912864785..91303046485d9 100644 --- a/x-pack/plugins/fleet/server/types/index.tsx +++ b/x-pack/plugins/fleet/server/types/index.tsx @@ -50,6 +50,7 @@ export type { EsAssetReference, KibanaAssetReference, RegistryPackage, + BundledPackage, InstallablePackage, AssetType, Installable, diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts index a803b7224d0b4..da8efafe8b637 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts @@ -218,7 +218,7 @@ export default function (providerContext: FtrProviderContext) { package: { name: 'endpoint', title: 'Endpoint', - version: '1.3.0-dev.0', + version: '1.4.1', }, }) .expect(200); @@ -236,7 +236,7 @@ export default function (providerContext: FtrProviderContext) { package: { name: 'endpoint', title: 'Endpoint', - version: '1.3.0-dev.0', + version: '1.3.0', }, }) .expect(400); diff --git a/x-pack/test/fleet_api_integration/config.ts b/x-pack/test/fleet_api_integration/config.ts index fb9dc7b6b4ce6..28af25c20181a 100644 --- a/x-pack/test/fleet_api_integration/config.ts +++ b/x-pack/test/fleet_api_integration/config.ts @@ -15,7 +15,7 @@ import { defineDockerServersConfig } from '@kbn/test'; // example: https://beats-ci.elastic.co/blue/organizations/jenkins/Ingest-manager%2Fpackage-storage/detail/snapshot/74/pipeline/257#step-302-log-1. // It should be updated any time there is a new Docker image published for the Snapshot Distribution of the Package Registry. export const dockerImage = - 'docker.elastic.co/package-registry/distribution@sha256:de952debe048d903fc73e8a4472bb48bb95028d440cba852f21b863d47020c61'; + 'docker.elastic.co/package-registry/distribution@sha256:c5bf8e058727de72e561b228f4b254a14a6f880e582190d01bd5ff74318e1d0b'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts')); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 67c2f9b386425..7e1ac8e5481bc 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -15,7 +15,7 @@ import { pageObjects } from './page_objects'; // example: https://beats-ci.elastic.co/blue/organizations/jenkins/Ingest-manager%2Fpackage-storage/detail/snapshot/74/pipeline/257#step-302-log-1. // It should be updated any time there is a new Docker image published for the Snapshot Distribution of the Package Registry. export const dockerImage = - 'docker.elastic.co/package-registry/distribution:ffcbe0ba25b9bae09a671249cbb1b25af0aa1994'; + 'docker.elastic.co/package-registry/distribution@sha256:c5bf8e058727de72e561b228f4b254a14a6f880e582190d01bd5ff74318e1d0b'; // the default export of config files must be a config provider // that returns an object with the projects config values diff --git a/x-pack/test/functional_synthetics/config.js b/x-pack/test/functional_synthetics/config.js index 28cd7e3b099dc..f9074812a7e22 100644 --- a/x-pack/test/functional_synthetics/config.js +++ b/x-pack/test/functional_synthetics/config.js @@ -17,7 +17,7 @@ import { pageObjects } from './page_objects'; // example: https://beats-ci.elastic.co/blue/organizations/jenkins/Ingest-manager%2Fpackage-storage/detail/snapshot/74/pipeline/257#step-302-log-1. // It should be updated any time there is a new Docker image published for the Snapshot Distribution of the Package Registry that updates Synthetics. export const dockerImage = - 'docker.elastic.co/package-registry/distribution:48202133e7506873aff3cc7c3b1d284158727779'; + 'docker.elastic.co/package-registry/distribution@sha256:c5bf8e058727de72e561b228f4b254a14a6f880e582190d01bd5ff74318e1d0b'; // the default export of config files must be a config provider // that returns an object with the projects config values diff --git a/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts b/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts index b0d935c408e4d..898d527245b16 100644 --- a/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts +++ b/x-pack/test/functional_synthetics/services/uptime/synthetics_package.ts @@ -50,6 +50,7 @@ export function SyntheticsPackageProvider({ getService }: FtrProviderContext) { apiRequest = retry.try(() => { return supertest .get(INGEST_API_EPM_PACKAGES) + .query({ experimental: true }) .set('kbn-xsrf', 'xxx') .expect(200) .catch((error) => { From 3f77c5f73f1f7dd4d0234c3693eb3e6be2f95faf Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 13:08:15 -0700 Subject: [PATCH 026/104] skip suite blocking es promotion (#125848) --- .../test/rule_registry/spaces_only/tests/trial/create_rule.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts index be3146f34c30e..5d0e73f6f07a5 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts @@ -39,7 +39,8 @@ const SPACE_ID = 'space1'; export default function registryRulesApiTest({ getService }: FtrProviderContext) { const es = getService('es'); - describe('Rule Registry API', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125848 + describe.skip('Rule Registry API', () => { describe('with write permissions', () => { it('does not bootstrap indices on plugin startup', async () => { const { body: targetIndices } = await getAlertsTargetIndices(getService, obsOnly, SPACE_ID); From 45b719d1b363d81339a5978d55780f24ef8f3647 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 13:13:14 -0700 Subject: [PATCH 027/104] skip suite blocking es promotion (#125851) --- .../security_and_spaces/tests/create_rules.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts index 0fcb98b51fa06..3bc547ccb6a9a 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts @@ -44,7 +44,8 @@ export default ({ getService }: FtrProviderContext) => { const supertestWithoutAuth = getService('supertestWithoutAuth'); const log = getService('log'); - describe('create_rules', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('create_rules', () => { describe('creating rules', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); From 08b7d18b639227ec5f97d569d21e19faf7eef181 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 16 Feb 2022 12:26:17 -0800 Subject: [PATCH 028/104] [DOCS] Remove unnecessary image from Slack connector (#125715) --- .../connectors/action-types/slack.asciidoc | 2 -- .../images/slack-copy-webhook-url.png | Bin 21738 -> 0 bytes 2 files changed, 2 deletions(-) delete mode 100644 docs/management/connectors/images/slack-copy-webhook-url.png diff --git a/docs/management/connectors/action-types/slack.asciidoc b/docs/management/connectors/action-types/slack.asciidoc index 6dffebd9d9354..19abf9119b837 100644 --- a/docs/management/connectors/action-types/slack.asciidoc +++ b/docs/management/connectors/action-types/slack.asciidoc @@ -76,5 +76,3 @@ URL, set up an an **Incoming Webhook Integration** through the Slack console: image::images/slack-add-webhook-integration.png[] . Click *Add Incoming Webhook Integration*. . Copy the generated webhook URL so you can paste it into your Slack connector form. -+ -image::images/slack-copy-webhook-url.png[] diff --git a/docs/management/connectors/images/slack-copy-webhook-url.png b/docs/management/connectors/images/slack-copy-webhook-url.png deleted file mode 100644 index 805f5719980dabed80af6a8fbaebf194b52305c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21738 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 CHZpVo From ecefde8743934666c5c16f854d0fe669f303c91d Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Wed, 16 Feb 2022 14:48:49 -0600 Subject: [PATCH 029/104] [Security Solution] remove metadata integ test explicit timeouts (#125742) --- .../services/endpoint.ts | 93 ++++++++++++++----- .../apis/metadata.ts | 33 +++++-- 2 files changed, 95 insertions(+), 31 deletions(-) diff --git a/x-pack/test/security_solution_endpoint/services/endpoint.ts b/x-pack/test/security_solution_endpoint/services/endpoint.ts index dbc2c165577c7..e2d3a77e46f61 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint.ts @@ -11,6 +11,7 @@ import { FtrService } from '../../functional/ftr_provider_context'; import { metadataCurrentIndexPattern, metadataTransformPrefix, + METADATA_UNITED_INDEX, } from '../../../plugins/security_solution/common/endpoint/constants'; import { deleteIndexedHostsAndAlerts, @@ -28,6 +29,7 @@ export class EndpointTestResources extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly kbnClient = this.ctx.getService('kibanaServer'); private readonly transform = this.ctx.getService('transform'); + private readonly config = this.ctx.getService('config'); private generateTransformId(endpointPackageVersion?: string): string { return `${metadataTransformPrefix}-${endpointPackageVersion ?? ''}`; @@ -137,13 +139,46 @@ export class EndpointTestResources extends FtrService { return deleteIndexedHostsAndAlerts(this.esClient as Client, this.kbnClient, indexedData); } + private async waitForIndex( + ids: string[], + index: string, + body: any = {}, + timeout: number = this.config.get('timeouts.waitFor') + ) { + // If we have a specific number of endpoint hosts to check for, then use that number, + // else we just want to make sure the index has data, thus just having one in the index will do + const size = ids.length || 1; + + await this.retry.waitForWithTimeout(`endpoint hosts in ${index}`, timeout, async () => { + try { + const searchResponse = await this.esClient.search({ + index, + size, + body, + rest_total_hits_as_int: true, + }); + + return searchResponse.hits.total === size; + } catch (error) { + // We ignore 404's (index might not exist) + if (error instanceof errors.ResponseError && error.statusCode === 404) { + return false; + } + + // Wrap the ES error so that we get a good stack trace + throw new EndpointError(error.message, error); + } + }); + } + /** * Waits for endpoints to show up on the `metadata-current` index. * Optionally, specific endpoint IDs (agent.id) can be provided to ensure those specific ones show up. * * @param [ids] optional list of ids to check for. If empty, it will just check if data exists in the index + * @param [timeout] optional max timeout to waitFor in ms. default is 20000. */ - async waitForEndpoints(ids: string[] = []) { + async waitForEndpoints(ids: string[] = [], timeout = this.config.get('timeouts.waitFor')) { const body = ids.length ? { query: { @@ -159,35 +194,49 @@ export class EndpointTestResources extends FtrService { }, } : { + size: 1, query: { match_all: {}, }, }; - // If we have a specific number of endpoint hosts to check for, then use that number, - // else we just want to make sure the index has data, thus just having one in the index will do - const size = ids.length || 1; - - await this.retry.waitFor('endpoint hosts', async () => { - try { - const searchResponse = await this.esClient.search({ - index: metadataCurrentIndexPattern, - size, - body, - rest_total_hits_as_int: true, - }); + await this.waitForIndex(ids, metadataCurrentIndexPattern, body, timeout); + } - return searchResponse.hits.total === size; - } catch (error) { - // We ignore 404's (index might not exist) - if (error instanceof errors.ResponseError && error.statusCode === 404) { - return false; + /** + * Waits for endpoints to show up on the `metadata_united` index. + * Optionally, specific endpoint IDs (agent.id) can be provided to ensure those specific ones show up. + * + * @param [ids] optional list of ids to check for. If empty, it will just check if data exists in the index + * @param [timeout] optional max timeout to waitFor in ms. default is 20000. + */ + async waitForUnitedEndpoints(ids: string[] = [], timeout = this.config.get('timeouts.waitFor')) { + const body = ids.length + ? { + query: { + bool: { + filter: [ + { + terms: { + 'agent.id': ids, + }, + }, + // make sure that both endpoint and agent portions are populated + // since agent is likely to be populated first + { exists: { field: 'united.endpoint.agent.id' } }, + { exists: { field: 'united.agent.agent.id' } }, + ], + }, + }, } + : { + size: 1, + query: { + match_all: {}, + }, + }; - // Wrap the ES error so that we get a good stack trace - throw new EndpointError(error.message, error); - } - }); + await this.waitForIndex(ids, METADATA_UNITED_INDEX, body, timeout); } /** diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts index e6fd28d279fe7..86c8e32f3bdf9 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts @@ -35,8 +35,13 @@ import { TRANSFORM_STATES } from '../../../plugins/security_solution/common/cons export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const endpointTestResources = getService('endpointTestResources'); describe('test metadata apis', () => { + before(async () => { + await endpointTestResources.setMetadataTransformFrequency('1s'); + }); + describe('list endpoints GET route', () => { describe('with .metrics-endpoint.metadata_united_default index', () => { const numberOfHostsInFixture = 2; @@ -58,17 +63,22 @@ export default function ({ getService }: FtrProviderContext) { const policyId = policy.integrationPolicies[0].policy_id; const currentTime = new Date().getTime(); + const agentDocs = generateAgentDocs(currentTime, policyId); + await Promise.all([ - bulkIndex(getService, AGENTS_INDEX, generateAgentDocs(currentTime, policyId)), + bulkIndex(getService, AGENTS_INDEX, agentDocs), bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(currentTime)), ]); - // wait for latest metadata transform to run - await new Promise((r) => setTimeout(r, 60000)); + await endpointTestResources.waitForEndpoints( + agentDocs.map((doc) => doc.agent.id), + 60000 + ); await startTransform(getService, METADATA_UNITED_TRANSFORM); - - // wait for united metadata transform to run - await new Promise((r) => setTimeout(r, 30000)); + await endpointTestResources.waitForUnitedEndpoints( + agentDocs.map((doc) => doc.agent.id), + 60000 + ); }); after(async () => { @@ -295,9 +305,14 @@ export default function ({ getService }: FtrProviderContext) { // otherwise it won't hit metrics-endpoint.metadata_current_default index await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); await deleteIndex(getService, METADATA_UNITED_INDEX); - await bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(timestamp)); - // wait for transform - await new Promise((r) => setTimeout(r, 60000)); + + const metadataDocs = generateMetadataDocs(timestamp); + await bulkIndex(getService, METADATA_DATASTREAM, metadataDocs); + + await endpointTestResources.waitForEndpoints( + Array.from(new Set(metadataDocs.map((doc) => doc.agent.id))), + 60000 + ); }); // the endpoint uses data streams and es archiver does not support deleting them at the moment so we need // to do it manually From 41d5c26ac1c1d79719377f270234fc59d8d9fb35 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Wed, 16 Feb 2022 22:04:16 +0100 Subject: [PATCH 030/104] [SecuritySolution][Endpoint] Hoist all function declarations in data generator script (#125759) * Hoist all function declarations refs elastic/kibana/pull/125476 * update alias --- .../scripts/endpoint/resolver_generator_script.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts index 74a51a6e16199..7181b97b4ff68 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts @@ -17,13 +17,13 @@ import { ANCESTRY_LIMIT, EndpointDocGenerator } from '../../common/endpoint/gene main(); -const handleErr = (err: unknown) => { +function handleErr(err: unknown) { if (err instanceof errors.ResponseError && err.statusCode !== 404) { console.log(JSON.stringify(err, null, 2)); // eslint-disable-next-line no-process-exit process.exit(1); } -}; +} async function deleteIndices(indices: string[], client: Client) { for (const index of indices) { @@ -84,7 +84,7 @@ async function deleteUser(esClient: Client, username: string): Promise<{ found: }); } -const updateURL = ({ +function updateURL({ url, user, protocol, @@ -92,7 +92,7 @@ const updateURL = ({ url: string; user?: { username: string; password: string }; protocol?: string; -}): string => { +}): string { const urlObject = new URL(url); if (user) { urlObject.username = user.username; @@ -102,7 +102,7 @@ const updateURL = ({ urlObject.protocol = protocol; } return urlObject.href; -}; +} async function main() { const argv = yargs.help().options({ @@ -247,7 +247,7 @@ async function main() { default: false, }, withNewUser: { - alias: 'nu', + alias: 'wnu', describe: 'If the --fleet flag is enabled, using `--withNewUser=username:password` would add a new user with \ the given username, password and `superuser`, `kibana_system` roles. Adding a new user would also write \ From ba06b99fff4400e2e42b30c7c96ac3351031d1dd Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 14:09:56 -0700 Subject: [PATCH 031/104] skip suite blocking es promition (#125848) --- .../spaces_only/tests/trial/lifecycle_executor.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts index 15ef6a7673d08..281be665301d6 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts @@ -59,7 +59,8 @@ export default function createLifecycleExecutorApiTest({ getService }: FtrProvid return Promise.resolve(client); }; - describe('createLifecycleExecutor', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125848 + describe.skip('createLifecycleExecutor', () => { let ruleDataClient: IRuleDataClient; before(async () => { // First we need to setup the data service. This happens within the From 0e928dc2e562bd7ea20d835535a8ad756a3bb545 Mon Sep 17 00:00:00 2001 From: Justin Ibarra Date: Wed, 16 Feb 2022 12:15:11 -0900 Subject: [PATCH 032/104] [Detection Rules] Add 8.1 rules (#125834) --- ...collection_cloudtrail_logging_created.json | 4 +- ...ion_gcp_pub_sub_subscription_creation.json | 4 +- ...collection_gcp_pub_sub_topic_creation.json | 4 +- ...llection_microsoft_365_new_inbox_rule.json | 19 +- .../collection_posh_audio_capture.json | 4 +- .../collection_posh_keylogger.json | 6 +- .../collection_posh_screen_grabber.json | 4 +- ...ommand_and_control_common_webservices.json | 6 +- .../command_and_control_iexplore_via_com.json | 4 +- ...ontrol_port_forwarding_added_registry.json | 4 +- ...tial_access_dcsync_replication_rights.json | 62 ++++ ...ntial_access_disable_kerberos_preauth.json | 59 ++++ ..._access_kerberoasting_unusual_process.json | 4 +- ...redential_access_mfa_push_brute_force.json | 49 +++ ..._365_brute_force_user_account_attempt.json | 6 +- ...65_potential_password_spraying_attack.json | 6 +- ..._access_mod_wdigest_security_provider.json | 4 +- ...e_network_logon_provider_modification.json | 6 +- .../credential_access_posh_minidump.json | 8 +- ...credential_access_posh_request_ticket.json | 83 +++++ ...edelegationprivilege_assigned_to_user.json | 55 ++++ .../credential_access_shadow_credentials.json | 56 ++++ ...l_access_suspicious_comsvcs_imageload.json | 4 +- ...ccess_suspicious_lsass_access_memdump.json | 6 +- ..._suspicious_lsass_access_via_snapshot.json | 6 +- ..._symbolic_link_to_shadow_copy_created.json | 6 +- ...ccess_user_excessive_sso_logon_errors.json | 4 +- ..._evasion_agent_spoofing_mismatched_id.json | 4 +- ...evasion_agent_spoofing_multiple_hosts.json | 4 +- .../defense_evasion_amsienable_key_mod.json | 4 +- ...se_evasion_cloudtrail_logging_deleted.json | 4 +- ...nse_evasion_cloudwatch_alarm_deletion.json | 4 +- ...vasion_defender_disabled_via_registry.json | 4 +- ...ion_defender_exclusion_via_powershell.json | 4 +- ...asion_disable_posh_scriptblocklogging.json | 56 ++++ ...defense_evasion_ec2_flow_log_deletion.json | 4 +- ...ense_evasion_ec2_network_acl_deletion.json | 4 +- ...n_elasticache_security_group_creation.json | 4 +- ...he_security_group_modified_or_deleted.json | 4 +- .../defense_evasion_event_hub_deletion.json | 4 +- ...ense_evasion_firewall_policy_deletion.json | 6 +- ...on_frontdoor_firewall_policy_deletion.json | 6 +- ...e_evasion_gcp_logging_bucket_deletion.json | 4 +- ...nse_evasion_gcp_logging_sink_deletion.json | 4 +- ...ion_gcp_pub_sub_subscription_deletion.json | 4 +- ...se_evasion_gcp_pub_sub_topic_deletion.json | 4 +- ...e_evasion_guardduty_detector_deletion.json | 4 +- ...sion_hide_encoded_executable_registry.json | 6 +- ...nse_evasion_kubernetes_events_deleted.json | 4 +- ...vasion_masquerading_trusted_directory.json | 4 +- ...osoft_365_exchange_dlp_policy_removed.json | 4 +- ...change_malware_filter_policy_deletion.json | 4 +- ..._365_exchange_malware_filter_rule_mod.json | 4 +- ...65_exchange_safe_attach_rule_disabled.json | 4 +- ...oft_365_mailboxauditbypassassociation.json | 6 +- ..._evasion_microsoft_defender_tampering.json | 4 +- ...e_evasion_ms_office_suspicious_regmod.json | 67 +++++ ...ense_evasion_network_watcher_deletion.json | 4 +- .../defense_evasion_posh_assembly_load.json | 4 +- .../defense_evasion_posh_compressed.json | 6 +- ...efense_evasion_posh_process_injection.json | 6 +- ..._powershell_windows_firewall_disabled.json | 4 +- ...sion_s3_bucket_configuration_deletion.json | 4 +- ...ion_scheduledjobs_at_protocol_enabled.json | 4 +- .../defense_evasion_sip_provider_mod.json | 6 +- ...ackdoor_service_disabled_via_registry.json | 4 +- ...ense_evasion_suppression_rule_created.json | 4 +- ...defense_evasion_suspicious_wmi_script.json | 4 +- .../defense_evasion_waf_acl_deletion.json | 4 +- ...asion_waf_rule_or_rule_group_deletion.json | 4 +- .../discovery_adfind_command_activity.json | 4 +- .../discovery_net_command_system_account.json | 4 +- ...scovery_posh_suspicious_api_functions.json | 6 +- ..._post_exploitation_external_ip_lookup.json | 6 +- ...very_privileged_localgroup_membership.json | 4 +- .../execution_posh_portable_executable.json | 4 +- .../execution_posh_psreflect.json | 6 +- ...er_program_connecting_to_the_internet.json | 4 +- ...tion_suspicious_java_netcon_childproc.json | 63 ++++ ..._365_exchange_transport_rule_creation.json | 4 +- ...osoft_365_exchange_transport_rule_mod.json | 4 +- .../exfiltration_rds_snapshot_restored.json | 4 +- ..._eventbridge_rule_disabled_or_deleted.json | 4 +- .../impact_cloudwatch_log_group_deletion.json | 4 +- ...impact_cloudwatch_log_stream_deletion.json | 4 +- ...mpact_efs_filesystem_or_mount_deleted.json | 4 +- .../impact_gcp_iam_role_deletion.json | 4 +- .../impact_gcp_storage_bucket_deleted.json | 4 +- ...p_virtual_private_cloud_route_created.json | 4 +- .../impact_iam_group_deletion.json | 4 +- .../impact_kubernetes_pod_deleted.json | 4 +- ...oft_365_potential_ransomware_activity.json | 4 +- ...t_365_unusual_volume_of_file_deletion.json | 6 +- .../impact_rds_cluster_deletion.json | 4 +- .../impact_rds_group_deletion.json | 4 +- ...mpact_virtual_network_device_modified.json | 8 +- ...copy_deletion_or_resized_via_vssadmin.json | 4 +- .../rules/prepackaged_rules/index.ts | 284 ++++++++++-------- ...l_access_gcp_iam_custom_role_creation.json | 4 +- ...5_exchange_anti_phish_policy_deletion.json | 4 +- ...soft_365_exchange_anti_phish_rule_mod.json | 4 +- ...osoft_365_exchange_safelinks_disabled.json | 4 +- ...65_user_restricted_from_sending_email.json | 4 +- ...cess_o365_user_reported_phish_malware.json | 65 ++++ ...ta_user_attempted_unauthorized_access.json | 4 +- ...n_lanman_nullsessionpipe_modification.json | 6 +- .../lateral_movement_dns_server_overflow.json | 4 +- ...al_movement_malware_uploaded_onedrive.json | 53 ++++ ..._movement_malware_uploaded_sharepoint.json | 53 ++++ ...lateral_movement_rdp_enabled_registry.json | 4 +- .../lateral_movement_rdp_sharprdp_target.json | 6 +- ...ateral_movement_scheduled_task_target.json | 4 +- ...nt_service_control_spawned_script_int.json | 8 +- ...exchange_dkim_signing_config_disabled.json | 4 +- ..._teams_custom_app_interaction_allowed.json | 4 +- .../ml_cloudtrail_error_message_spike.json | 4 +- .../ml_cloudtrail_rare_method_by_country.json | 4 +- .../ml_rare_process_by_host_windows.json | 4 +- .../persistence_ad_adminsdholder.json | 45 +++ .../persistence_appcertdlls_registry.json | 4 +- ...re_global_administrator_role_assigned.json | 57 ++++ .../persistence_ec2_network_acl_creation.json | 4 +- ..._group_configuration_change_detection.json | 4 +- ...tence_evasion_registry_ifeo_injection.json | 6 +- ...egistry_startup_shell_folder_modified.json | 8 +- ...e_suspicious_mailbox_right_delegation.json | 8 +- ..._gcp_iam_service_account_key_deletion.json | 4 +- .../persistence_iam_group_creation.json | 4 +- ...istence_local_scheduled_task_creation.json | 4 +- ...5_exchange_management_role_assignment.json | 4 +- ..._365_global_administrator_role_assign.json | 57 ++++ ...oft_365_teams_external_access_enabled.json | 4 +- ...rosoft_365_teams_guest_access_enabled.json | 4 +- ...istence_msds_alloweddelegateto_krbtgt.json | 67 +++++ .../persistence_rds_cluster_creation.json | 4 +- .../persistence_rds_group_creation.json | 4 +- .../persistence_rds_instance_creation.json | 4 +- .../persistence_registry_uncommon.json | 6 +- .../persistence_remote_password_reset.json | 4 +- .../persistence_route_table_created.json | 4 +- ...tence_route_table_modified_or_deleted.json | 4 +- ...persistence_run_key_and_startup_broad.json | 6 +- ...saver_engine_unexpected_child_process.json | 4 +- .../persistence_services_registry.json | 6 +- ...stence_suspicious_com_hijack_registry.json | 6 +- ...e_suspicious_service_created_registry.json | 6 +- .../persistence_time_provider_mod.json | 6 +- ...sistence_via_hidden_run_key_valuename.json | 4 +- ...sa_security_support_provider_registry.json | 4 +- ...tence_via_wmi_stdregprov_run_services.json | 6 +- ...calation_aws_suspicious_saml_activity.json | 4 +- ...ilege_escalation_disable_uac_registry.json | 4 +- ...netes_rolebindings_created_or_patched.json | 6 +- ...ege_escalation_group_policy_iniscript.json | 4 +- ...lation_group_policy_privileged_groups.json | 6 +- ...scalation_group_policy_scheduled_task.json | 4 +- ...rivilege_escalation_installertakeover.json | 6 +- ...privilege_escalation_lsa_auth_package.json | 6 +- ...ion_new_or_modified_federation_domain.json | 4 +- ...vilege_escalation_pkexec_envar_hijack.json | 70 +++++ ...ion_port_monitor_print_pocessor_abuse.json | 8 +- ...ooler_malicious_registry_modification.json | 5 +- ...ation_printspooler_registry_copyfiles.json | 6 +- ...calation_rogue_windir_environment_var.json | 6 +- ...lation_samaccountname_spoofing_attack.json | 75 +++++ ...ilege_escalation_sts_assumerole_usage.json | 4 +- ...ion_unusual_printspooler_childprocess.json | 4 +- ...on_windows_service_via_unusual_client.json | 58 ++++ .../threat_intel_filebeat8x.json | 12 +- .../threat_intel_fleet_integrations.json | 8 +- 170 files changed, 1652 insertions(+), 504 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dcsync_replication_rights.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_disable_kerberos_preauth.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mfa_push_brute_force.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_request_ticket.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_seenabledelegationprivilege_assigned_to_user.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_shadow_credentials.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_posh_scriptblocklogging.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ms_office_suspicious_regmod.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_java_netcon_childproc.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_o365_user_reported_phish_malware.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_onedrive.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_sharepoint.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ad_adminsdholder.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_global_administrator_role_assigned.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_global_administrator_role_assign.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_msds_alloweddelegateto_krbtgt.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_pkexec_envar_hijack.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_samaccountname_spoofing_attack.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_windows_service_via_unusual_client.json diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json index 7debf76f371c5..41b9c053ca41a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json @@ -4,7 +4,7 @@ ], "description": "Identifies the creation of an AWS log trail that specifies the settings for delivery of log data.", "false_positives": [ - "Trail creations may be made by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Trail creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Trail creations may be made by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Trail creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json index a24c533e2c272..cfa1ed57a34e7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies the creation of a subscription in Google Cloud Platform (GCP). In GCP, the publisher-subscriber relationship (Pub/Sub) is an asynchronous messaging service that decouples event-producing and event-processing services. A subscription is a named resource representing the stream of messages to be delivered to the subscribing application.", "false_positives": [ - "Subscription creations may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Subscription creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Subscription creations may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Subscription creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json index af20bdf46e42a..43f69c10740a5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies the creation of a topic in Google Cloud Platform (GCP). In GCP, the publisher-subscriber relationship (Pub/Sub) is an asynchronous messaging service that decouples event-producing and event-processing services. A topic is used to forward messages from publishers to subscribers.", "false_positives": [ - "Topic creations may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Topic creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Topic creations may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Topic creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json index 1a9ccc9c70696..30c63674ef284 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json @@ -4,9 +4,9 @@ "Gary Blackwell", "Austin Songer" ], - "description": "Identifies when a new Inbox rule is created in Microsoft 365. Inbox rules process messages in the Inbox based on conditions and take actions, such as moving a message to a specified folder or deleting a message. Adequate permissions are required on the mailbox to create an Inbox rule.", + "description": "Identifies when a new Inbox forwarding rule is created in Microsoft 365. Inbox rules process messages in the Inbox based on conditions and take actions. In this case, the rules will forward the emails to a defined address. Attackers can abuse Inbox Rules to intercept and exfiltrate email data while not requiring organization-wide configuration changes nor privileges to set those.", "false_positives": [ - "An inbox rule may be created by a system or network administrator. Verify that the configuration change was expected. Exceptions can be added to this rule to filter expected behavior." + "Users and Administrators can create inbox rules for legitimate purposes. Verify if it complies with the company policy and done with the user's consent. Exceptions can be added to this rule to filter expected behavior." ], "from": "now-30m", "index": [ @@ -15,17 +15,18 @@ ], "language": "kuery", "license": "Elastic License v2", - "name": "Microsoft 365 New Inbox Rule Created", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-InboxRule\" and event.outcome:success\n", + "name": "Microsoft 365 Inbox Forwarding Rule Created", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:Exchange and\nevent.category:web and event.action:\"New-InboxRule\" and\n (\n o365audit.Parameters.ForwardTo:* or\n o365audit.Parameters.ForwardAsAttachmentTo:* or\n o365audit.Parameters.RedirectTo:*\n ) \n and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/responding-to-a-compromised-email-account?view=o365-worldwide", "https://docs.microsoft.com/en-us/powershell/module/exchange/new-inboxrule?view=exchange-ps", - "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/detect-and-remediate-outlook-rules-forms-attack?view=o365-worldwide" + "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/detect-and-remediate-outlook-rules-forms-attack?view=o365-worldwide", + "https://raw.githubusercontent.com/PwC-IR/Business-Email-Compromise-Guide/main/Extractor%20Cheat%20Sheet.pdf" ], - "risk_score": 21, + "risk_score": 47, "rule_id": "ec8efb0c-604d-42fa-ac46-ed1cfbc38f78", - "severity": "low", + "severity": "medium", "tags": [ "Elastic", "Cloud", @@ -60,5 +61,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json index 741c07504d920..491ba75865885 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "PowerShell Suspicious Script with Audio Capture Capabilities", - "note": "## Triage and analysis.\n\n### Investigating PowerShell Suspicious Script with Audio Capture Capabilities\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can use PowerShell to interact with the Windows API and capture audio from input devices connected to the\ncomputer.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree)\n- Inspect any file or network events from the suspicious powershell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n- Potential Process Injection via PowerShell - 2e29e96a-b67c-455a-afe4-de6183431d0d\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis.\n\n### Investigating PowerShell Suspicious Script with Audio Capture Capabilities\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can use PowerShell to interact with the Windows API and capture audio from input devices connected to the\ncomputer.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious PowerShell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n- Potential Process Injection via PowerShell - 2e29e96a-b67c-455a-afe4-de6183431d0d\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and \n powershell.file.script_block_text : (\n Get-MicrophoneAudio or (waveInGetNumDevs and mciSendStringA)\n )\n", "references": [ "https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Get-MicrophoneAudio.ps1" @@ -67,5 +67,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_keylogger.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_keylogger.json index f128a2cac13cc..8cac619d6c7dd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_keylogger.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_keylogger.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Detects the use of Win32 API Functions that can be used to capture user Keystrokes in PowerShell Scripts. Attackers use this technique to capture user input, looking for credentials and/or other valuable data.", + "description": "Detects the use of Win32 API Functions that can be used to capture user keystrokes in PowerShell scripts. Attackers use this technique to capture user input, looking for credentials and/or other valuable data.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "PowerShell Keylogging Script", - "note": "## Triage and analysis.\n\n### Investigating PowerShell Keylogging Script\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can abuse PowerShell capabilities to capture user Keystrokes with the goal of stealing credentials and other\nvaluable information as Credit Card data and confidential conversations.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree)\n- Inspect any file or network events from the suspicious powershell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis.\n\n### Investigating PowerShell Keylogging Script\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can abuse PowerShell capabilities to capture user keystrokes with the goal of stealing credentials and other\nvaluable information as credit card data and confidential conversations.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious PowerShell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and \n ( \n powershell.file.script_block_text : (GetAsyncKeyState or NtUserGetAsyncKeyState or GetKeyboardState or Get-Keystrokes) or \n powershell.file.script_block_text : ((SetWindowsHookA or SetWindowsHookW or SetWindowsHookEx or SetWindowsHookExA or NtUserSetWindowsHookEx) and (GetForegroundWindow or GetWindowTextA or GetWindowTextW or WM_KEYBOARD_LL))\n )\n", "references": [ "https://github.com/EmpireProject/Empire/blob/master/data/module_source/collection/Get-Keystrokes.ps1", @@ -75,5 +75,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_screen_grabber.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_screen_grabber.json index 916939dc652a6..afab1df677e3d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_screen_grabber.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_screen_grabber.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Detects PowerShell Scripts that can take screenshots, which is a common feature in post-exploitation kits and RATs (Remote Access Tools).", + "description": "Detects PowerShell scripts that can take screenshots, which is a common feature in post-exploitation kits and remote access tools (RATs).", "from": "now-9m", "index": [ "winlogbeat-*", @@ -66,5 +66,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_common_webservices.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_common_webservices.json index 50deb969b57a6..665049d1d9b13 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_common_webservices.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_common_webservices.json @@ -5,9 +5,7 @@ "description": "Adversaries may implement command and control communications that use common web services in order to hide their activity. This attack technique is typically targeted to an organization and uses web services common to the victim network which allows the adversary to blend into legitimate traffic. activity. These popular services are typically targeted since they have most likely been used before a compromise and allow adversaries to blend in the network.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -69,5 +67,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_iexplore_via_com.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_iexplore_via_com.json index d0039ab4f02d4..f86a96c81460c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_iexplore_via_com.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_iexplore_via_com.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Potential Command and Control via Internet Explorer", - "query": "sequence by host.id, user.id with maxspan = 5s\n [library where dll.name : \"IEProxy.dll\" and process.name : (\"rundll32.exe\", \"regsvr32.exe\")]\n [process where event.type == \"start\" and process.parent.name : \"iexplore.exe\" and process.parent.args : \"-Embedding\"]\n /* IE started via COM in normal conditions makes few connections, mainly to Microsoft and OCSP related domains, add FPs here */\n [network where network.protocol == \"dns\" and process.name : \"iexplore.exe\" and\n not dns.question.name :\n (\n \"*.microsoft.com\",\n \"*.digicert.com\",\n \"*.msocsp.com\",\n \"*.windowsupdate.com\",\n \"*.bing.com\",\n \"*.identrust.com\",\n \"*.sharepoint.com\",\n \"*.office365.com\",\n \"*.office.com\"\n )\n ]\n", + "query": "sequence by host.id, user.name with maxspan = 5s\n [library where dll.name : \"IEProxy.dll\" and process.name : (\"rundll32.exe\", \"regsvr32.exe\")]\n [process where event.type == \"start\" and process.parent.name : \"iexplore.exe\" and process.parent.args : \"-Embedding\"]\n /* IE started via COM in normal conditions makes few connections, mainly to Microsoft and OCSP related domains, add FPs here */\n [network where network.protocol == \"dns\" and process.name : \"iexplore.exe\" and\n not dns.question.name :\n (\n \"*.microsoft.com\",\n \"*.digicert.com\",\n \"*.msocsp.com\",\n \"*.windowsupdate.com\",\n \"*.bing.com\",\n \"*.identrust.com\",\n \"*.sharepoint.com\",\n \"*.office365.com\",\n \"*.office.com\"\n )\n ] /* with runs=5 */\n", "risk_score": 47, "rule_id": "acd611f3-2b93-47b3-a0a3-7723bcc46f6d", "severity": "medium", @@ -66,5 +66,5 @@ } ], "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_forwarding_added_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_forwarding_added_registry.json index 65612e6c28f20..91ca5d8d74166 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_forwarding_added_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_forwarding_added_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Port Forwarding Rule Addition", - "query": "registry where registry.path : \"HKLM\\\\SYSTEM\\\\ControlSet*\\\\Services\\\\PortProxy\\\\v4tov4\\\\*\"\n", + "query": "registry where registry.path : \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Services\\\\PortProxy\\\\v4tov4\\\\*\"\n", "references": [ "https://www.fireeye.com/blog/threat-research/2019/01/bypassing-network-restrictions-through-rdp-tunneling.html" ], @@ -45,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dcsync_replication_rights.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dcsync_replication_rights.json new file mode 100644 index 0000000000000..ee85eacf12b75 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dcsync_replication_rights.json @@ -0,0 +1,62 @@ +{ + "author": [ + "Elastic" + ], + "description": "This rule identifies when a User Account starts the Active Directory Replication Process. Attackers can use the DCSync technique to get credential information of individual accounts or the entire domain, thus compromising the entire domain.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-system.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Potential Credential Access via DCSync", + "note": "## Triage and analysis.\n\n### Investigating Active Directory Replication From User Account\n\nActive Directory replication is the process by which the changes that originate on one domain controller are\nautomatically transferred to other domain controllers that store the same data. \n\nActive Directory data takes the form of objects that have properties, or attributes. Each object is an instance\nof an object class, and object classes and their respective attributes are defined in the Active Directory schema.\nThe values of the attributes define the object, and a change to a value of an attribute must be transferred from\nthe domain controller on which it occurs to every other domain controller that stores a replica of that object.\n\nAdversaries can use the DCSync technique that uses Windows Domain Controller's API to simulate the replication process\nfrom a remote domain controller, compromising major credential material such as the Kerberos krbtgt keys used\nlegitimately for tickets creation, but also tickets forging by attackers. This attack requires some extended privileges\nto succeed (DS-Replication-Get-Changes and DS-Replication-Get-Changes-All), which are granted by default to members of\nthe Administrators, Domain Admins, Enterprise Admins, and Domain Controllers groups. Privileged accounts can be abused\nto grant controlled objects the right to DCsync/Replicate.\n\nMore details can be found on [Threat Hunter Playbook](https://threathunterplaybook.com/library/windows/active_directory_replication.html?highlight=dcsync#directory-replication-services-auditing).\nand [The Hacker Recipes](https://www.thehacker.recipes/ad/movement/credentials/dumping/dcsync)\n\nThis rule will monitor for Event ID 4662 (Operation was performed on an Active Directory object) and identify events that use the access\nmask 0x100 (Control Access) and properties that contain at least one of the following or their equivalent Schema-Id-GUID\n(DS-Replication-Get-Changes, DS-Replication-Get-Changes-All, DS-Replication-Get-Changes-In-Filtered-Set). It also filters out events that\nuse computer accounts and also Azure AD Connect MSOL accounts (more details [here](https://techcommunity.microsoft.com/t5/microsoft-defender-for-identity/ad-connect-msol-user-suspected-dcsync-attack/m-p/788028)).\n\n#### Possible investigation steps:\n\n- Identify the account that performed the action\n- Confirm whether the account owner is aware of the operation\n- Investigate other alerts related to the user/host in the last 48 hours.\n- Correlate security events 4662 and 4624 (Logon Type 3) by their Logon ID (`winlog.logon.id`) on the Domain Controller (DC) that received\nthe replication request. This will tell you where the AD replication request came from, and if it came from another DC or not.\n- Investigate which credentials were compromised (e.g. All accounts were replicated or a specific account).\n\n### False Positive Analysis\n\n- This activity should not happen legitimately. Any potential B-TP (Benign True Positive) should be mapped and monitored by the security\nteam as replication should be done by Domain Controllers only. Any account that performs this activity can put the domain at risk for not\nhaving the same security standards (Long, complex, random passwords that change frequently) as computer accounts, exposing it to credential\ncracking attacks (Kerberoasting, brute force, etc.).\n\n### Response and Remediation\n\n- Initiate the incident response process based on the outcome of the triage\n- In case of specific credentials were compromised:\n - Reset the password for the accounts\n- In case of the entire domain or the `krbtgt` user were compromised:\n - Activate your incident response plan for total Active Directory compromise which should include, but not be limited to, a password\n reset (twice) of the `krbtgt` user.\n\n## Config\n\nThe 'Audit Directory Service Access' logging policy must be configured for (Success, Failure).\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Access (Success,Failure)\n```\n", + "query": "any where event.action == \"Directory Service Access\" and\n event.code == \"4662\" and winlog.event_data.Properties : (\n\n /* Control Access Rights/Permissions Symbol */\n\n \"*DS-Replication-Get-Changes*\",\n \"*DS-Replication-Get-Changes-All*\",\n \"*DS-Replication-Get-Changes-In-Filtered-Set*\",\n\n /* Identifying GUID used in ACE */\n\n \"*1131f6ad-9c07-11d1-f79f-00c04fc2dcd2*\",\n \"*1131f6aa-9c07-11d1-f79f-00c04fc2dcd2*\",\n \"*89e95b76-444d-4c62-991a-0facbeda640c*\") \n \n /* The right to perform an operation controlled by an extended access right. */\n\n and winlog.event_data.AccessMask : \"0x100\" and\n not winlog.event_data.SubjectUserName : (\"*$\", \"MSOL_*\")\n", + "references": [ + "https://threathunterplaybook.com/notebooks/windows/06_credential_access/WIN-180815210510.html", + "https://threathunterplaybook.com/library/windows/active_directory_replication.html?highlight=dcsync#directory-replication-services-auditing", + "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/builtin/security/win_ad_replication_non_machine_account.yml", + "https://github.com/atc-project/atomic-threat-coverage/blob/master/Atomic_Threat_Coverage/Logging_Policies/LP_0027_windows_audit_directory_service_access.md", + "https://attack.stealthbits.com/privilege-escalation-using-mimikatz-dcsync", + "https://www.thehacker.recipes/ad/movement/credentials/dumping/dcsync" + ], + "risk_score": 73, + "rule_id": "9f962927-1a4f-45f3-a57b-287f2c7029c1", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Credential Access", + "Active Directory" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1003", + "name": "OS Credential Dumping", + "reference": "https://attack.mitre.org/techniques/T1003/", + "subtechnique": [ + { + "id": "T1003.006", + "name": "DCSync", + "reference": "https://attack.mitre.org/techniques/T1003/006/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_disable_kerberos_preauth.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_disable_kerberos_preauth.json new file mode 100644 index 0000000000000..781a90638b187 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_disable_kerberos_preauth.json @@ -0,0 +1,59 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies the modification of account Kerberos preauthentication options. An adversary with GenericWrite/GenericAll rights over the account can maliciously modify these settings to perform offline password cracking attacks such as AS-REP roasting.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*", + "logs-system.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Kerberos Preauthentication Disabled for User", + "note": "## Config\n\nThe 'Audit User Account Management' logging policy must be configured for (Success, Failure).\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nAccount Management > \nAudit User Account Management (Success,Failure)\n```\n", + "query": "event.code:4738 and message:\"'Don't Require Preauth' - Enabled\"\n", + "references": [ + "https://www.harmj0y.net/blog/activedirectory/roasting-as-reps", + "https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4738", + "https://github.com/atc-project/atomic-threat-coverage/blob/master/Atomic_Threat_Coverage/Logging_Policies/LP_0026_windows_audit_user_account_management.md" + ], + "risk_score": 47, + "rule_id": "e514d8cd-ed15-4011-84e2-d15147e059f1", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Credential Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1558", + "name": "Steal or Forge Kerberos Tickets", + "reference": "https://attack.mitre.org/techniques/T1558/", + "subtechnique": [ + { + "id": "T1558.004", + "name": "AS-REP Roasting", + "reference": "https://attack.mitre.org/techniques/T1558/004/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberoasting_unusual_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberoasting_unusual_process.json index 8fc7cd7b379b8..f1d18a80a4652 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberoasting_unusual_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberoasting_unusual_process.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Kerberos Traffic from Unusual Process", - "query": "network where event.type == \"start\" and network.direction : (\"outgoing\", \"egress\") and\n destination.port == 88 and source.port >= 49152 and\n process.executable != \"C:\\\\Windows\\\\System32\\\\lsass.exe\" and destination.address !=\"127.0.0.1\" and destination.address !=\"::1\" and\n /* insert False Positives here */\n not process.name in (\"swi_fc.exe\", \"fsIPcam.exe\", \"IPCamera.exe\", \"MicrosoftEdgeCP.exe\", \"MicrosoftEdge.exe\", \"iexplore.exe\", \"chrome.exe\", \"msedge.exe\", \"opera.exe\", \"firefox.exe\")\n", + "query": "network where event.type == \"start\" and network.direction : (\"outgoing\", \"egress\") and\n destination.port == 88 and source.port >= 49152 and\n process.executable != \"C:\\\\Windows\\\\System32\\\\lsass.exe\" and destination.address !=\"127.0.0.1\" and destination.address !=\"::1\" and\n /* insert false positives here */\n not process.name in (\"swi_fc.exe\", \"fsIPcam.exe\", \"IPCamera.exe\", \"MicrosoftEdgeCP.exe\", \"MicrosoftEdge.exe\", \"iexplore.exe\", \"chrome.exe\", \"msedge.exe\", \"opera.exe\", \"firefox.exe\")\n", "risk_score": 47, "rule_id": "897dc6b5-b39f-432a-8d75-d3730d50c782", "severity": "medium", @@ -45,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mfa_push_brute_force.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mfa_push_brute_force.json new file mode 100644 index 0000000000000..9fa6f3a10b31c --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mfa_push_brute_force.json @@ -0,0 +1,49 @@ +{ + "author": [ + "Elastic" + ], + "description": "Detect when an attacker abuses the Multi-Factor authentication mechanism by repeatedly issuing login requests until the user eventually accepts the Okta push notification. An adversary may attempt to bypass the Okta MFA policies configured for an organization to obtain unauthorized access.", + "index": [ + "filebeat-*", + "logs-okta*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Potential Abuse of Repeated MFA Push Notifications", + "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "sequence by user.email with maxspan=10m\n [any where event.module == \"okta\" and event.action == \"user.mfa.okta_verify.deny_push\"]\n [any where event.module == \"okta\" and event.action == \"user.mfa.okta_verify.deny_push\"]\n [any where event.module == \"okta\" and event.action == \"user.authentication.sso\"]\n", + "references": [ + "https://www.mandiant.com/resources/russian-targeting-gov-business" + ], + "risk_score": 73, + "rule_id": "97a8e584-fd3b-421f-9b9d-9c9d9e57e9d7", + "severity": "high", + "tags": [ + "Elastic", + "Identity", + "Okta", + "Continuous Monitoring", + "SecOps", + "Identity and Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1110", + "name": "Brute Force", + "reference": "https://attack.mitre.org/techniques/T1110/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json index 6bd3606d3b1f9..823d0d29b301f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json @@ -16,8 +16,8 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempts to Brute Force a Microsoft 365 User Account", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:(AzureActiveDirectory or Exchange) and\n event.category:authentication and event.action:(UserLoginFailed or PasswordLogonInitialAuthUsingPassword) and\n not o365.audit.LogonError:(UserAccountNotFound or EntitlementGrantsNotFound or UserStrongAuthEnrollmentRequired or\n UserStrongAuthClientAuthNRequired or InvalidReplyTo) and event.outcome:failure\n", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:(AzureActiveDirectory or Exchange) and\n event.category:authentication and event.action:(UserLoginFailed or PasswordLogonInitialAuthUsingPassword) and\n not o365.audit.LogonError:(UserAccountNotFound or EntitlementGrantsNotFound or UserStrongAuthEnrollmentRequired or\n UserStrongAuthClientAuthNRequired or InvalidReplyTo) and event.outcome:success\n", "references": [ "https://blueteamblog.com/7-ways-to-monitor-your-office-365-logs-using-siem" ], @@ -56,5 +56,5 @@ "value": 10 }, "type": "threshold", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json index c5a20b643b6d7..ba4500b56c6df 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json @@ -14,8 +14,8 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Password Spraying of Microsoft 365 User Accounts", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:(Exchange or AzureActiveDirectory) and event.category:authentication and \nevent.action:(\"UserLoginFailed\" or \"PasswordLogonInitialAuthUsingPassword\") and event.outcome:failure\n", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:(Exchange or AzureActiveDirectory) and event.category:authentication and \nevent.action:(\"UserLoginFailed\" or \"PasswordLogonInitialAuthUsingPassword\") and event.outcome:success\n", "risk_score": 73, "rule_id": "3efee4f0-182a-40a8-a835-102c68a4175d", "severity": "high", @@ -51,5 +51,5 @@ "value": 25 }, "type": "threshold", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mod_wdigest_security_provider.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mod_wdigest_security_provider.json index cd7a6959958fc..d2360c9889dea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mod_wdigest_security_provider.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mod_wdigest_security_provider.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Modification of WDigest Security Provider", - "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path:\"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\SecurityProviders\\\\WDigest\\\\UseLogonCredential\" and\n registry.data.strings:\"1\"\n", + "query": "registry where event.type : (\"creation\", \"change\") and\n registry.path : \n \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\SecurityProviders\\\\WDigest\\\\UseLogonCredential\"\n and registry.data.strings : (\"1\", \"0x00000001\")\n", "references": [ "https://www.csoonline.com/article/3438824/how-to-detect-and-halt-credential-theft-via-windows-wdigest.html", "https://www.praetorian.com/blog/mitigating-mimikatz-wdigest-cleartext-credential-theft?edition=2019" @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_persistence_network_logon_provider_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_persistence_network_logon_provider_modification.json index 166ddf7c5592d..d83bf00d9860c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_persistence_network_logon_provider_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_persistence_network_logon_provider_modification.json @@ -8,9 +8,7 @@ ], "from": "now-9m", "index": [ - "auditbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -65,5 +63,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json index 1bdba2064b4a4..b9cbc6f0c60cc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json @@ -2,9 +2,9 @@ "author": [ "Elastic" ], - "description": "This rule detects PowerShell scripts that have capabilities to dump process memory using WindowsErrorReporting or Dbghelp.dll MiniDumpWriteDump. Attackers can use this tooling to dump LSASS and get access to credentials.", + "description": "This rule detects PowerShell scripts capable of dumping process memory using WindowsErrorReporting or Dbghelp.dll MiniDumpWriteDump. Attackers can use this tooling to dump LSASS and get access to credentials.", "false_positives": [ - "Powershell Scripts that use this capability for troubleshooting." + "PowerShell scripts that use this capability for troubleshooting." ], "from": "now-9m", "index": [ @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "PowerShell MiniDump Script", - "note": "## Triage and analysis.\n\n### Investigating PowerShell MiniDump Script\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nProcess Memory Dump capabilities can be abused by attackers to extract credentials from LSASS or to obtain other privileged\ninformation stored in the process memory.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree)\n- Inspect any file or network events from the suspicious powershell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n- Potential Process Injection via PowerShell - 2e29e96a-b67c-455a-afe4-de6183431d0d\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis.\n\n### Investigating PowerShell MiniDump Script\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nProcess Memory Dump capabilities can be abused by attackers to extract credentials from LSASS or to obtain other privileged\ninformation stored in the process memory.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious PowerShell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n- Potential Process Injection via PowerShell - 2e29e96a-b67c-455a-afe4-de6183431d0d\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and powershell.file.script_block_text:(MiniDumpWriteDump or MiniDumpWithFullMemory or pmuDetirWpmuDiniM)\n", "references": [ "https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Out-Minidump.ps1", @@ -79,5 +79,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 3 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_request_ticket.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_request_ticket.json new file mode 100644 index 0000000000000..ca1ea37561b20 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_request_ticket.json @@ -0,0 +1,83 @@ +{ + "author": [ + "Elastic" + ], + "description": "Detects PowerShell scripts that have the capability of requesting kerberos tickets, which is common step in Kerberoasting toolkits to crack service accounts.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "PowerShell Kerberos Ticket Request", + "query": "event.category:process and \n powershell.file.script_block_text : (\n KerberosRequestorSecurityToken\n )\n", + "references": [ + "https://cobalt.io/blog/kerberoast-attack-techniques", + "https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/Invoke-Kerberoast.ps1" + ], + "risk_score": 47, + "rule_id": "eb610e70-f9e6-4949-82b9-f1c5bcd37c39", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Credential Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1003", + "name": "OS Credential Dumping", + "reference": "https://attack.mitre.org/techniques/T1003/" + }, + { + "id": "T1558", + "name": "Steal or Forge Kerberos Tickets", + "reference": "https://attack.mitre.org/techniques/T1558/", + "subtechnique": [ + { + "id": "T1558.003", + "name": "Kerberoasting", + "reference": "https://attack.mitre.org/techniques/T1558/003/" + } + ] + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.001", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1059/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_seenabledelegationprivilege_assigned_to_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_seenabledelegationprivilege_assigned_to_user.json new file mode 100644 index 0000000000000..20738784c1c5e --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_seenabledelegationprivilege_assigned_to_user.json @@ -0,0 +1,55 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies the assignment of the SeEnableDelegationPrivilege sensitive \"user right\" to a user. The SeEnableDelegationPrivilege \"user right\" enables computer and user accounts to be trusted for delegation. Attackers can abuse this right to compromise Active Directory accounts and elevate their privileges.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*", + "logs-system.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Sensitive Privilege SeEnableDelegationPrivilege assigned to a User", + "note": "## Config\n\nThe 'Audit Authorization Policy Change' logging policy must be configured for (Success, Failure).\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration >\nWindows Settings >\nSecurity Settings >\nAdvanced Audit Policy Configuration >\nAudit Policies >\nPolicy Change >\nAudit Authorization Policy Change (Success,Failure)\n```\n", + "query": "event.action: \"Authorization Policy Change\" and event.code:4704 and winlog.event_data.PrivilegeList:\"SeEnableDelegationPrivilege\"\n", + "references": [ + "https://www.harmj0y.net/blog/activedirectory/the-most-dangerous-user-right-you-probably-have-never-heard-of", + "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/builtin/security/win_alert_active_directory_user_control.yml", + "https://github.com/atc-project/atomic-threat-coverage/blob/master/Atomic_Threat_Coverage/Logging_Policies/LP_0105_windows_audit_authorization_policy_change.md" + ], + "risk_score": 73, + "rule_id": "f494c678-3c33-43aa-b169-bb3d5198c41d", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Credential Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_shadow_credentials.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_shadow_credentials.json new file mode 100644 index 0000000000000..261510427a628 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_shadow_credentials.json @@ -0,0 +1,56 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identify the modification of the msDS-KeyCredentialLink attribute in an Active Directory Computer or User Object. Attackers can abuse control over the object and create a key pair, append to raw public key in the attribute, and obtain persistent and stealthy access to the target user or computer object.", + "false_positives": [ + "Modifications in the msDS-KeyCredentialLink attribute can be done legitimately by the Azure AD Connect synchronization account or the ADFS service account. These accounts can be added as Exceptions." + ], + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*", + "logs-system.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Potential Shadow Credentials added to AD Object", + "note": "## Config\n\nThe 'Audit Directory Service Changes' logging policy must be configured for (Success, Failure).\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n\nThe above policy does not cover User objects, so we need to set up an AuditRule using https://github.com/OTRF/Set-AuditRule.\nAs this specifies the msDS-KeyCredentialLink Attribute GUID, it is expected to be low noise.\n\n```\nSet-AuditRule -AdObjectPath 'AD:\\CN=Users,DC=Domain,DC=com' -WellKnownSidType WorldSid -Rights WriteProperty -InheritanceFlags Children -AttributeGUID 5b47d60f-6090-40b2-9f37-2a4de88f3063 -AuditFlags Success\n```\n", + "query": "event.action:\"Directory Service Changes\" and event.code:\"5136\" and winlog.event_data.AttributeLDAPDisplayName:\"msDS-KeyCredentialLink\"\n", + "references": [ + "https://posts.specterops.io/shadow-credentials-abusing-key-trust-account-mapping-for-takeover-8ee1a53566ab", + "https://www.thehacker.recipes/ad/movement/kerberos/shadow-credentials", + "https://github.com/OTRF/Set-AuditRule" + ], + "risk_score": 73, + "rule_id": "79f97b31-480e-4e63-a7f4-ede42bf2c6de", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Credential Access", + "Active Directory" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1556", + "name": "Modify Authentication Process", + "reference": "https://attack.mitre.org/techniques/T1556/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_comsvcs_imageload.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_comsvcs_imageload.json index d5b3a0acd4314..ce37891caaea4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_comsvcs_imageload.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_comsvcs_imageload.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Identifies suspicious renamed COMSVCS.DLL Image Load, which exports the MiniDump function that can be used to dump a process memory. This may indicate an attempt to dump LSASS memory while bypassing command line based detection in preparation for credential access.", + "description": "Identifies suspicious renamed COMSVCS.DLL Image Load, which exports the MiniDump function that can be used to dump a process memory. This may indicate an attempt to dump LSASS memory while bypassing command-line based detection in preparation for credential access.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -52,5 +52,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_memdump.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_memdump.json index 14416213c101c..f51f049f03641 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_memdump.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_memdump.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Identifies suspicious access to LSASS handle from a call trace pointing to DBGHelp.dll or DBGCore.dll, which both export the MiniDumpWriteDump method that can be used to dump LSASS memory content in preperation for credential access.", + "description": "Identifies suspicious access to LSASS handle from a call trace pointing to DBGHelp.dll or DBGCore.dll, which both export the MiniDumpWriteDump method that can be used to dump LSASS memory content in preparation for credential access.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -11,7 +11,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Potential Credential Access via LSASS Memory Dump", - "query": "process where event.code == \"10\" and\n winlog.event_data.TargetImage : \"?:\\\\WINDOWS\\\\system32\\\\lsass.exe\" and\n \n /* DLLs exporting MiniDumpWriteDump API to create an lsass mdmp*/\n winlog.event_data.CallTrace : (\"*dbhelp*\", \"*dbgcore*\") and\n \n /* case of lsass crashing */\n not process.executable : (\"?:\\\\Windows\\\\System32\\\\WerFault.exe\", \"?:\\\\Windows\\\\System32\\\\WerFaultSecure.exe\")\n", + "query": "process where event.code == \"10\" and\n winlog.event_data.TargetImage : \"?:\\\\WINDOWS\\\\system32\\\\lsass.exe\" and\n \n /* DLLs exporting MiniDumpWriteDump API to create an lsass mdmp*/\n winlog.event_data.CallTrace : (\"*dbghelp*\", \"*dbgcore*\") and\n \n /* case of lsass crashing */\n not process.executable : (\"?:\\\\Windows\\\\System32\\\\WerFault.exe\", \"?:\\\\Windows\\\\System32\\\\WerFaultSecure.exe\")\n", "references": [ "https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dump-credentials-from-lsass-process-without-mimikatz" ], @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_via_snapshot.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_via_snapshot.json index f5a444deabeed..95b1ff9fac197 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_via_snapshot.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_lsass_access_via_snapshot.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Identifies suspicious access to an LSASS handle via PssCaptureSnapShot where two successive process access are performed by the same process and targeting two different instances of LSASS. This may indicate an attempt to evade detection and dump LSASS memory for credential access.", + "description": "Identifies suspicious access to an LSASS handle via PssCaptureSnapShot where two successive process accesses are performed by the same process and targeting two different instances of LSASS. This may indicate an attempt to evade detection and dump LSASS memory for credential access.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential LSASS Memory Dump via PssCaptureSnapShot", - "note": "## Config\n\nThis is meant to run only on datasources using agents v7.14+ since versions prior to that will be missing the threshold\nrule cardinality feature.", + "note": "## Config\n\nThis is meant to run only on datasources using Elastic Agent 7.14+ since versions prior to that will be missing the threshold\nrule cardinality feature.", "query": "event.category:process and event.code:10 and\n winlog.event_data.TargetImage:(\"C:\\\\Windows\\\\system32\\\\lsass.exe\" or\n \"c:\\\\Windows\\\\system32\\\\lsass.exe\" or\n \"c:\\\\Windows\\\\System32\\\\lsass.exe\")\n", "references": [ "https://www.matteomalvica.com/blog/2019/12/02/win-defender-atp-cred-bypass/", @@ -65,5 +65,5 @@ }, "timestamp_override": "event.ingested", "type": "threshold", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_symbolic_link_to_shadow_copy_createdcredential_access_symbolic_link_to_shadow_copy_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_symbolic_link_to_shadow_copy_createdcredential_access_symbolic_link_to_shadow_copy_created.json index 80604018e8d55..bbf07b959285f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_symbolic_link_to_shadow_copy_createdcredential_access_symbolic_link_to_shadow_copy_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_symbolic_link_to_shadow_copy_createdcredential_access_symbolic_link_to_shadow_copy_created.json @@ -2,9 +2,9 @@ "author": [ "Austin Songer" ], - "description": "Identifies the creation of symbolic links to a shadow copy. Symbolic Links can be used to access files in the shadow copy, including sensitive files that may contain credential information.", + "description": "Identifies the creation of symbolic links to a shadow copy. Symbolic links can be used to access files in the shadow copy, including sensitive files that may contain credential information.", "false_positives": [ - "Legitimate administrative activity related to shadow copies" + "Legitimate administrative activity related to shadow copies." ], "from": "now-9m", "index": [ @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_user_excessive_sso_logon_errors.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_user_excessive_sso_logon_errors.json index 14f44ed3c3824..408a12cf85ce2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_user_excessive_sso_logon_errors.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_user_excessive_sso_logon_errors.json @@ -15,7 +15,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "O365 Excessive Single Sign-On Logon Errors", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:AzureActiveDirectory and event.category:authentication and o365.audit.LogonError:\"SsoArtifactInvalidOrExpired\"\n", "risk_score": 73, "rule_id": "2de10e77-c144-4e69-afb7-344e7127abd0", @@ -52,5 +52,5 @@ "value": 5 }, "type": "threshold", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_mismatched_id.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_mismatched_id.json index bf33f1d70f7ea..b5dfb8c37a47e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_mismatched_id.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_mismatched_id.json @@ -4,7 +4,7 @@ ], "description": "Detects events which have a mismatch on the expected event agent ID. The status \"agent_id_mismatch\" occurs when the expected agent ID associated with the API key does not match the actual agent ID in an event. This could indicate attempts to spoof events in order to masquerade actual activity to evade detection.", "false_positives": [ - "This is meant to run only on datasources using agents v7.14+ since versions prior to that will be missing the necessary field, resulting in false positives." + "This is meant to run only on datasources using Elastic Agent 7.14+ since versions prior to that will be missing the necessary field, resulting in false positives." ], "from": "now-9m", "index": [ @@ -43,5 +43,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_multiple_hosts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_multiple_hosts.json index 4163e79cfd8db..e74f382e2291f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_multiple_hosts.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_agent_spoofing_multiple_hosts.json @@ -4,7 +4,7 @@ ], "description": "Detects when multiple hosts are using the same agent ID. This could occur in the event of an agent being taken over and used to inject illegitimate documents into an instance as an attempt to spoof events in order to masquerade actual activity to evade detection.", "false_positives": [ - "This is meant to run only on datasources using agents v7.14+ since versions prior to that will be missing the necessary field, resulting in false positives." + "This is meant to run only on datasources using Elastic Agent 7.14+ since versions prior to that will be missing the necessary field, resulting in false positives." ], "from": "now-9m", "index": [ @@ -55,5 +55,5 @@ }, "timestamp_override": "event.ingested", "type": "threshold", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json index 80f855706e0fd..a1905ffa6c9aa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Modification of AmsiEnable Registry Key", - "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path: \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows Script\\\\Settings\\\\AmsiEnable\" and\n registry.data.strings: \"0\"\n", + "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path : (\n \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows Script\\\\Settings\\\\AmsiEnable\",\n \"HKU\\\\*\\\\Software\\\\Microsoft\\\\Windows Script\\\\Settings\\\\AmsiEnable\"\n ) and\n registry.data.strings: (\"0\", \"0x00000000\")\n", "references": [ "https://hackinparis.com/data/slides/2019/talks/HIP2019-Dominic_Chell-Cracking_The_Perimeter_With_Sharpshooter.pdf", "https://docs.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal" @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json index 744543ab8a1f0..cc131b5236a62 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an AWS log trail. An adversary may delete trails in an attempt to evade defenses.", "false_positives": [ - "Trail deletions may be made by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Trail deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Trail deletions may be made by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Trail deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json index 61806b640fae2..e188a1ee50c65 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an AWS CloudWatch alarm. An adversary may delete alarms in an attempt to evade defenses.", "false_positives": [ - "Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Alarm deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Alarm deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_disabled_via_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_disabled_via_registry.json index 8b3557e4a8fbd..5571bb2b9e317 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_disabled_via_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_disabled_via_registry.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Windows Defender Disabled via Registry Modification", "note": "## Triage and analysis\n\nDetections should be investigated to identify if the hosts and users are authorized to use this tool. As this rule detects post-exploitation process activity, investigations into this should be prioritized.", - "query": "registry where event.type in (\"creation\", \"change\") and\n ((registry.path:\"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\DisableAntiSpyware\" and\n registry.data.strings:\"1\") or\n (registry.path:\"HKLM\\\\System\\\\ControlSet*\\\\Services\\\\WinDefend\\\\Start\" and\n registry.data.strings in (\"3\", \"4\")))\n", + "query": "registry where event.type in (\"creation\", \"change\") and\n (\n (\n registry.path:\"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\DisableAntiSpyware\" and\n registry.data.strings: (\"1\", \"0x00000001\")\n ) or\n (\n registry.path:\"HKLM\\\\System\\\\*ControlSet*\\\\Services\\\\WinDefend\\\\Start\" and\n registry.data.strings in (\"3\", \"4\", \"0x00000003\", \"0x00000004\")\n )\n )\n", "references": [ "https://thedfirreport.com/2020/12/13/defender-control/" ], @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json index 44fed396b8ea8..ecd200c116b04 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Windows Defender Exclusions Added via PowerShell", - "note": "## Triage and analysis\n\n### Investigating Windows Defender Exclusions\n\nMicrosoft Windows Defender is an anti-virus product built-in within Microsoft Windows. Since this software product is\nused to prevent and stop malware, it's important to monitor what specific exclusions are made to the product's configuration\nsettings. These can often be signs of an adversary or malware trying to bypass Windows Defender's capabilities. One of the more\nnotable [examples](https://www.cyberbit.com/blog/endpoint-security/latest-trickbot-variant-has-new-tricks-up-its-sleeve/) was observed in 2018 where Trickbot incorporated mechanisms to disable Windows Defense to avoid detection.\n\n#### Possible investigation steps:\n- With this specific rule, it's completely possible to trigger detections on network administrative activity or benign users\nusing scripting and PowerShell to configure the different exclusions for Windows Defender. Therefore, it's important to\nidentify the source of the activity first and determine if there is any mal-intent behind the events.\n- The actual exclusion such as the process, the file or directory should be reviewed in order to determine the original\nintent behind the exclusion. Is the excluded file or process malicious in nature or is it related to software that needs\nto be legitimately whitelisted from Windows Defender?\n\n### False Positive Analysis\n- This rule has a higher chance to produce false positives based on the nature around configuring exclusions by possibly\na network administrator. In order to validate the activity further, review the specific exclusion made and determine based\non the exclusion of the original intent behind the exclusion. There are often many legitimate reasons why exclusions are made\nwith Windows Defender so it's important to gain context around the exclusion.\n\n### Related Rules\n- Windows Defender Disabled via Registry Modification\n- Disabling Windows Defender Security Settings via PowerShell\n\n### Response and Remediation\n- Since this is related to post-exploitation activity, immediate response should be taken to review, investigate and\npotentially isolate further activity\n- If further analysis showed malicious intent was behind the Defender exclusions, administrators should remove\nthe exclusion and ensure antimalware capability has not been disabled or deleted\n- Exclusion lists for antimalware capabilities should always be routinely monitored for review\n", + "note": "## Triage and analysis\n\n### Investigating Windows Defender Exclusions\n\nMicrosoft Windows Defender is an anti-virus product built-in within Microsoft Windows. Since this software product is\nused to prevent and stop malware, it's important to monitor what specific exclusions are made to the product's configuration\nsettings. These can often be signs of an adversary or malware trying to bypass Windows Defender's capabilities. One of the more\nnotable [examples](https://www.cyberbit.com/blog/endpoint-security/latest-trickbot-variant-has-new-tricks-up-its-sleeve/) was observed in 2018 where Trickbot incorporated mechanisms to disable Windows Defense to avoid detection.\n\n#### Possible investigation steps:\n- With this specific rule, it's completely possible to trigger detections on network administrative activity or benign users\nusing scripting and PowerShell to configure the different exclusions for Windows Defender. Therefore, it's important to\nidentify the source of the activity first and determine if there is any mal-intent behind the events.\n- The actual exclusion such as the process, the file or directory should be reviewed in order to determine the original\nintent behind the exclusion. Is the excluded file or process malicious in nature or is it related to software that needs\nto be legitimately allowlisted from Windows Defender?\n\n### False Positive Analysis\n- This rule has a higher chance to produce false positives based on the nature around configuring exclusions by possibly\na network administrator. In order to validate the activity further, review the specific exclusion and based on its\nintent. There are many legitimate reasons for exclusions, so it's important to gain context.\n\n### Related Rules\n- Windows Defender Disabled via Registry Modification\n- Disabling Windows Defender Security Settings via PowerShell\n\n### Response and Remediation\n- Since this is related to post-exploitation activity, take immediate action to review, investigate and\npotentially isolate further activity\n- If further analysis showed malicious intent was behind the Defender exclusions, administrators should remove\nthe exclusion and ensure antimalware capability has not been disabled or deleted\n- Exclusion lists for antimalware capabilities should always be routinely monitored for review\n", "query": "process where event.type == \"start\" and\n (process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") or process.pe.original_file_name in (\"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\")) and\n process.args : (\"*Add-MpPreference*\", \"*Set-MpPreference*\") and\n process.args : (\"*-Exclusion*\")\n", "references": [ "https://www.bitdefender.com/files/News/CaseStudies/study/400/Bitdefender-PR-Whitepaper-MosaicLoader-creat5540-en-EN.pdf" @@ -80,5 +80,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_posh_scriptblocklogging.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_posh_scriptblocklogging.json new file mode 100644 index 0000000000000..f3f321fe6918a --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_posh_scriptblocklogging.json @@ -0,0 +1,56 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies attempts to disable PowerShell Script Block Logging via registry modification. Attackers may disable this logging to conceal their activities in the host and evade detection.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "PowerShell Script Block Logging Disabled", + "query": "registry where event.type == \"change\" and\n registry.path : \n \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows\\\\PowerShell\\\\ScriptBlockLogging\\\\EnableScriptBlockLogging\"\n and registry.data.strings : (\"0\", \"0x00000000\")\n", + "references": [ + "https://admx.help/?Category=Windows_10_2016&Policy=Microsoft.Policies.PowerShell::EnableScriptBlockLogging" + ], + "risk_score": 47, + "rule_id": "818e23e6-2094-4f0e-8c01-22d30f3506c6", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1562", + "name": "Impair Defenses", + "reference": "https://attack.mitre.org/techniques/T1562/", + "subtechnique": [ + { + "id": "T1562.002", + "name": "Disable Windows Event Logging", + "reference": "https://attack.mitre.org/techniques/T1562/002/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json index 8c74783642395..d93764d893ef6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of one or more flow logs in AWS Elastic Compute Cloud (EC2). An adversary may delete flow logs in an attempt to evade defenses.", "false_positives": [ - "Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Flow log deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Flow log deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json index b64f7eed4be8d..0e019e84c8298 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an Amazon Elastic Compute Cloud (EC2) network access control list (ACL) or one of its ingress/egress entries.", "false_positives": [ - "Network ACL's may be deleted by a network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Network ACL deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Network ACL's may be deleted by a network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Network ACL deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -60,5 +60,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_creation.json index 5685ac76b3ef9..38f6d22bef189 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies when an ElastiCache security group has been created.", "false_positives": [ - "A ElastiCache security group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A ElastiCache security group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -57,5 +57,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_modified_or_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_modified_or_deleted.json index 83b58c0c046e0..0ba4be1170091 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_modified_or_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_elasticache_security_group_modified_or_deleted.json @@ -4,7 +4,7 @@ ], "description": "Identifies when an ElastiCache security group has been modified or deleted.", "false_positives": [ - "A ElastiCache security group deletion may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security Group deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A ElastiCache security group deletion may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security Group deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -57,5 +57,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json index a8a2f945c76e6..58cd10a68a612 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies an Event Hub deletion in Azure. An Event Hub is an event processing service that ingests and processes large volumes of events and data. An adversary may delete an Event Hub in an attempt to evade detection.", "false_positives": [ - "Event Hub deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Event Hub deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Event Hub deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Event Hub deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json index 98ee5f6eb8cbf..7d5bf5af25ea6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json @@ -2,9 +2,9 @@ "author": [ "Elastic" ], - "description": "Identifies the deletion of a firewall policy in Azure. An adversary may delete a firewall policy in an attempt to evade defenses and/or to eliminate barriers in carrying out their initiative.", + "description": "Identifies the deletion of a firewall policy in Azure. An adversary may delete a firewall policy in an attempt to evade defenses and/or to eliminate barriers to their objective.", "false_positives": [ - "Firewall policy deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Firewall policy deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Firewall policy deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Firewall policy deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_frontdoor_firewall_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_frontdoor_firewall_policy_deletion.json index c443d45dde4f0..a0b97a358ff07 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_frontdoor_firewall_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_frontdoor_firewall_policy_deletion.json @@ -2,9 +2,9 @@ "author": [ "Austin Songer" ], - "description": "Identifies the deletion of a Frontdoor Web Application Firewall (WAF) Policy in Azure. An adversary may delete a Frontdoor Web Application Firewall (WAF) Policy in an attempt to evade defenses and/or to eliminate barriers in carrying out their initiative.", + "description": "Identifies the deletion of a Frontdoor Web Application Firewall (WAF) Policy in Azure. An adversary may delete a Frontdoor Web Application Firewall (WAF) Policy in an attempt to evade defenses and/or to eliminate barriers to their objective.", "false_positives": [ - "Azure Front Web Application Firewall (WAF) Policy deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Azure Front Web Application Firewall (WAF) Policy deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Azure Front Web Application Firewall (WAF) Policy deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Azure Front Web Application Firewall (WAF) Policy deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json index d2fd746f8971e..69dfd4c1fad1a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies a Logging bucket deletion in Google Cloud Platform (GCP). Log buckets are containers that store and organize log data. A deleted bucket stays in a pending state for 7 days, and Logging continues to route logs to the bucket during that time. To stop routing logs to a deleted bucket, the log sinks can be deleted that have the bucket as a destination, or the filter for the sinks can be modified to stop routing logs to the deleted bucket. An adversary may delete a log bucket to evade detection.", "false_positives": [ - "Logging bucket deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Logging bucket deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Logging bucket deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Logging bucket deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json index 3e103413967fe..f604365ca46e6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies a Logging sink deletion in Google Cloud Platform (GCP). Every time a log entry arrives, Logging compares the log entry to the sinks in that resource. Each sink whose filter matches the log entry writes a copy of the log entry to the sink's export destination. An adversary may delete a Logging sink to evade detection.", "false_positives": [ - "Logging sink deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Logging sink deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Logging sink deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Logging sink deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json index 78435128865f2..b3fe5da917406 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a subscription in Google Cloud Platform (GCP). In GCP, the publisher-subscriber relationship (Pub/Sub) is an asynchronous messaging service that decouples event-producing and event-processing services. A subscription is a named resource representing the stream of messages to be delivered to the subscribing application.", "false_positives": [ - "Subscription deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Subscription deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Subscription deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Subscription deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json index eb6945e88e3fa..2b90f7601204f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a topic in Google Cloud Platform (GCP). In GCP, the publisher-subscriber relationship (Pub/Sub) is an asynchronous messaging service that decouples event-producing and event-processing services. A publisher application creates and sends messages to a topic. Deleting a topic can interrupt message flow in the Pub/Sub pipeline.", "false_positives": [ - "Topic deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Topic deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Topic deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Topic deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json index 7132fed195ccf..343fa6ad88956 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an Amazon GuardDuty detector. Upon deletion, GuardDuty stops monitoring the environment and all existing findings are lost.", "false_positives": [ - "The GuardDuty detector may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Detector deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "The GuardDuty detector may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Detector deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hide_encoded_executable_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hide_encoded_executable_registry.json index c40bbf236d668..709464c4cbb05 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hide_encoded_executable_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hide_encoded_executable_registry.json @@ -5,9 +5,7 @@ "description": "Identifies registry write modifications to hide an encoded portable executable. This could be indicative of adversary defense evasion by avoiding the storing of malicious content directly on disk.", "from": "now-9m", "index": [ - "logs-endpoint.events.*", - "winlogbeat-*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -47,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json index 525b45432b00c..33dac6fd4f37a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json @@ -4,7 +4,7 @@ ], "description": "Identifies when events are deleted in Azure Kubernetes. Kubernetes events are objects that log any state changes. Example events are a container creation, an image pull, or a pod scheduling on a node. An adversary may delete events in Azure Kubernetes in an attempt to evade detection.", "false_positives": [ - "Events deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Events deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Events deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Events deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_trusted_directory.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_trusted_directory.json index 7ac21a70100c0..54d251f3417a5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_trusted_directory.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_trusted_directory.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Identifies execution from a directory masquerading as the Windows Program Files directories. These paths are trusted and usually host trusted third party programs. An adversary may leverage masquerading, along with low privileges to bypass detections whitelisting those folders.", + "description": "Identifies execution from a directory masquerading as the Windows Program Files directories. These paths are trusted and usually host trusted third party programs. An adversary may leverage masquerading, along with low privileges to bypass detections allowlisting those folders.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json index f4c3e3476c0b6..f9f465ef3ee18 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange DLP Policy Removed", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-DlpPolicy\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-dlppolicy?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json index ab3399bddbe7a..0f2c612324234 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Malware Filter Policy Deletion", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-MalwareFilterPolicy\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-malwarefilterpolicy?view=exchange-ps" @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json index 06728dee5b150..7af0c1ea45d2a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Malware Filter Rule Modification", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-MalwareFilterRule\" or \"Disable-MalwareFilterRule\") and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-malwarefilterrule?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json index 50af384100139..38a7edda3a4e9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Safe Attachment Rule Disabled", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Disable-SafeAttachmentRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-safeattachmentrule?view=exchange-ps" @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_mailboxauditbypassassociation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_mailboxauditbypassassociation.json index 169ad751e6144..ae9512e52c705 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_mailboxauditbypassassociation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_mailboxauditbypassassociation.json @@ -4,7 +4,7 @@ ], "description": "Detects the occurrence of mailbox audit bypass associations. The mailbox audit is responsible for logging specified mailbox events (like accessing a folder or a message or permanently deleting a message). However, actions taken by some authorized accounts, such as accounts used by third-party tools or accounts used for lawful monitoring, can create a large number of mailbox audit log entries and may not be of interest to your organization. Because of this, administrators can create bypass associations, allowing certain accounts to perform their tasks without being logged. Attackers can abuse this allowlist mechanism to conceal actions taken, as the mailbox audit will log no activity done by the account.", "false_positives": [ - "Legitimate whitelisting of noisy accounts" + "Legitimate allowlisting of noisy accounts" ], "from": "now-30m", "index": [ @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "O365 Mailbox Audit Logging Bypass", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.action:Set-MailboxAuditBypassAssociation and event.outcome:success\n", "references": [ "https://twitter.com/misconfig/status/1476144066807140355" @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_defender_tampering.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_defender_tampering.json index f73b96015f885..9d37136d8db91 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_defender_tampering.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_defender_tampering.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Microsoft Windows Defender Tampering", - "query": "registry where event.type in (\"creation\", \"change\") and\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\PUAProtection\" and\n registry.data.strings : \"0\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender Security Center\\\\App and Browser protection\\\\DisallowExploitProtectionOverride\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\DisableAntiSpyware\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Features\\\\TamperProtection\" and\n registry.data.strings : \"0\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableRealtimeMonitoring\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableIntrusionPreventionSystem\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableScriptScanning\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Windows Defender Exploit Guard\\\\Controlled Folder Access\\\\EnableControlledFolderAccess\" and\n registry.data.strings : \"0\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableIOAVProtection\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Reporting\\\\DisableEnhancedNotifications\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\SpyNet\\\\DisableBlockAtFirstSeen\" and\n registry.data.strings : \"1\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\SpyNet\\\\SpynetReporting\" and\n registry.data.strings : \"0\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\SpyNet\\\\SubmitSamplesConsent\" and\n registry.data.strings : \"0\") or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableBehaviorMonitoring\" and\n registry.data.strings : \"1\")\n", + "query": "registry where event.type in (\"creation\", \"change\") and\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\PUAProtection\" and\n registry.data.strings : (\"0\", \"0x00000000\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender Security Center\\\\App and Browser protection\\\\DisallowExploitProtectionOverride\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\DisableAntiSpyware\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Features\\\\TamperProtection\" and\n registry.data.strings : (\"0\", \"0x00000000\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableRealtimeMonitoring\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableIntrusionPreventionSystem\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableScriptScanning\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Windows Defender Exploit Guard\\\\Controlled Folder Access\\\\EnableControlledFolderAccess\" and\n registry.data.strings : (\"0\", \"0x00000000\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableIOAVProtection\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Reporting\\\\DisableEnhancedNotifications\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\SpyNet\\\\DisableBlockAtFirstSeen\" and\n registry.data.strings : (\"1\", \"0x00000001\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\SpyNet\\\\SpynetReporting\" and\n registry.data.strings : (\"0\", \"0x00000000\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\SpyNet\\\\SubmitSamplesConsent\" and\n registry.data.strings : (\"0\", \"0x00000000\")) or\n (registry.path : \"HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows Defender\\\\Real-Time Protection\\\\DisableBehaviorMonitoring\" and\n registry.data.strings : (\"1\", \"0x00000001\"))\n", "references": [ "https://thedfirreport.com/2021/10/18/icedid-to-xinglocker-ransomware-in-24-hours/", "https://www.tenforums.com/tutorials/32236-enable-disable-microsoft-defender-pua-protection-windows-10-a.html", @@ -55,5 +55,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ms_office_suspicious_regmod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ms_office_suspicious_regmod.json new file mode 100644 index 0000000000000..bbd6d1840fc0e --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ms_office_suspicious_regmod.json @@ -0,0 +1,67 @@ +{ + "author": [ + "Elastic" + ], + "description": "Microsoft Office Products offers options for users and developers to control the security settings for running and using Macros. Adversaries may abuse these security settings to modify the default behavior of the Office Application to trust future macros and/or disable security warnings, which could increase their chances of establishing persistence.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "MS Office Macro Security Registry Modifications", + "query": "registry where event.type == \"change\" and\n registry.path : (\n \"HKU\\\\S-1-5-21-*\\\\SOFTWARE\\\\Microsoft\\\\Office\\\\*\\\\Security\\\\AccessVBOM\",\n \"HKU\\\\S-1-5-21-*\\\\SOFTWARE\\\\Microsoft\\\\Office\\\\*\\\\Security\\\\VbaWarnings\"\n ) and \n registry.data.strings == \"0x00000001\" and\n process.name : (\"cscript.exe\", \"wscript.exe\", \"mshta.exe\", \"mshta.exe\", \"winword.exe\", \"excel.exe\")\n", + "risk_score": 47, + "rule_id": "feeed87c-5e95-4339-aef1-47fd79bcfbe3", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1112", + "name": "Modify Registry", + "reference": "https://attack.mitre.org/techniques/T1112/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1204", + "name": "User Execution", + "reference": "https://attack.mitre.org/techniques/T1204/", + "subtechnique": [ + { + "id": "T1204.002", + "name": "Malicious File", + "reference": "https://attack.mitre.org/techniques/T1204/002/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json index 030e72dd4a411..135f70740692c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a Network Watcher in Azure. Network Watchers are used to monitor, diagnose, view metrics, and enable or disable logs for resources in an Azure virtual network. An adversary may delete a Network Watcher in an attempt to evade defenses.", "false_positives": [ - "Network Watcher deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Network Watcher deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Network Watcher deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Network Watcher deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_assembly_load.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_assembly_load.json index 1050efef9df21..a13aea7c4ee8c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_assembly_load.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_assembly_load.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "This rule detects the use of Reflection.Assembly to load PEs and DLLs in memory in Powershell Scripts. Attackers use this method to load executables and DLLs without writing to the disk, bypassing security solutions.", + "description": "Detects the use of Reflection.Assembly to load PEs and DLLs in memory in PowerShell scripts. Attackers use this method to load executables and DLLs without writing to the disk, bypassing security solutions.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -78,5 +78,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_compressed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_compressed.json index 03de37966bbd4..81b17f8aa1039 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_compressed.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_compressed.json @@ -2,9 +2,9 @@ "author": [ "Elastic" ], - "description": "Identifies the use of .Net functionality for decompression and base64 decoding combined in PowerShell scripts, which Malware and security tools heavily use to deobfuscate payloads and load them directly in memory to bypass defenses.", + "description": "Identifies the use of .NET functionality for decompression and base64 decoding combined in PowerShell scripts, which malware and security tools heavily use to deobfuscate payloads and load them directly in memory to bypass defenses.", "false_positives": [ - "Legitimate PowerShell Scripts which makes use of compression and encoding" + "Legitimate PowerShell Scripts which makes use of compression and encoding." ], "from": "now-9m", "index": [ @@ -71,5 +71,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_process_injection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_process_injection.json index 873969efa49c0..86f1d853330bb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_process_injection.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_posh_process_injection.json @@ -4,7 +4,7 @@ ], "description": "Detects the use of Windows API functions that are commonly abused by malware and security tools to load malicious code or inject it into remote processes.", "false_positives": [ - "Legitimate Powershell Scripts that make use of these Functions" + "Legitimate PowerShell scripts that make use of these functions." ], "from": "now-9m", "index": [ @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Process Injection via PowerShell", - "note": "## Triage and analysis.\n\n### Investigating Potential Process Injection via PowerShell\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nPowerShell also has solid capabilities to make the interaction with the Win32 API in an uncomplicated and reliable way,\nlike the execution of inline C# code, PSReflect, Get-ProcAddress, etc.\n\nRed Team tooling and Malware Developers take advantage of these capabilities to develop stagers and loaders that inject\npayloads directly into the memory, without touching the disk.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree)\n- Inspect any file or network events from the suspicious powershell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis.\n\n### Investigating Potential Process Injection via PowerShell\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nPowerShell also has solid capabilities to make the interaction with the Win32 API in an uncomplicated and reliable way,\nlike the execution of inline C# code, PSReflect, Get-ProcAddress, etc.\n\nRed Team tooling and malware developers take advantage of these capabilities to develop stagers and loaders that inject\npayloads directly into the memory, without touching the disk.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious PowerShell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and \n powershell.file.script_block_text : (\n (VirtualAlloc or VirtualAllocEx or VirtualProtect or LdrLoadDll or LoadLibrary or LoadLibraryA or\n LoadLibraryEx or GetProcAddress or OpenProcess or OpenProcessToken or AdjustTokenPrivileges) and\n (WriteProcessMemory or CreateRemoteThread or NtCreateThreadEx or CreateThread or QueueUserAPC or\n SuspendThread or ResumeThread)\n )\n", "references": [ "https://github.com/EmpireProject/Empire/blob/master/data/module_source/management/Invoke-PSInject.ps1", @@ -62,5 +62,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_powershell_windows_firewall_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_powershell_windows_firewall_disabled.json index 8c6ae92ef0a2d..d4e49ec00b648 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_powershell_windows_firewall_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_powershell_windows_firewall_disabled.json @@ -4,7 +4,7 @@ ], "description": "Identifies when the Windows Firewall is disabled using PowerShell cmdlets, which attackers do to evade network constraints, like internet and network lateral communication restrictions.", "false_positives": [ - "Windows Firewall can be disabled may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Windows Profile being disabled from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Windows Firewall can be disabled by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Windows Profile being disabled by unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-9m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json index d673b7ef324f6..febf708cc12d5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of various Amazon Simple Storage Service (S3) bucket configuration components.", "false_positives": [ - "Bucket components may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Bucket component deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Bucket components may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Bucket component deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -54,5 +54,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_scheduledjobs_at_protocol_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_scheduledjobs_at_protocol_enabled.json index 3e1925fce6254..e5d4e23d55bec 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_scheduledjobs_at_protocol_enabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_scheduledjobs_at_protocol_enabled.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Scheduled Tasks AT Command Enabled", - "query": "registry where \n registry.path : \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\Configuration\\\\EnableAt\" and registry.data.strings == \"1\"\n", + "query": "registry where \n registry.path : \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\Configuration\\\\EnableAt\" and \n registry.data.strings : (\"1\", \"0x00000001\")\n", "references": [ "https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-scheduledjob" ], @@ -52,5 +52,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sip_provider_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sip_provider_mod.json index 7e0622cd025dd..9092870cdffa1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sip_provider_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sip_provider_mod.json @@ -5,9 +5,7 @@ "description": "Identifies modifications to the registered Subject Interface Package (SIP) providers. SIP providers are used by the Windows cryptographic system to validate file signatures on the system. This may be an attempt to bypass signature validation checks or inject code into critical processes.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -52,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_solarwinds_backdoor_service_disabled_via_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_solarwinds_backdoor_service_disabled_via_registry.json index 5de655977130f..743ebc561dd1c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_solarwinds_backdoor_service_disabled_via_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_solarwinds_backdoor_service_disabled_via_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "SolarWinds Process Disabling Services via Registry", - "query": "registry where registry.path : \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Services\\\\*\\\\Start\" and registry.data.strings == \"4\" and\n process.name : (\n \"SolarWinds.BusinessLayerHost*.exe\", \n \"ConfigurationWizard*.exe\", \n \"NetflowDatabaseMaintenance*.exe\", \n \"NetFlowService*.exe\", \n \"SolarWinds.Administration*.exe\", \n \"SolarWinds.Collector.Service*.exe\" , \n \"SolarwindsDiagnostics*.exe\")\n", + "query": "registry where registry.path : \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Services\\\\*\\\\Start\" and\n registry.data.strings : (\"4\", \"0x00000004\") and\n process.name : (\n \"SolarWinds.BusinessLayerHost*.exe\", \n \"ConfigurationWizard*.exe\", \n \"NetflowDatabaseMaintenance*.exe\", \n \"NetFlowService*.exe\", \n \"SolarWinds.Administration*.exe\", \n \"SolarWinds.Collector.Service*.exe\" , \n \"SolarwindsDiagnostics*.exe\")\n", "references": [ "https://www.fireeye.com/blog/threat-research/2020/12/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor.html" ], @@ -74,5 +74,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suppression_rule_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suppression_rule_created.json index cce222e233838..d939761852ca8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suppression_rule_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suppression_rule_created.json @@ -2,7 +2,7 @@ "author": [ "Austin Songer" ], - "description": "Identifies the creation of suppression rules in Azure. Suppression rules are a mechanism used to suppress alerts previously identified as False Positives or too noisy to be in Production. This mechanism can be abused or mistakenly configured, resulting in defense evasions and loss of security visibility.", + "description": "Identifies the creation of suppression rules in Azure. Suppression rules are a mechanism used to suppress alerts previously identified as false positives or too noisy to be in production. This mechanism can be abused or mistakenly configured, resulting in defense evasions and loss of security visibility.", "false_positives": [ "Suppression Rules can be created legitimately by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Suppression Rules created by unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json index 9c1f82d12a441..8d02b5b8e52e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Identifies WMIC whitelisting bypass techniques by alerting on suspicious execution of scripts. When WMIC loads scripting libraries it may be indicative of a whitelist bypass.", + "description": "Identifies WMIC allowlist bypass techniques by alerting on suspicious execution of scripts. When WMIC loads scripting libraries it may be indicative of an allowlist bypass.", "from": "now-9m", "index": [ "winlogbeat-*", @@ -41,5 +41,5 @@ } ], "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json index 9a7c7c9f668cc..1b959097e30c9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a specified AWS Web Application Firewall (WAF) access control list.", "false_positives": [ - "Firewall ACL's may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Web ACL deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Firewall ACL's may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Web ACL deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json index 6f42caa63cf49..fb35a65bde354 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a specified AWS Web Application Firewall (WAF) rule or rule group.", "false_positives": [ - "WAF rules or rule groups may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Rule deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "WAF rules or rule groups may be deleted by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Rule deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_adfind_command_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_adfind_command_activity.json index 9af3832303666..9cf0541d1162e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_adfind_command_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_adfind_command_activity.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "AdFind Command Activity", - "note": "## Triage and analysis\n\n### Investigating AdFind Command Activity\n\n[AdFind](http://www.joeware.net/freetools/tools/adfind/) is a freely available command-line tool used to retrieve information from\nActivity Directory (AD). Network discovery and enumeration tools like `AdFind` are useful to adversaries in the same ways\nthey are effective for network administrators. This tool provides quick ability to scope AD person/computer objects and\nunderstand subnets and domain information. There are many [examples](https://thedfirreport.com/category/adfind/)\nobserved where this tool has been adopted by ransomware and criminal groups and used in compromises.\n\n#### Possible investigation steps:\n- `AdFind` is a legitimate Active Directory enumeration tool used by network administrators, it's important to understand\nthe source of the activity. This could involve identifying the account using `AdFind` and determining based on the command-lines\nwhat information was retrieved, then further determining if these actions are in scope of that user's traditional responsibilities.\n- In multiple public references, `AdFind` is leveraged after initial access is achieved, review previous activity on impacted\nmachine looking for suspicious indicators such as previous anti-virus/EDR alerts, phishing emails received, or network traffic\nto suspicious infrastructure\n\n### False Positive Analysis\n- This rule has the high chance to produce false positives as it is a legitimate tool used by network administrators. One\noption could be whitelisting specific users or groups who use the tool as part of their daily responsibilities. This can\nbe done by leveraging the exception workflow in the Kibana Security App or Elasticsearch API to tune this rule to your environment\n- Malicious behavior with `AdFind` should be investigated as part of a step within an attack chain. It doesn't happen in\nisolation, so reviewing previous logs/activity from impacted machines could be very telling.\n\n### Related Rules\n- Windows Network Enumeration\n- Enumeration of Administrator Accounts\n- Enumeration Command Spawned via WMIPrvSE\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior\n- It's important to understand that `AdFind` is an Active Directory enumeration tool and can be used for malicious or legitimate\npurposes, so understanding the intent behind the activity will help determine the appropropriate response.\n", + "note": "## Triage and analysis\n\n### Investigating AdFind Command Activity\n\n[AdFind](http://www.joeware.net/freetools/tools/adfind/) is a freely available command-line tool used to retrieve information from\nActive Directory (AD). Network discovery and enumeration tools like `AdFind` are useful to adversaries in the same ways\nthey are effective for network administrators. This tool provides quick ability to scope AD person/computer objects and\nunderstand subnets and domain information. There are many [examples](https://thedfirreport.com/category/adfind/)\nobserved where this tool has been adopted by ransomware and criminal groups and used in compromises.\n\n#### Possible investigation steps:\n- `AdFind` is a legitimate Active Directory enumeration tool used by network administrators, it's important to understand\nthe source of the activity. This could involve identifying the account using `AdFind` and determining based on the command-lines\nwhat information was retrieved, then further determining if these actions are in scope of that user's traditional responsibilities.\n- In multiple public references, `AdFind` is leveraged after initial access is achieved, review previous activity on impacted\nmachine looking for suspicious indicators such as previous anti-virus/EDR alerts, phishing emails received, or network traffic\nto suspicious infrastructure.\n\n### False Positive Analysis\n- This rule has the high chance to produce false positives as it is a legitimate tool used by network administrators. One\noption could be allowlisting specific users or groups who use the tool as part of their daily responsibilities. This can\nbe done by leveraging the exception workflow in the Kibana Security App or Elasticsearch API to tune this rule to your environment\n- Malicious behavior with `AdFind` should be investigated as part of a step within an attack chain. It doesn't happen in\nisolation, so reviewing previous logs/activity from impacted machines could be very telling.\n\n### Related Rules\n- Windows Network Enumeration\n- Enumeration of Administrator Accounts\n- Enumeration Command Spawned via WMIPrvSE\n\n### Response and Remediation\n- take immediate action to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior\n- It's important to understand that `AdFind` is an Active Directory enumeration tool and can be used for malicious or legitimate\npurposes, so understanding the intent behind the activity will help determine the appropropriate response.\n", "query": "process where event.type in (\"start\", \"process_started\") and \n (process.name : \"AdFind.exe\" or process.pe.original_file_name == \"AdFind.exe\") and \n process.args : (\"objectcategory=computer\", \"(objectcategory=computer)\", \n \"objectcategory=person\", \"(objectcategory=person)\",\n \"objectcategory=subnet\", \"(objectcategory=subnet)\",\n \"objectcategory=group\", \"(objectcategory=group)\", \n \"objectcategory=organizationalunit\", \"(objectcategory=organizationalunit)\",\n \"objectcategory=attributeschema\", \"(objectcategory=attributeschema)\",\n \"domainlist\", \"dcmodes\", \"adinfo\", \"dclist\", \"computers_pwnotreqd\", \"trustdmp\")\n", "references": [ "http://www.joeware.net/freetools/tools/adfind/", @@ -80,5 +80,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json index dc855f3ed9a57..0ea71e5314ed4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Net command via SYSTEM account", - "query": "process where event.type in (\"start\", \"process_started\") and \n user.id in (\"S-1-5-18\", \"S-1-5-19\", \"S-1-5-20\") and\n process.name : \"whoami.exe\" or\n (process.name : \"net1.exe\" and not process.parent.name : \"net.exe\")\n", + "query": "process where event.type in (\"start\", \"process_started\") and \n (process.Ext.token.integrity_level_name : \"System\" or\n winlog.event_data.IntegrityLevel : \"System\") and\n process.name : \"whoami.exe\" or\n (process.name : \"net1.exe\" and not process.parent.name : \"net.exe\")\n", "risk_score": 21, "rule_id": "2856446a-34e6-435b-9fb5-f8f040bfa7ed", "severity": "low", @@ -42,5 +42,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json index 6a38ff75d6660..5f5d99e7f17f5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json @@ -4,7 +4,7 @@ ], "description": "This rule detects the use of discovery-related Windows API functions in PowerShell Scripts. Attackers can use these functions to perform various situational awareness related activities, like enumerating users, shares, sessions, domain trusts, groups, etc.", "false_positives": [ - "Legitimate Powershell Scripts that make use of these Functions" + "Legitimate PowerShell scripts that make use of these functions." ], "from": "now-9m", "index": [ @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "PowerShell Suspicious Discovery Related Windows API Functions", - "note": "## Triage and analysis.\n\n### Investigating PowerShell Suspicious Discovery Related Windows API Functions\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can use PowerShell to interact with the Win32 API to bypass file based AntiVirus detections, using libraries\nlike PSReflect or Get-ProcAddress Cmdlet.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious powershell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis.\n\n### Investigating PowerShell Suspicious Discovery Related Windows API Functions\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can use PowerShell to interact with the Win32 API to bypass file based antivirus detections, using libraries\nlike PSReflect or Get-ProcAddress Cmdlet.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious PowerShell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and \n powershell.file.script_block_text : (\n NetShareEnum or\n NetWkstaUserEnum or\n NetSessionEnum or\n NetLocalGroupEnum or\n NetLocalGroupGetMembers or\n DsGetSiteName or\n DsEnumerateDomainTrusts or\n WTSEnumerateSessionsEx or\n WTSQuerySessionInformation or\n LsaGetLogonSessionData or\n QueryServiceObjectSecurity\n )\n", "references": [ "https://github.com/BC-SECURITY/Empire/blob/9259e5106986847d2bb770c4289c0c0f1adf2344/data/module_source/situational_awareness/network/powerview.ps1#L21413", @@ -88,5 +88,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_external_ip_lookup.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_external_ip_lookup.json index 9beafd16f7956..1e687851af5f3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_external_ip_lookup.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_external_ip_lookup.json @@ -8,9 +8,7 @@ ], "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -49,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_privileged_localgroup_membership.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_privileged_localgroup_membership.json index 5594a5e583a1c..467d5ecc88977 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_privileged_localgroup_membership.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_privileged_localgroup_membership.json @@ -11,7 +11,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Enumeration of Privileged Local Groups Membership", - "note": "## Config\n\nThis will require Windows security event 4799 by enabling audit success for the windows Account Management category and\nthe Security Group Management subcategory.\n", + "note": "## Config\n\nThis will require Windows security event 4799 by enabling audit success for the Windows Account Management category and\nthe Security Group Management subcategory.\n", "query": "iam where event.action == \"user-member-enumerated\" and\n\n /* noisy and usual legit processes excluded */\n not winlog.event_data.CallerProcessName:\n (\"?:\\\\Windows\\\\System32\\\\VSSVC.exe\",\n \"?:\\\\Windows\\\\System32\\\\SearchIndexer.exe\",\n \"?:\\\\Windows\\\\System32\\\\CompatTelRunner.exe\",\n \"?:\\\\Windows\\\\System32\\\\oobe\\\\msoobe.exe\",\n \"?:\\\\Windows\\\\System32\\\\net1.exe\",\n \"?:\\\\Windows\\\\System32\\\\svchost.exe\",\n \"?:\\\\Windows\\\\System32\\\\Netplwiz.exe\",\n \"?:\\\\Windows\\\\System32\\\\msiexec.exe\",\n \"?:\\\\Windows\\\\System32\\\\CloudExperienceHostBroker.exe\",\n \"?:\\\\Windows\\\\System32\\\\wbem\\\\WmiPrvSE.exe\",\n \"?:\\\\Windows\\\\System32\\\\SrTasks.exe\",\n \"?:\\\\Windows\\\\System32\\\\lsass.exe\",\n \"?:\\\\Windows\\\\System32\\\\diskshadow.exe\",\n \"?:\\\\Windows\\\\System32\\\\dfsrs.exe\",\n \"?:\\\\Program Files\\\\*.exe\",\n \"?:\\\\Program Files (x86)\\\\*.exe\") and\n /* privileged local groups */\n (group.name:(\"admin*\",\"RemoteDesktopUsers\") or\n winlog.event_data.TargetSid:(\"S-1-5-32-544\",\"S-1-5-32-555\"))\n", "risk_score": 43, "rule_id": "291a0de9-937a-4189-94c0-3e847c8b13e4", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json index f4e07c6fa15b5..38dfa02f40560 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Suspicious Portable Executable Encoded in Powershell Script", - "note": "## Triage and analysis.\n\n### Investigating Suspicious Portable Executable Encoded in Powershell Script\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can abuse PowerShell In-Memory capabilities to inject executables into memory without touching the disk, bypassing\nAntiVirus software. These executables are generally base64 encoded.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious powershell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell Reflection Assembly Load - e26f042e-c590-4e82-8e05-41e81bd822ad\n- PowerShell Suspicious Payload Encoded and Compressed - 81fe9dc6-a2d7-4192-a2d8-eed98afc766a\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis.\n\n### Investigating Suspicious Portable Executable Encoded in Powershell Script\n\nPowerShell is one of the main tools used by system administrators for automation, report routines, and other tasks.\n\nAttackers can abuse PowerShell in-memory capabilities to inject executables into memory without touching the disk,\nbypassing antivirus software. These executables are generally base64 encoded.\n\n#### Possible investigation steps:\n\n- Examine script content that triggered the detection. \n- Investigate script execution chain (parent process tree).\n- Inspect any file or network events from the suspicious PowerShell host process instance.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n\n- PowerShell Reflection Assembly Load - e26f042e-c590-4e82-8e05-41e81bd822ad\n- PowerShell Suspicious Payload Encoded and Compressed - 81fe9dc6-a2d7-4192-a2d8-eed98afc766a\n- PowerShell PSReflect Script - 56f2e9b5-4803-4e44-a0a4-a52dc79d57fe\n\n### Response and Remediation\n\n- Immediate response should be taken to validate, investigate, and potentially contain the activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'PowerShell Script Block Logging' logging policy must be enabled.\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\n\nSteps to implement the logging policy via registry:\n\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and \n powershell.file.script_block_text : (\n TVqQAAMAAAAEAAAA\n )\n", "references": [ "https://github.com/atc-project/atc-data/blob/master/docs/Logging_Policies/LP_0109_windows_powershell_script_block_log.md" @@ -52,5 +52,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_psreflect.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_psreflect.json index 4cdb6edcde1b6..6ff1d2b8fff9d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_psreflect.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_psreflect.json @@ -4,7 +4,7 @@ ], "description": "Detects the use of PSReflect in PowerShell scripts. Attackers leverage PSReflect as a library that enables PowerShell to access win32 API functions.", "false_positives": [ - "Legitimate Powershell Scripts that make use of PSReflect to access the win32 API" + "Legitimate PowerShell scripts that make use of PSReflect to access the win32 API" ], "from": "now-9m", "index": [ @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "PowerShell PSReflect Script", - "note": "## Triage and analysis\n### Investigating PowerShell PSReflect Script\n\nPowerShell is one of the main tools in the belt of system administrators for automation, report routines, and other tasks.\n\nPSReflect is a library that enables PowerShell to access win32 API functions in an uncomplicated way. It also helps to\ncreate enums and structs easily\u2014all without touching the disk.\n\nAlthough this is an interesting project for every developer and admin out there, it is mainly used in the red team and\nmalware tooling for its capabilities.\n\nDetecting the core implementation of PSReflect means detecting most of the tooling that uses windows API through\nPowerShell, enabling the defender to discover tools being dropped in the environment.\n\n#### Possible investigation steps:\n- Check for additional PowerShell logs that indicate that the script/command was run.\n- Gather the script content that may be split into multiple script blocks, and identify its capabilities.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n- Look for additional alerts involving the host and the user.\n\n### False Positive Analysis\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n- PowerShell Suspicious Discovery Related Windows API Functions - 61ac3638-40a3-44b2-855a-985636ca985e\n- PowerShell Keylogging Script - bd2c86a0-8b61-4457-ab38-96943984e889\n- PowerShell Suspicious Script with Audio Capture Capabilities - 2f2f4939-0b34-40c2-a0a3-844eb7889f43\n- Potential Process Injection via PowerShell - 2e29e96a-b67c-455a-afe4-de6183431d0d\n- PowerShell Reflection Assembly Load - e26f042e-c590-4e82-8e05-41e81bd822ad\n- PowerShell Suspicious Payload Encoded and Compressed - 81fe9dc6-a2d7-4192-a2d8-eed98afc766a\n- PowerShell Suspicious Script with Screenshot Capabilities - 959a7353-1129-4aa7-9084-30746b256a70\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\nThe 'PowerShell Script Block Logging' logging policy is required be configured (Enable).\n\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\nSteps to implement the logging policy via registry:\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", + "note": "## Triage and analysis\n### Investigating PowerShell PSReflect Script\n\nPowerShell is one of the main tools in the belt of system administrators for automation, report routines, and other tasks.\n\nPSReflect is a library that enables PowerShell to access win32 API functions in an uncomplicated way. It also helps to\ncreate enums and structs easily\u2014all without touching the disk.\n\nAlthough this is an interesting project for every developer and admin out there, it is mainly used in the red team and\nmalware tooling for its capabilities.\n\nDetecting the core implementation of PSReflect means detecting most of the tooling that uses Windows API through\nPowerShell, enabling the defender to discover tools being dropped in the environment.\n\n#### Possible investigation steps:\n- Check for additional PowerShell logs that indicate that the script/command was run.\n- Gather the script content that may be split into multiple script blocks, and identify its capabilities.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n- Look for additional alerts involving the host and the user.\n\n### False Positive Analysis\n- Verify whether the script content is malicious/harmful.\n\n### Related Rules\n- PowerShell Suspicious Discovery Related Windows API Functions - 61ac3638-40a3-44b2-855a-985636ca985e\n- PowerShell Keylogging Script - bd2c86a0-8b61-4457-ab38-96943984e889\n- PowerShell Suspicious Script with Audio Capture Capabilities - 2f2f4939-0b34-40c2-a0a3-844eb7889f43\n- Potential Process Injection via PowerShell - 2e29e96a-b67c-455a-afe4-de6183431d0d\n- PowerShell Reflection Assembly Load - e26f042e-c590-4e82-8e05-41e81bd822ad\n- PowerShell Suspicious Payload Encoded and Compressed - 81fe9dc6-a2d7-4192-a2d8-eed98afc766a\n- PowerShell Suspicious Script with Screenshot Capabilities - 959a7353-1129-4aa7-9084-30746b256a70\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate, and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\nThe 'PowerShell Script Block Logging' logging policy is required be configured (Enable).\n\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nAdministrative Templates > \nWindows PowerShell > \nTurn on PowerShell Script Block Logging (Enable)\n```\nSteps to implement the logging policy via registry:\n```\nreg add \"hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging\" /v EnableScriptBlockLogging /t REG_DWORD /d 1\n```\n", "query": "event.category:process and \n powershell.file.script_block_text:(\n New-InMemoryModule or\n Add-Win32Type or\n psenum or\n DefineDynamicAssembly or\n DefineDynamicModule or\n Reflection.TypeAttributes or\n Reflection.Emit.OpCodes or\n Reflection.Emit.CustomAttributeBuilder or\n Runtime.InteropServices.DllImportAttribute\n )\n", "references": [ "https://github.com/mattifestation/PSReflect/blob/master/PSReflect.psm1", @@ -61,5 +61,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json index 2ccc730c3fa01..34ec31d697fa4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via Registration Utility", - "query": "sequence by process.entity_id\n [process where event.type == \"start\" and\n process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not (\n user.id == \"S-1-5-18\" and\n (process.parent.name : \"msiexec.exe\" or process.parent.executable : (\"C:\\\\Program Files (x86)\\\\*.exe\", \"C:\\\\Program Files\\\\*.exe\"))\n )\n ]\n [network where process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\",\n \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\",\n \"100.64.0.0/10\", \"192.175.48.0/24\",\"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\") and network.protocol != \"dns\"]\n", + "query": "sequence by process.entity_id\n [process where event.type == \"start\" and\n process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not (\n (process.Ext.token.integrity_level_name : \"System\" or winlog.event_data.IntegrityLevel : \"System\") and\n (process.parent.name : \"msiexec.exe\" or process.parent.executable : (\"C:\\\\Program Files (x86)\\\\*.exe\", \"C:\\\\Program Files\\\\*.exe\"))\n )\n ]\n [network where process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\",\n \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\",\n \"100.64.0.0/10\", \"192.175.48.0/24\",\"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\") and network.protocol != \"dns\"]\n", "references": [ "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" ], @@ -63,5 +63,5 @@ } ], "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_java_netcon_childproc.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_java_netcon_childproc.json new file mode 100644 index 0000000000000..fe04cfe35b363 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_java_netcon_childproc.json @@ -0,0 +1,63 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies an outbound network connection by JAVA to LDAP, RMI or DNS standard ports followed by a suspicious JAVA child processes. This may indicate an attempt to exploit a JAVA/NDI (Java Naming and Directory Interface) injection vulnerability.", + "from": "now-9m", + "index": [ + "auditbeat-*", + "logs-endpoint.events.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Potential JAVA/JNDI Exploitation Attempt", + "query": "sequence by host.id with maxspan=1m\n [network where event.action == \"connection_attempted\" and\n process.name : \"java\" and\n /*\n outbound connection attempt to\n LDAP, RMI or DNS standard ports\n by JAVA process\n */\n destination.port in (1389, 389, 1099, 53, 5353)] by process.pid\n [process where event.type == \"start\" and\n\n /* Suspicious JAVA child process */\n process.parent.name : \"java\" and\n process.name : (\"sh\",\n \"bash\",\n \"dash\",\n \"ksh\",\n \"tcsh\",\n \"zsh\",\n \"curl\",\n \"perl*\",\n \"python*\",\n \"ruby*\",\n \"php*\",\n \"wget\")] by process.parent.pid\n", + "references": [ + "https://www.lunasec.io/docs/blog/log4j-zero-day/", + "https://github.com/christophetd/log4shell-vulnerable-app", + "https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf" + ], + "risk_score": 73, + "rule_id": "c3f5e1d8-910e-43b4-8d44-d748e498ca86", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Linux", + "macOS", + "Threat Detection", + "Execution" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.007", + "name": "JavaScript", + "reference": "https://attack.mitre.org/techniques/T1059/007/" + } + ] + }, + { + "id": "T1203", + "name": "Exploitation for Client Execution", + "reference": "https://attack.mitre.org/techniques/T1203/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json index a6a9e24ccb63a..25ae6170a7ca5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Transport Rule Creation", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-TransportRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/new-transportrule?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json index 836ade6c0b80f..b0e311200ce2e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Transport Rule Modification", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-TransportRule\" or \"Disable-TransportRule\") and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-transportrule?view=exchange-ps", @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json index c396c9a2cce17..36f53d2b60072 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json @@ -4,7 +4,7 @@ ], "description": "Identifies when an attempt was made to restore an RDS Snapshot. Snapshots are sometimes shared by threat actors in order to exfiltrate bulk data. If the permissions were modified, verify if the snapshot was shared with an unauthorized or unexpected AWS account.", "false_positives": [ - "Restoring snapshots may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Snapshot restoration from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Restoring snapshots may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Snapshot restoration by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -43,5 +43,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json index 034a6ebfc02f3..61903a15c0993 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json @@ -4,7 +4,7 @@ ], "description": "Identifies when a user has disabled or deleted an EventBridge rule. This activity can result in an unintended loss of visibility in applications or a break in the flow with other AWS services.", "false_positives": [ - "EventBridge Rules could be deleted or disabled by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. EventBridge Rules being deleted or disabled from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "EventBridge Rules could be deleted or disabled by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. EventBridge Rules being deleted or disabled by unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-20m", "index": [ @@ -44,5 +44,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json index f92d6ec44d655..9ad5f631ad307 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a specified AWS CloudWatch log group. When a log group is deleted, all the archived log events associated with the log group are also permanently deleted.", "false_positives": [ - "Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Log group deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Log group deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -73,5 +73,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json index 46ac2d19889f2..930dc822eea03 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an AWS CloudWatch log stream, which permanently deletes all associated archived log events with the stream.", "false_positives": [ - "A log stream may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Log stream deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A log stream may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Log stream deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -73,5 +73,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json index 52fadfdf8ee19..9465922d7c34f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json @@ -4,7 +4,7 @@ ], "description": "Detects when a EFS File System or Mount is deleted. An adversary could break any file system using the mount target that is being deleted, which might disrupt instances or applications using those mounts. The mount must be deleted prior to deleting the File System, or the adversary will be unable to delete the File System.", "false_positives": [ - "File System or Mount being deleted may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. File System Mount deleted from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "File System or Mount being deleted may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. File System Mount deletion by unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json index 76901da74ce96..f67419f5746ce 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies an Identity and Access Management (IAM) role deletion in Google Cloud Platform (GCP). A role contains a set of permissions that allows you to perform specific actions on Google Cloud resources. An adversary may delete an IAM role to inhibit access to accounts utilized by legitimate users.", "false_positives": [ - "Role deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Role deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Role deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Role deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json index c3aa1523e4d1e..9d28009acb13b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json @@ -4,7 +4,7 @@ ], "description": "Identifies when a Google Cloud Platform (GCP) storage bucket is deleted. An adversary may delete a storage bucket in order to disrupt their target's business operations.", "false_positives": [ - "Storage buckets may be deleted by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Bucket deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Storage buckets may be deleted by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Bucket deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json index ecf52f8e8830c..143d7138d8bad 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "Identifies when a Virtual Private Cloud a virtual private cloud (VPC) route is created in Google Cloud Platform (GCP). Google Cloud routes define the paths that network traffic takes from a virtual machine (VM) instance to other destinations. These destinations can be inside a Google VPC network or outside it. An adversary may create a route in order to impact the flow of network traffic in their target's cloud environment.", + "description": "Identifies when a virtual private cloud (VPC) route is created in Google Cloud Platform (GCP). Google Cloud routes define the paths that network traffic takes from a virtual machine (VM) instance to other destinations. These destinations can be inside a Google VPC network or outside it. An adversary may create a route in order to impact the flow of network traffic in their target's cloud environment.", "false_positives": [ "Virtual Private Cloud routes may be created by system administrators. Verify that the configuration change was expected. Exceptions can be added to this rule to filter expected behavior." ], @@ -32,5 +32,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json index e1f5fcbf4836e..9aea3879d2545 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of a specified AWS Identity and Access Management (IAM) resource group. Deleting a resource group does not delete resources that are members of the group; it only deletes the group structure.", "false_positives": [ - "A resource group may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Resource group deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A resource group may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Resource group deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json index 0612c3868b9aa..456eff557ccf1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of Azure Kubernetes Pods. Adversaries may delete a Kubernetes pod to disrupt the normal behavior of the environment.", "false_positives": [ - "Pods may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Pods deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Pods may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Pods deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -43,5 +43,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_potential_ransomware_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_potential_ransomware_activity.json index 46e760bb32243..14a2f6ddeb095 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_potential_ransomware_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_potential_ransomware_activity.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Potential ransomware activity", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n", "query": "event.dataset:o365.audit and event.provider:SecurityComplianceCenter and event.category:web and event.action:\"Potential ransomware activity\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/cloud-app-security/anomaly-detection-policy", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_unusual_volume_of_file_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_unusual_volume_of_file_deletion.json index c3a53310781df..1534e4ba9f75c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_unusual_volume_of_file_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_microsoft_365_unusual_volume_of_file_deletion.json @@ -2,7 +2,7 @@ "author": [ "Austin Songer" ], - "description": "Identifies that a user has deleted an unusually large volume of files as reported by Microsoft Cloud App Security.", + "description": "Identifies that a user has deleted an unusually large volume of files as reported by Microsoft Cloud App Security.", "false_positives": [ "Users or System Administrator cleaning out folders." ], @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Unusual Volume of File Deletion", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n", "query": "event.dataset:o365.audit and event.provider:SecurityComplianceCenter and event.category:web and event.action:\"Unusual volume of file deletion\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/cloud-app-security/anomaly-detection-policy", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json index 08ae6ce11bbb5..c114c26556033 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an Amazon Relational Database Service (RDS) Aurora database cluster or global database cluster.", "false_positives": [ - "Clusters may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Cluster deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Clusters may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Cluster deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_group_deletion.json index c60b467fa238b..5f13c9ca2ecb8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_group_deletion.json @@ -5,7 +5,7 @@ ], "description": "Identifies the deletion of an Amazon Relational Database Service (RDS) Security group.", "false_positives": [ - "An RDS security group deletion may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "An RDS security group deletion may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json index a378a3d607abb..bf988e5dd1e0c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json @@ -2,9 +2,9 @@ "author": [ "Austin Songer" ], - "description": "Identifies when a virtual network device is being modified or deleted. This can be a network virtual appliance, virtual hub, or virtual router.", + "description": "Identifies when a virtual network device is modified or deleted. This can be a network virtual appliance, virtual hub, or virtual router.", "false_positives": [ - "Virtual Network Device being modified or deleted may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Virtual Network Device modified or deleted from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Virtual Network Device modification or deletion may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Virtual Network Device modification or deletion by unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Virtual Network Device Modified or Deleted", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:(\"MICROSOFT.NETWORK/NETWORKINTERFACES/TAPCONFIGURATIONS/WRITE\" or\n\"MICROSOFT.NETWORK/NETWORKINTERFACES/TAPCONFIGURATIONS/DELETE\" or \"MICROSOFT.NETWORK/NETWORKINTERFACES/WRITE\" or\n\"MICROSOFT.NETWORK/NETWORKINTERFACES/JOIN/ACTION\" or \"MICROSOFT.NETWORK/NETWORKINTERFACES/DELETE\"or\n\"MICROSOFT.NETWORK/NETWORKVIRTUALAPPLIANCES/DELETE\" or \"MICROSOFT.NETWORK/NETWORKVIRTUALAPPLIANCES/WRITE\" or\n\"MICROSOFT.NETWORK/VIRTUALHUBS/DELETE\" or \"MICROSOFT.NETWORK/VIRTUALHUBS/WRITE\" or\n\"MICROSOFT.NETWORK/VIRTUALROUTERS/WRITE\" or \"MICROSOFT.NETWORK/VIRTUALROUTERS/DELETE\") and \nevent.outcome:(Success or success)\n", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:(\"MICROSOFT.NETWORK/NETWORKINTERFACES/TAPCONFIGURATIONS/WRITE\" or\n\"MICROSOFT.NETWORK/NETWORKINTERFACES/TAPCONFIGURATIONS/DELETE\" or \"MICROSOFT.NETWORK/NETWORKINTERFACES/WRITE\" or\n\"MICROSOFT.NETWORK/NETWORKINTERFACES/JOIN/ACTION\" or \"MICROSOFT.NETWORK/NETWORKINTERFACES/DELETE\" or\n\"MICROSOFT.NETWORK/NETWORKVIRTUALAPPLIANCES/DELETE\" or \"MICROSOFT.NETWORK/NETWORKVIRTUALAPPLIANCES/WRITE\" or\n\"MICROSOFT.NETWORK/VIRTUALHUBS/DELETE\" or \"MICROSOFT.NETWORK/VIRTUALHUBS/WRITE\" or\n\"MICROSOFT.NETWORK/VIRTUALROUTERS/WRITE\" or \"MICROSOFT.NETWORK/VIRTUALROUTERS/DELETE\") and \nevent.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations" ], @@ -43,5 +43,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_or_resized_via_vssadmin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_or_resized_via_vssadmin.json index 940229bf63751..fb7121abee4c7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_or_resized_via_vssadmin.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_or_resized_via_vssadmin.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Volume Shadow Copy Deleted or Resized via VssAdmin", - "query": "process where event.type in (\"start\", \"process_started\") and event.action == \"start\" \n and (process.name : \"vssadmin.exe\" or process.pe.original_file_name == \"VSSADMIN.EXE\") and\n process.args in (\"delete\", \"resize\") and process.args : \"shadows*\"\n", + "query": "process where event.type in (\"start\", \"process_started\")\n and (process.name : \"vssadmin.exe\" or process.pe.original_file_name == \"VSSADMIN.EXE\") and\n process.args in (\"delete\", \"resize\") and process.args : \"shadows*\"\n", "risk_score": 73, "rule_id": "b5ea4bfe-a1b2-421f-9d47-22a75a6f2921", "severity": "high", @@ -42,5 +42,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 10 + "version": 11 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts index eba920055a4f2..db98e7af01c3e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts @@ -522,129 +522,148 @@ import rule509 from './persistence_periodic_tasks_file_mdofiy.json'; import rule510 from './persistence_via_atom_init_file_modification.json'; import rule511 from './privilege_escalation_lsa_auth_package.json'; import rule512 from './privilege_escalation_port_monitor_print_pocessor_abuse.json'; -import rule513 from './credential_access_dumping_hashes_bi_cmds.json'; -import rule514 from './lateral_movement_mounting_smb_share.json'; -import rule515 from './privilege_escalation_echo_nopasswd_sudoers.json'; -import rule516 from './privilege_escalation_ld_preload_shared_object_modif.json'; -import rule517 from './privilege_escalation_root_crontab_filemod.json'; -import rule518 from './defense_evasion_create_mod_root_certificate.json'; -import rule519 from './privilege_escalation_sudo_buffer_overflow.json'; -import rule520 from './execution_installer_spawned_network_event.json'; -import rule521 from './initial_access_suspicious_ms_exchange_files.json'; -import rule522 from './initial_access_suspicious_ms_exchange_process.json'; -import rule523 from './initial_access_suspicious_ms_exchange_worker_child_process.json'; -import rule524 from './persistence_evasion_registry_startup_shell_folder_modified.json'; -import rule525 from './persistence_local_scheduled_job_creation.json'; -import rule526 from './persistence_via_wmi_stdregprov_run_services.json'; -import rule527 from './credential_access_persistence_network_logon_provider_modification.json'; -import rule528 from './lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json'; -import rule529 from './collection_microsoft_365_new_inbox_rule.json'; -import rule530 from './ml_high_count_network_denies.json'; -import rule531 from './ml_high_count_network_events.json'; -import rule532 from './ml_rare_destination_country.json'; -import rule533 from './ml_spike_in_traffic_to_a_country.json'; -import rule534 from './command_and_control_tunneling_via_earthworm.json'; -import rule535 from './lateral_movement_evasion_rdp_shadowing.json'; -import rule536 from './threat_intel_fleet_integrations.json'; -import rule537 from './exfiltration_ec2_vm_export_failure.json'; -import rule538 from './exfiltration_ec2_full_network_packet_capture_detected.json'; -import rule539 from './impact_azure_service_principal_credentials_added.json'; -import rule540 from './persistence_ec2_security_group_configuration_change_detection.json'; -import rule541 from './defense_evasion_disabling_windows_logs.json'; -import rule542 from './persistence_route_53_domain_transfer_lock_disabled.json'; -import rule543 from './persistence_route_53_domain_transferred_to_another_account.json'; -import rule544 from './initial_access_okta_user_attempted_unauthorized_access.json'; -import rule545 from './credential_access_user_excessive_sso_logon_errors.json'; -import rule546 from './persistence_exchange_suspicious_mailbox_right_delegation.json'; -import rule547 from './privilege_escalation_new_or_modified_federation_domain.json'; -import rule548 from './privilege_escalation_sts_assumerole_usage.json'; -import rule549 from './privilege_escalation_sts_getsessiontoken_abuse.json'; -import rule550 from './defense_evasion_suspicious_execution_from_mounted_device.json'; -import rule551 from './defense_evasion_unusual_network_connection_via_dllhost.json'; -import rule552 from './defense_evasion_amsienable_key_mod.json'; -import rule553 from './impact_rds_group_deletion.json'; -import rule554 from './persistence_rds_group_creation.json'; -import rule555 from './persistence_route_table_created.json'; -import rule556 from './persistence_route_table_modified_or_deleted.json'; -import rule557 from './exfiltration_rds_snapshot_export.json'; -import rule558 from './persistence_rds_instance_creation.json'; -import rule559 from './privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json'; -import rule560 from './ml_auth_rare_hour_for_a_user_to_logon.json'; -import rule561 from './ml_auth_rare_source_ip_for_a_user.json'; -import rule562 from './ml_auth_rare_user_logon.json'; -import rule563 from './ml_auth_spike_in_failed_logon_events.json'; -import rule564 from './ml_auth_spike_in_logon_events.json'; -import rule565 from './ml_auth_spike_in_logon_events_from_a_source_ip.json'; -import rule566 from './privilege_escalation_cyberarkpas_error_audit_event_promotion.json'; -import rule567 from './privilege_escalation_cyberarkpas_recommended_events_to_monitor_promotion.json'; -import rule568 from './defense_evasion_kubernetes_events_deleted.json'; -import rule569 from './impact_kubernetes_pod_deleted.json'; -import rule570 from './exfiltration_rds_snapshot_restored.json'; -import rule571 from './privilege_escalation_printspooler_malicious_driver_file_changes.json'; -import rule572 from './privilege_escalation_printspooler_malicious_registry_modification.json'; -import rule573 from './privilege_escalation_printspooler_suspicious_file_deletion.json'; -import rule574 from './privilege_escalation_unusual_printspooler_childprocess.json'; -import rule575 from './defense_evasion_disabling_windows_defender_powershell.json'; -import rule576 from './defense_evasion_enable_network_discovery_with_netsh.json'; -import rule577 from './defense_evasion_execution_windefend_unusual_path.json'; -import rule578 from './defense_evasion_agent_spoofing_mismatched_id.json'; -import rule579 from './defense_evasion_agent_spoofing_multiple_hosts.json'; -import rule580 from './defense_evasion_parent_process_pid_spoofing.json'; -import rule581 from './impact_microsoft_365_potential_ransomware_activity.json'; -import rule582 from './impact_microsoft_365_unusual_volume_of_file_deletion.json'; -import rule583 from './initial_access_microsoft_365_user_restricted_from_sending_email.json'; -import rule584 from './defense_evasion_elasticache_security_group_creation.json'; -import rule585 from './defense_evasion_elasticache_security_group_modified_or_deleted.json'; -import rule586 from './impact_volume_shadow_copy_deletion_via_powershell.json'; -import rule587 from './persistence_route_53_hosted_zone_associated_with_a_vpc.json'; -import rule588 from './defense_evasion_defender_exclusion_via_powershell.json'; -import rule589 from './defense_evasion_dns_over_https_enabled.json'; -import rule590 from './defense_evasion_whitespace_padding_in_command_line.json'; -import rule591 from './defense_evasion_frontdoor_firewall_policy_deletion.json'; -import rule592 from './credential_access_azure_full_network_packet_capture_detected.json'; -import rule593 from './persistence_webshell_detection.json'; -import rule594 from './defense_evasion_suppression_rule_created.json'; -import rule595 from './impact_efs_filesystem_or_mount_deleted.json'; -import rule596 from './defense_evasion_execution_control_panel_suspicious_args.json'; -import rule597 from './defense_evasion_azure_blob_permissions_modified.json'; -import rule598 from './privilege_escalation_aws_suspicious_saml_activity.json'; -import rule599 from './credential_access_potential_lsa_memdump_via_mirrordump.json'; -import rule600 from './discovery_virtual_machine_fingerprinting_grep.json'; -import rule601 from './impact_backup_file_deletion.json'; -import rule602 from './credential_access_posh_minidump.json'; -import rule603 from './persistence_screensaver_engine_unexpected_child_process.json'; -import rule604 from './persistence_screensaver_plist_file_modification.json'; -import rule605 from './credential_access_suspicious_lsass_access_memdump.json'; -import rule606 from './defense_evasion_suspicious_process_access_direct_syscall.json'; -import rule607 from './discovery_posh_suspicious_api_functions.json'; -import rule608 from './privilege_escalation_via_rogue_named_pipe.json'; -import rule609 from './credential_access_suspicious_lsass_access_via_snapshot.json'; -import rule610 from './defense_evasion_posh_process_injection.json'; -import rule611 from './collection_posh_keylogger.json'; -import rule612 from './defense_evasion_posh_assembly_load.json'; -import rule613 from './defense_evasion_powershell_windows_firewall_disabled.json'; -import rule614 from './execution_posh_portable_executable.json'; -import rule615 from './execution_posh_psreflect.json'; -import rule616 from './credential_access_suspicious_comsvcs_imageload.json'; -import rule617 from './impact_aws_eventbridge_rule_disabled_or_deleted.json'; -import rule618 from './defense_evasion_microsoft_defender_tampering.json'; -import rule619 from './initial_access_azure_active_directory_high_risk_signin_atrisk_or_confirmed.json'; -import rule620 from './persistence_remote_password_reset.json'; -import rule621 from './privilege_escalation_azure_kubernetes_rolebinding_created.json'; -import rule622 from './collection_posh_audio_capture.json'; -import rule623 from './collection_posh_screen_grabber.json'; -import rule624 from './defense_evasion_posh_compressed.json'; -import rule625 from './defense_evasion_suspicious_process_creation_calltrace.json'; -import rule626 from './privilege_escalation_group_policy_iniscript.json'; -import rule627 from './privilege_escalation_group_policy_privileged_groups.json'; -import rule628 from './privilege_escalation_group_policy_scheduled_task.json'; -import rule629 from './defense_evasion_clearing_windows_console_history.json'; -import rule630 from './threat_intel_filebeat8x.json'; -import rule631 from './privilege_escalation_installertakeover.json'; -import rule632 from './credential_access_via_snapshot_lsass_clone_creation.json'; -import rule633 from './persistence_via_bits_job_notify_command.json'; -import rule634 from './credential_access_symbolic_link_to_shadow_copy_createdcredential_access_symbolic_link_to_shadow_copy_created.json'; -import rule635 from './defense_evasion_microsoft_365_mailboxauditbypassassociation.json'; +import rule513 from './credential_access_posh_request_ticket.json'; +import rule514 from './credential_access_dumping_hashes_bi_cmds.json'; +import rule515 from './lateral_movement_mounting_smb_share.json'; +import rule516 from './privilege_escalation_echo_nopasswd_sudoers.json'; +import rule517 from './privilege_escalation_ld_preload_shared_object_modif.json'; +import rule518 from './privilege_escalation_root_crontab_filemod.json'; +import rule519 from './defense_evasion_create_mod_root_certificate.json'; +import rule520 from './privilege_escalation_sudo_buffer_overflow.json'; +import rule521 from './execution_installer_spawned_network_event.json'; +import rule522 from './initial_access_suspicious_ms_exchange_files.json'; +import rule523 from './initial_access_suspicious_ms_exchange_process.json'; +import rule524 from './initial_access_suspicious_ms_exchange_worker_child_process.json'; +import rule525 from './persistence_evasion_registry_startup_shell_folder_modified.json'; +import rule526 from './persistence_local_scheduled_job_creation.json'; +import rule527 from './persistence_via_wmi_stdregprov_run_services.json'; +import rule528 from './credential_access_persistence_network_logon_provider_modification.json'; +import rule529 from './lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json'; +import rule530 from './collection_microsoft_365_new_inbox_rule.json'; +import rule531 from './ml_high_count_network_denies.json'; +import rule532 from './ml_high_count_network_events.json'; +import rule533 from './ml_rare_destination_country.json'; +import rule534 from './ml_spike_in_traffic_to_a_country.json'; +import rule535 from './command_and_control_tunneling_via_earthworm.json'; +import rule536 from './lateral_movement_evasion_rdp_shadowing.json'; +import rule537 from './threat_intel_fleet_integrations.json'; +import rule538 from './exfiltration_ec2_vm_export_failure.json'; +import rule539 from './exfiltration_ec2_full_network_packet_capture_detected.json'; +import rule540 from './impact_azure_service_principal_credentials_added.json'; +import rule541 from './persistence_ec2_security_group_configuration_change_detection.json'; +import rule542 from './defense_evasion_disabling_windows_logs.json'; +import rule543 from './persistence_route_53_domain_transfer_lock_disabled.json'; +import rule544 from './persistence_route_53_domain_transferred_to_another_account.json'; +import rule545 from './initial_access_okta_user_attempted_unauthorized_access.json'; +import rule546 from './credential_access_user_excessive_sso_logon_errors.json'; +import rule547 from './persistence_exchange_suspicious_mailbox_right_delegation.json'; +import rule548 from './privilege_escalation_new_or_modified_federation_domain.json'; +import rule549 from './privilege_escalation_sts_assumerole_usage.json'; +import rule550 from './privilege_escalation_sts_getsessiontoken_abuse.json'; +import rule551 from './defense_evasion_suspicious_execution_from_mounted_device.json'; +import rule552 from './defense_evasion_unusual_network_connection_via_dllhost.json'; +import rule553 from './defense_evasion_amsienable_key_mod.json'; +import rule554 from './impact_rds_group_deletion.json'; +import rule555 from './persistence_rds_group_creation.json'; +import rule556 from './persistence_route_table_created.json'; +import rule557 from './persistence_route_table_modified_or_deleted.json'; +import rule558 from './exfiltration_rds_snapshot_export.json'; +import rule559 from './persistence_rds_instance_creation.json'; +import rule560 from './privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json'; +import rule561 from './ml_auth_rare_hour_for_a_user_to_logon.json'; +import rule562 from './ml_auth_rare_source_ip_for_a_user.json'; +import rule563 from './ml_auth_rare_user_logon.json'; +import rule564 from './ml_auth_spike_in_failed_logon_events.json'; +import rule565 from './ml_auth_spike_in_logon_events.json'; +import rule566 from './ml_auth_spike_in_logon_events_from_a_source_ip.json'; +import rule567 from './privilege_escalation_cyberarkpas_error_audit_event_promotion.json'; +import rule568 from './privilege_escalation_cyberarkpas_recommended_events_to_monitor_promotion.json'; +import rule569 from './defense_evasion_kubernetes_events_deleted.json'; +import rule570 from './impact_kubernetes_pod_deleted.json'; +import rule571 from './exfiltration_rds_snapshot_restored.json'; +import rule572 from './privilege_escalation_printspooler_malicious_driver_file_changes.json'; +import rule573 from './privilege_escalation_printspooler_malicious_registry_modification.json'; +import rule574 from './privilege_escalation_printspooler_suspicious_file_deletion.json'; +import rule575 from './privilege_escalation_unusual_printspooler_childprocess.json'; +import rule576 from './defense_evasion_disabling_windows_defender_powershell.json'; +import rule577 from './defense_evasion_enable_network_discovery_with_netsh.json'; +import rule578 from './defense_evasion_execution_windefend_unusual_path.json'; +import rule579 from './defense_evasion_agent_spoofing_mismatched_id.json'; +import rule580 from './defense_evasion_agent_spoofing_multiple_hosts.json'; +import rule581 from './defense_evasion_parent_process_pid_spoofing.json'; +import rule582 from './impact_microsoft_365_potential_ransomware_activity.json'; +import rule583 from './impact_microsoft_365_unusual_volume_of_file_deletion.json'; +import rule584 from './initial_access_microsoft_365_user_restricted_from_sending_email.json'; +import rule585 from './defense_evasion_elasticache_security_group_creation.json'; +import rule586 from './defense_evasion_elasticache_security_group_modified_or_deleted.json'; +import rule587 from './impact_volume_shadow_copy_deletion_via_powershell.json'; +import rule588 from './persistence_route_53_hosted_zone_associated_with_a_vpc.json'; +import rule589 from './defense_evasion_defender_exclusion_via_powershell.json'; +import rule590 from './defense_evasion_dns_over_https_enabled.json'; +import rule591 from './defense_evasion_whitespace_padding_in_command_line.json'; +import rule592 from './defense_evasion_frontdoor_firewall_policy_deletion.json'; +import rule593 from './credential_access_azure_full_network_packet_capture_detected.json'; +import rule594 from './persistence_webshell_detection.json'; +import rule595 from './defense_evasion_suppression_rule_created.json'; +import rule596 from './impact_efs_filesystem_or_mount_deleted.json'; +import rule597 from './defense_evasion_execution_control_panel_suspicious_args.json'; +import rule598 from './defense_evasion_azure_blob_permissions_modified.json'; +import rule599 from './privilege_escalation_aws_suspicious_saml_activity.json'; +import rule600 from './credential_access_potential_lsa_memdump_via_mirrordump.json'; +import rule601 from './discovery_virtual_machine_fingerprinting_grep.json'; +import rule602 from './impact_backup_file_deletion.json'; +import rule603 from './credential_access_posh_minidump.json'; +import rule604 from './persistence_screensaver_engine_unexpected_child_process.json'; +import rule605 from './persistence_screensaver_plist_file_modification.json'; +import rule606 from './credential_access_suspicious_lsass_access_memdump.json'; +import rule607 from './defense_evasion_suspicious_process_access_direct_syscall.json'; +import rule608 from './discovery_posh_suspicious_api_functions.json'; +import rule609 from './privilege_escalation_via_rogue_named_pipe.json'; +import rule610 from './credential_access_suspicious_lsass_access_via_snapshot.json'; +import rule611 from './defense_evasion_posh_process_injection.json'; +import rule612 from './collection_posh_keylogger.json'; +import rule613 from './defense_evasion_posh_assembly_load.json'; +import rule614 from './defense_evasion_powershell_windows_firewall_disabled.json'; +import rule615 from './execution_posh_portable_executable.json'; +import rule616 from './execution_posh_psreflect.json'; +import rule617 from './credential_access_suspicious_comsvcs_imageload.json'; +import rule618 from './impact_aws_eventbridge_rule_disabled_or_deleted.json'; +import rule619 from './defense_evasion_microsoft_defender_tampering.json'; +import rule620 from './initial_access_azure_active_directory_high_risk_signin_atrisk_or_confirmed.json'; +import rule621 from './persistence_remote_password_reset.json'; +import rule622 from './privilege_escalation_azure_kubernetes_rolebinding_created.json'; +import rule623 from './collection_posh_audio_capture.json'; +import rule624 from './collection_posh_screen_grabber.json'; +import rule625 from './defense_evasion_posh_compressed.json'; +import rule626 from './defense_evasion_suspicious_process_creation_calltrace.json'; +import rule627 from './privilege_escalation_group_policy_iniscript.json'; +import rule628 from './privilege_escalation_group_policy_privileged_groups.json'; +import rule629 from './privilege_escalation_group_policy_scheduled_task.json'; +import rule630 from './defense_evasion_clearing_windows_console_history.json'; +import rule631 from './threat_intel_filebeat8x.json'; +import rule632 from './privilege_escalation_installertakeover.json'; +import rule633 from './credential_access_via_snapshot_lsass_clone_creation.json'; +import rule634 from './persistence_via_bits_job_notify_command.json'; +import rule635 from './execution_suspicious_java_netcon_childproc.json'; +import rule636 from './privilege_escalation_samaccountname_spoofing_attack.json'; +import rule637 from './credential_access_symbolic_link_to_shadow_copy_createdcredential_access_symbolic_link_to_shadow_copy_created.json'; +import rule638 from './credential_access_mfa_push_brute_force.json'; +import rule639 from './persistence_azure_global_administrator_role_assigned.json'; +import rule640 from './persistence_microsoft_365_global_administrator_role_assign.json'; +import rule641 from './lateral_movement_malware_uploaded_onedrive.json'; +import rule642 from './lateral_movement_malware_uploaded_sharepoint.json'; +import rule643 from './defense_evasion_ms_office_suspicious_regmod.json'; +import rule644 from './initial_access_o365_user_reported_phish_malware.json'; +import rule645 from './defense_evasion_microsoft_365_mailboxauditbypassassociation.json'; +import rule646 from './credential_access_disable_kerberos_preauth.json'; +import rule647 from './credential_access_shadow_credentials.json'; +import rule648 from './privilege_escalation_pkexec_envar_hijack.json'; +import rule649 from './credential_access_seenabledelegationprivilege_assigned_to_user.json'; +import rule650 from './persistence_msds_alloweddelegateto_krbtgt.json'; +import rule651 from './defense_evasion_disable_posh_scriptblocklogging.json'; +import rule652 from './persistence_ad_adminsdholder.json'; +import rule653 from './privilege_escalation_windows_service_via_unusual_client.json'; +import rule654 from './credential_access_dcsync_replication_rights.json'; export const rawRules = [ rule1, @@ -1282,4 +1301,23 @@ export const rawRules = [ rule633, rule634, rule635, + rule636, + rule637, + rule638, + rule639, + rule640, + rule641, + rule642, + rule643, + rule644, + rule645, + rule646, + rule647, + rule648, + rule649, + rule650, + rule651, + rule652, + rule653, + rule654, ]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json index 7cd94103c6395..2624371aa5a62 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies an Identity and Access Management (IAM) custom role creation in Google Cloud Platform (GCP). Custom roles are user-defined, and allow for the bundling of one or more supported permissions to meet specific needs. Custom roles will not be updated automatically and could lead to privilege creep if not carefully scrutinized.", "false_positives": [ - "Custom role creations may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Role creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Custom role creations may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Role creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -63,5 +63,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json index d98c6d1fb2260..defd5ce4da497 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Anti-Phish Policy Deletion", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-AntiPhishPolicy\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-antiphishpolicy?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json index 554f5f80be246..9a14545f39745 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Anti-Phish Rule Modification", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-AntiPhishRule\" or \"Disable-AntiPhishRule\") and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-antiphishrule?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json index 0f936a91023f2..eafb3b71584e2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Safe Link Policy Disabled", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Disable-SafeLinksRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-safelinksrule?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_user_restricted_from_sending_email.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_user_restricted_from_sending_email.json index 31950fc345c0e..ce2a713a5c7d2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_user_restricted_from_sending_email.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_user_restricted_from_sending_email.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 User Restricted from Sending Email", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n", "query": "event.dataset:o365.audit and event.provider:SecurityComplianceCenter and event.category:web and event.action:\"User restricted from sending email\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/cloud-app-security/anomaly-detection-policy", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_o365_user_reported_phish_malware.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_o365_user_reported_phish_malware.json new file mode 100644 index 0000000000000..8ceca899412b2 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_o365_user_reported_phish_malware.json @@ -0,0 +1,65 @@ +{ + "author": [ + "Elastic" + ], + "description": "Detects the occurrence of emails reported as Phishing or Malware by Users. Security Awareness training is essential to stay ahead of scammers and threat actors, as security products can be bypassed, and the user can still receive a malicious message. Educating users to report suspicious messages can help identify gaps in security controls and prevent malware infections and Business Email Compromise attacks.", + "false_positives": [ + "Legitimate files reported by the users" + ], + "from": "now-30m", + "index": [ + "filebeat-*", + "logs-o365*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "O365 Email Reported by User as Malware or Phish", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:SecurityComplianceCenter and event.action:AlertTriggered and rule.name:\"Email reported by user as malware or phish\"\n", + "references": [ + "https://support.microsoft.com/en-us/office/use-the-report-message-add-in-b5caa9f1-cdf3-4443-af8c-ff724ea719d2?ui=en-us&rs=en-us&ad=us" + ], + "risk_score": 47, + "rule_id": "5930658c-2107-4afc-91af-e0e55b7f7184", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Microsoft 365", + "Continuous Monitoring", + "SecOps", + "Initial Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0001", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0001/" + }, + "technique": [ + { + "id": "T1566", + "name": "Phishing", + "reference": "https://attack.mitre.org/techniques/T1566/", + "subtechnique": [ + { + "id": "T1566.001", + "name": "Spearphishing Attachment", + "reference": "https://attack.mitre.org/techniques/T1566/001/" + }, + { + "id": "T1566.002", + "name": "Spearphishing Link", + "reference": "https://attack.mitre.org/techniques/T1566/002/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_okta_user_attempted_unauthorized_access.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_okta_user_attempted_unauthorized_access.json index 222d30723bc9e..d016add9637e3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_okta_user_attempted_unauthorized_access.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_okta_user_attempted_unauthorized_access.json @@ -3,7 +3,7 @@ "Elastic", "Austin Songer" ], - "description": "Identifies when an unauthorized access attempt is made by a user for an Okta application.", + "description": "Identifies unauthorized access attempts to Okta applications.", "index": [ "filebeat-*", "logs-okta*" @@ -70,5 +70,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json index 1ccabf42237ef..25b6e42b2312f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json @@ -5,9 +5,7 @@ "description": "Identifies NullSessionPipe registry modifications that specify which pipes can be accessed anonymously. This could be indicative of adversary lateral movement preparation by making the added pipe available to everyone.", "from": "now-9m", "index": [ - "logs-endpoint.events.*", - "winlogbeat-*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -53,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json index 6e11258e23d00..ca6484afd077c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json @@ -13,7 +13,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Abnormally Large DNS Response", - "note": "## Triage and analysis\n\n### Investigating Large DNS Responses\nDetection alerts from this rule indicate possible anomalous activity around large byte DNS responses from a Windows DNS\nserver. This detection rule was created based on activity represented in exploitation of vulnerability (CVE-2020-1350)\nalso known as [SigRed](https://www.elastic.co/blog/detection-rules-for-sigred-vulnerability) during July 2020.\n\n#### Possible investigation steps:\n- This specific rule is sourced from network log activity such as DNS or network level data. It's important to validate\nthe source of the incoming traffic and determine if this activity has been observed previously within an environment.\n- Activity can be further investigated and validated by reviewing available corresponding Intrusion Detection Signatures (IDS) alerts associated with activity.\n- Further examination can be made by reviewing the `dns.question_type` network fieldset with a protocol analyzer, such as Zeek, Packetbeat, or Suricata, for `SIG` or `RRSIG` data.\n- Validate the patch level and OS of the targeted DNS server to validate the observed activity was not large-scale Internet vulnerability scanning.\n- Validate that the source of the network activity was not from an authorized vulnerability scan or compromise assessment.\n\n#### False Positive Analysis\n- Based on this rule which looks for a threshold of 60k bytes, it is possible for activity to be generated under 65k bytes\nand related to legitimate behavior. In packet capture files received by the [SANS Internet Storm Center](https://isc.sans.edu/forums/diary/PATCH+NOW+SIGRed+CVE20201350+Microsoft+DNS+Server+Vulnerability/26356/), byte responses\nwere all observed as greater than 65k bytes.\n- This activity has the ability to be triggered from compliance/vulnerability scanning or compromise assessment, it's\nimportant to determine the source of the activity and potential whitelist the source host\n\n\n### Related Rules\n- Unusual Child Process of dns.exe\n- Unusual File Modification by dns.exe\n\n### Response and Remediation\n- Review and implement the above detection logic within your environment using technology such as Endpoint security, Winlogbeat, Packetbeat, or network security monitoring (NSM) platforms such as Zeek or Suricata.\n- Ensure that you have deployed the latest Microsoft [Security Update](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350) (Monthly Rollup or Security Only) and restart the\npatched machines. If unable to patch immediately: Microsoft [released](https://support.microsoft.com/en-us/help/4569509/windows-dns-server-remote-code-execution-vulnerability) a registry-based workaround that doesn\u2019t require a\nrestart. This can be used as a temporary solution before the patch is applied.\n- Maintain backups of your critical systems to aid in quick recovery.\n- Perform routine vulnerability scans of your systems, monitor [CISA advisories](https://us-cert.cisa.gov/ncas/current-activity) and patch identified vulnerabilities.\n- If observed true positive activity, implement a remediation plan and monitor host-based artifacts for additional post-exploitation behavior.\n", + "note": "## Triage and analysis\n\n### Investigating Large DNS Responses\nDetection alerts from this rule indicate possible anomalous activity around large byte DNS responses from a Windows DNS\nserver. This detection rule was created based on activity represented in exploitation of vulnerability (CVE-2020-1350)\nalso known as [SigRed](https://www.elastic.co/blog/detection-rules-for-sigred-vulnerability) during July 2020.\n\n#### Possible investigation steps:\n- This specific rule is sourced from network log activity such as DNS or network level data. It's important to validate\nthe source of the incoming traffic and determine if this activity has been observed previously within an environment.\n- Activity can be further investigated and validated by reviewing available corresponding Intrusion Detection Signatures (IDS) alerts associated with activity.\n- Further examination can include a review of the `dns.question_type` network fieldset with a protocol analyzer, such as Zeek, Packetbeat, or Suricata, for `SIG` or `RRSIG` data.\n- Validate the patch level and OS of the targeted DNS server to validate the observed activity was not large-scale Internet vulnerability scanning.\n- Validate that the source of the network activity was not from an authorized vulnerability scan or compromise assessment.\n\n#### False Positive Analysis\n- Based on this rule which looks for a threshold of 60k bytes, it is possible for activity to be generated under 65k bytes\nand related to legitimate behavior. In packet capture files received by the [SANS Internet Storm Center](https://isc.sans.edu/forums/diary/PATCH+NOW+SIGRed+CVE20201350+Microsoft+DNS+Server+Vulnerability/26356/), byte responses\nwere all observed as greater than 65k bytes.\n- This activity can be triggered by compliance/vulnerability scanning or compromise assessment, it's\nimportant to determine the source of the activity and potentially allowlist the source host.\n\n\n### Related Rules\n- Unusual Child Process of dns.exe\n- Unusual File Modification by dns.exe\n\n### Response and Remediation\n- Review and implement the above detection logic within your environment using technology such as Endpoint security, Winlogbeat, Packetbeat, or network security monitoring (NSM) platforms such as Zeek or Suricata.\n- Ensure that you have deployed the latest Microsoft [Security Update](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350) (Monthly Rollup or Security Only) and restart the\npatched machines. If unable to patch immediately: Microsoft [released](https://support.microsoft.com/en-us/help/4569509/windows-dns-server-remote-code-execution-vulnerability) a registry-based workaround that doesn\u2019t require a\nrestart. This can be used as a temporary solution before the patch is applied.\n- Maintain backups of your critical systems to aid in quick recovery.\n- Perform routine vulnerability scans of your systems, monitor [CISA advisories](https://us-cert.cisa.gov/ncas/current-activity) and patch identified vulnerabilities.\n- If you observe a true positive, implement a remediation plan and monitor host-based artifacts for additional post-exploitation behavior.\n", "query": "event.category:(network or network_traffic) and destination.port:53 and\n (event.dataset:zeek.dns or type:dns or event.type:connection) and network.bytes > 60000\n", "references": [ "https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin-exploiting-a-17-year-old-bug-in-windows-dns-servers/", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_onedrive.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_onedrive.json new file mode 100644 index 0000000000000..37f2066e7b9b4 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_onedrive.json @@ -0,0 +1,53 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies the occurence of files uploaded to OneDrive being detected as Malware by the file scanning engine. Attackers can use File Sharing and Organization Repositories to spread laterally within the company and amplify their access. Users can inadvertently share these files without knowing their maliciousness, giving adversaries opportunity to gain initial access to other endpoints in the environment.", + "false_positives": [ + "Benign files can trigger signatures in the built-in virus protection" + ], + "from": "now-30m", + "index": [ + "filebeat-*", + "logs-o365*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "OneDrive Malware File Upload", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:OneDrive and event.code:SharePointFileOperation and event.action:FileMalwareDetected\n", + "references": [ + "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/virus-detection-in-spo?view=o365-worldwide" + ], + "risk_score": 73, + "rule_id": "bba1b212-b85c-41c6-9b28-be0e5cdfc9b1", + "severity": "high", + "tags": [ + "Elastic", + "Cloud", + "Microsoft 365", + "Continuous Monitoring", + "SecOps", + "Lateral Movement" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1080", + "name": "Taint Shared Content", + "reference": "https://attack.mitre.org/techniques/T1080/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_sharepoint.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_sharepoint.json new file mode 100644 index 0000000000000..52b06e00d68f6 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_malware_uploaded_sharepoint.json @@ -0,0 +1,53 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies the occurence of files uploaded to SharePoint being detected as Malware by the file scanning engine. Attackers can use File Sharing and Organization Repositories to spread laterally within the company and amplify their access. Users can inadvertently share these files without knowing their maliciousness, giving adversaries opportunity to gain initial access to other endpoints in the environment.", + "false_positives": [ + "Benign files can trigger signatures in the built-in virus protection" + ], + "from": "now-30m", + "index": [ + "filebeat-*", + "logs-o365*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "SharePoint Malware File Upload", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:SharePoint and event.code:SharePointFileOperation and event.action:FileMalwareDetected\n", + "references": [ + "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/virus-detection-in-spo?view=o365-worldwide" + ], + "risk_score": 73, + "rule_id": "0e52157a-8e96-4a95-a6e3-5faae5081a74", + "severity": "high", + "tags": [ + "Elastic", + "Cloud", + "Microsoft 365", + "Continuous Monitoring", + "SecOps", + "Lateral Movement" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1080", + "name": "Taint Shared Content", + "reference": "https://attack.mitre.org/techniques/T1080/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_enabled_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_enabled_registry.json index 584f24cfb30f3..46a3a25877b5d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_enabled_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_enabled_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "RDP Enabled via Registry", - "query": "registry where\nregistry.path : \"HKLM\\\\SYSTEM\\\\ControlSet*\\\\Control\\\\Terminal Server\\\\fDenyTSConnections\" and\nregistry.data.strings == \"0\" and not (process.name : \"svchost.exe\" and user.domain == \"NT AUTHORITY\") and\nnot process.executable : \"C:\\\\Windows\\\\System32\\\\SystemPropertiesRemote.exe\"\n", + "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path : \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Terminal Server\\\\fDenyTSConnections\" and\n registry.data.strings : (\"0\", \"0x00000000\") and not (process.name : \"svchost.exe\" and user.domain == \"NT AUTHORITY\") and\n not process.executable : \"C:\\\\Windows\\\\System32\\\\SystemPropertiesRemote.exe\"\n", "risk_score": 47, "rule_id": "58aa72ca-d968-4f34-b9f7-bea51d75eb50", "severity": "medium", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_sharprdp_target.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_sharprdp_target.json index e5bfc3242be34..c4001b6ed88cf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_sharprdp_target.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_rdp_sharprdp_target.json @@ -5,9 +5,7 @@ "description": "Identifies potential behavior of SharpRDP, which is a tool that can be used to perform authenticated command execution against a remote target via Remote Desktop Protocol (RDP) for the purposes of lateral movement.", "from": "now-9m", "index": [ - "logs-endpoint.events.*", - "winlogbeat-*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -52,5 +50,5 @@ } ], "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_scheduled_task_target.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_scheduled_task_target.json index 710f08ce5213a..95170577bc8c9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_scheduled_task_target.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_scheduled_task_target.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Remote Scheduled Task Creation", - "note": "## Triage and analysis\n\n### Investigating Creation of Remote Scheduled Tasks\n\n[Scheduled tasks](https://docs.microsoft.com/en-us/windows/win32/taskschd/about-the-task-scheduler) are a great mechanism used for persistence and executing programs. These features can\nbe used remotely for a variety of legitimate reasons, but at the same time used by malware and adversaries.\nWhen investigating scheduled tasks that have been set-up remotely, one of the first methods should be determining the\noriginal intent behind the configuration and verify if the activity is tied to benign behavior such as software installations or any kind\nof network administrator work. One objective for these alerts is to understand the configured action within the scheduled\ntask, this is captured within the registry event data for this rule and can be base64 decoded to view the value.\n\n#### Possible investigation steps:\n- Review the base64 encoded tasks actions registry value to investigate the task configured action.\n- Determine if task is related to legitimate or benign behavior based on the corresponding process or program tied to the\nscheduled task.\n- Further examination should include both the source and target machines where host-based artifacts and network logs\nshould be reviewed further around the time window of the creation of the scheduled task.\n\n### False Positive Analysis\n- There is a high possibility of benign activity tied to the creation of remote scheduled tasks as it is a general feature\nwithin Windows and used for legitimate purposes for a wide range of activity. Any kind of context should be found to\nfurther understand the source of the activity and determine the intent based on the scheduled task contents.\n\n### Related Rules\n- Service Command Lateral Movement\n- Remotely Started Services via RPC\n\n### Response and Remediation\n- This behavior represents post-exploitation actions such as persistence or lateral movement, immediate response should\nbe taken to review and investigate the activity and potentially isolate involved machines to prevent further post-compromise\nbehavior.\n- Remove scheduled task and any other related artifacts to the activity.\n- Review privileged account management and user account management settings such as implementing GPO policies to further\nrestrict activity or configure settings that only allow Administrators to create remote scheduled tasks.\n", + "note": "## Triage and analysis\n\n### Investigating Creation of Remote Scheduled Tasks\n\n[Scheduled tasks](https://docs.microsoft.com/en-us/windows/win32/taskschd/about-the-task-scheduler) are a great\nmechanism for persistence and program execution. These features can\nbe used remotely for a variety of legitimate reasons, but at the same time used by malware and adversaries.\nWhen investigating scheduled tasks that were set up remotely, one of the first steps should be to determine the\noriginal intent behind the configuration and to verify if the activity is tied to benign behavior such as software installation or any kind\nof network administrator work. One objective for these alerts is to understand the configured action within the scheduled\ntask. This is captured within the registry event data for this rule and can be base64 decoded to view the value.\n\n#### Possible investigation steps:\n- Review the base64 encoded tasks actions registry value to investigate the task configured action.\n- Determine if task is related to legitimate or benign behavior based on the corresponding process or program tied to the\nscheduled task.\n- Further examination should include both the source and target machines where host-based artifacts and network logs\nshould be reviewed further around the time window of the creation of the scheduled task.\n\n### False Positive Analysis\n- There is a high possibility of benign activity tied to the creation of remote scheduled tasks as it is a general feature\nwithin Windows and used for legitimate purposes for a wide range of activity. Any kind of context should be found to\nfurther understand the source of the activity and determine the intent based on the scheduled task contents.\n\n### Related Rules\n- Service Command Lateral Movement\n- Remotely Started Services via RPC\n\n### Response and Remediation\n- This behavior represents post-exploitation actions such as persistence or lateral movement, immediately review and\ninvestigate the activity and potentially isolate involved machines to prevent further post-compromise\nbehavior.\n- Remove scheduled task and any other related artifacts to the activity.\n- Review privileged account management and user account management settings such as implementing GPO policies to further\nrestrict activity or configure settings that only allow Administrators to create remote scheduled tasks.\n", "query": "/* Task Scheduler service incoming connection followed by TaskCache registry modification */\n\nsequence by host.id, process.entity_id with maxspan = 1m\n [network where process.name : \"svchost.exe\" and\n network.direction : (\"incoming\", \"ingress\") and source.port >= 49152 and destination.port >= 49152 and\n source.ip != \"127.0.0.1\" and source.ip != \"::1\"\n ]\n [registry where registry.path : \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tasks\\\\*\\\\Actions\"]\n", "risk_score": 47, "rule_id": "954ee7c8-5437-49ae-b2d6-2960883898e9", @@ -64,5 +64,5 @@ } ], "type": "eql", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_service_control_spawned_script_int.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_service_control_spawned_script_int.json index 61234f392158f..3cf70a8f26739 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_service_control_spawned_script_int.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_service_control_spawned_script_int.json @@ -5,14 +5,14 @@ "description": "Identifies Service Control (sc.exe) spawning from script interpreter processes to create, modify, or start services. This could be indicative of adversary lateral movement but will be noisy if commonly done by admins.", "from": "now-9m", "index": [ - "winlogbeat-*", "logs-endpoint.events.*", - "logs-windows.*" + "logs-system.*", + "winlogbeat-*" ], "language": "eql", "license": "Elastic License v2", "name": "Service Control Spawned via Script Interpreter", - "query": "process where event.type == \"start\" and\n (process.name : \"sc.exe\" or process.pe.original_file_name == \"sc.exe\") and\n process.parent.name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\",\n \"wmic.exe\", \"mshta.exe\",\"powershell.exe\", \"pwsh.exe\") and\n process.args:(\"config\", \"create\", \"start\", \"delete\", \"stop\", \"pause\") and\n /* exclude SYSTEM SID - look for service creations by non-SYSTEM user */\n not user.id : \"S-1-5-18\"\n", + "query": "/* This rule is not compatible with Sysmon due to user.id issues */\n\nprocess where event.type == \"start\" and\n (process.name : \"sc.exe\" or process.pe.original_file_name == \"sc.exe\") and\n process.parent.name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\",\n \"wmic.exe\", \"mshta.exe\",\"powershell.exe\", \"pwsh.exe\") and\n process.args:(\"config\", \"create\", \"start\", \"delete\", \"stop\", \"pause\") and\n /* exclude SYSTEM SID - look for service creations by non-SYSTEM user */\n not user.id : \"S-1-5-18\"\n", "risk_score": 21, "rule_id": "e8571d5f-bea1-46c2-9f56-998de2d3ed95", "severity": "low", @@ -42,5 +42,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json index 6933a81a22944..6c8b7805bbb06 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange DKIM Signing Configuration Disabled", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Set-DkimSigningConfig\" and o365.audit.Parameters.Enabled:False and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/set-dkimsigningconfig?view=exchange-ps" @@ -32,5 +32,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json index add3495d03271..c2074329fb5ab 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Teams Custom Application Interaction Allowed", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:MicrosoftTeams and\nevent.category:web and event.action:TeamsTenantSettingChanged and\no365.audit.Name:\"Allow sideloading and interaction of custom apps\" and\no365.audit.NewValue:True and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload" @@ -32,5 +32,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json index 1b64f1d85301a..a751087df9676 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "machine_learning_job_id": "high_distinct_count_error_message", "name": "Spike in AWS Error Messages", - "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n## Triage and analysis\n\n### Investigating Spikes in CloudTrail Errors\n\nCloudTrail logging provides visibility on actions taken within an AWS environment. By monitoring these events and understanding\nwhat is considered normal behavior within an organization, suspicious or malicious activity can be spotted when deviations\nare observed. This example rule triggers from a large spike in the number of CloudTrail log messages that contain a\nparticular error message. The error message in question was associated with the response to an AWS API command or method call,\nthis has the potential to uncover unknown threats or activity.\n\n#### Possible investigation steps:\n- Examine the history of the error. Has it manifested before? If the error, which is visible in the `aws.cloudtrail.error_message` field, only manifested recently, it might be related to recent changes in an automation module or script.\n- Examine the request parameters. These may provide indications as to the nature of the task being performed when the error occurred. Is the error related to unsuccessful attempts to enumerate or access objects, data, or secrets? If so, this can sometimes be a byproduct of discovery, privilege escalation or lateral movement attempts.\n- Consider the user as identified by the `user.name field`. Is this activity part of an expected workflow for the user context? Examine the user identity in the `aws.cloudtrail.user_identity.arn` field and the access key ID in the `aws.cloudtrail.user_identity.access_key_id` field, which can help identify the precise user context. The user agent details in the `user_agent.original` field may also indicate what kind of a client made the request.\n- Consider the source IP address and geolocation for the calling user who issued the command. Do they look normal for the calling user? If the source is an EC2 IP address, is it associated with an EC2 instance in one of your accounts, or could it be sourcing from an EC2 instance that's not under your control? If it is an authorized EC2 instance, is the activity associated with normal behavior for the instance role or roles? Are there any other alerts or signs of suspicious activity involving this instance?\n\n### False Positive Analysis\n- This rule has the possibility to produce false positives based on unexpected activity occurring such as bugs or recent\nchanges to automation modules or scripting.\n- Adoption of new services or implementing new functionality to scripts may generate false positives\n\n### Related Rules\n- Unusual AWS Command for a User\n- Rare AWS Error Code\n\n### Response and Remediation\n- If activity is observed as suspicious or malicious, immediate response should be looked into rotating and deleting AWS IAM access keys\n- Validate if any unauthorized new users were created, remove these accounts and request password resets for other IAM users\n- Look into enabling multi-factor authentication for users\n- Follow security best practices [outlined](https://aws.amazon.com/premiumsupport/knowledge-center/security-best-practices/) by AWS\n", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n## Triage and analysis\n\n### Investigating Spikes in CloudTrail Errors\n\nCloudTrail logging provides visibility on actions taken within an AWS environment. By monitoring these events and understanding\nwhat is considered normal behavior within an organization, suspicious or malicious activity can be spotted when deviations\nare observed. This example rule triggers from a large spike in the number of CloudTrail log messages that contain a\nparticular error message. The error message in question was associated with the response to an AWS API command or method call,\nthis has the potential to uncover unknown threats or activity.\n\n#### Possible investigation steps:\n- Examine the history of the error. Has it manifested before? If the error, which is visible in the `aws.cloudtrail.error_message` field, only manifested recently, it might be related to recent changes in an automation module or script.\n- Examine the request parameters. These may provide indications as to the nature of the task being performed when the error occurred. Is the error related to unsuccessful attempts to enumerate or access objects, data, or secrets? If so, this can sometimes be a byproduct of discovery, privilege escalation or lateral movement attempts.\n- Consider the user as identified by the `user.name field`. Is this activity part of an expected workflow for the user context? Examine the user identity in the `aws.cloudtrail.user_identity.arn` field and the access key ID in the `aws.cloudtrail.user_identity.access_key_id` field, which can help identify the precise user context. The user agent details in the `user_agent.original` field may also indicate what kind of a client made the request.\n- Consider the source IP address and geolocation for the calling user who issued the command. Do they look normal for the calling user? If the source is an EC2 IP address, is it associated with an EC2 instance in one of your accounts, or could it be sourcing from an EC2 instance that's not under your control? If it is an authorized EC2 instance, is the activity associated with normal behavior for the instance role or roles? Are there any other alerts or signs of suspicious activity involving this instance?\n\n### False Positive Analysis\n- This rule has the possibility to produce false positives based on unexpected activity occurring such as bugs or recent\nchanges to automation modules or scripting.\n- The adoption of new services or the addition of new functionality to scripts may generate false positives.\n\n### Related Rules\n- Unusual AWS Command for a User\n- Rare AWS Error Code\n\n### Response and Remediation\n- If suspicious or malicious activity is observed, immediately rotate and delete relevant AWS IAM access keys\n- Validate if any unauthorized new users were created, remove these accounts and request password resets for other IAM users\n- Look into enabling multi-factor authentication for users\n- Follow security best practices [outlined](https://aws.amazon.com/premiumsupport/knowledge-center/security-best-practices/) by AWS\n", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" ], @@ -26,5 +26,5 @@ "ML" ], "type": "machine_learning", - "version": 7 + "version": 8 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json index 4576b080e1ea6..a9483c3f981c4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "machine_learning_job_id": "rare_method_for_a_country", "name": "Unusual Country For an AWS Command", - "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n## Triage and analysis\n\n### Investigating an Unusual Country For an AWS Command\n\nCloudTrail logging provides visibility on actions taken within an AWS environment. By monitoring these events and understanding\nwhat is considered normal behavior within an organization, suspicious or malicious activity can be spotted when deviations\nare observed. This example rule focuses on AWS command activity where the country from the source of the activity has been\nconsidered unusual based on previous history.\n\n#### Possible investigation steps:\n- Consider the source IP address and geolocation for the calling user who issued the command. Do they look normal for the calling user? If the source is an EC2 IP address, is it associated with an EC2 instance in one of your accounts, or could it be sourcing from an EC2 instance that's not under your control? If it is an authorized EC2 instance, is the activity associated with normal behavior for the instance role or roles? Are there any other alerts or signs of suspicious activity involving this instance?\n- Consider the user as identified by the `user.name` field. Is this command part of an expected workflow for the user context? Examine the user identity in the `aws.cloudtrail.user_identity.arn` field and the access key ID in the `aws.cloudtrail.user_identity.access_key_id` field, which can help identify the precise user context. The user agent details in the `user_agent.original` field may also indicate what kind of a client made the request.\n- Consider the time of day. If the user is a human, not a program or script, did the activity take place during a normal time of day?\n- Examine the history of the command. If the command, which is visible in the `event.action field`, only manifested recently, it might be part of a new automation module or script. If it has a consistent cadence (for example, if it appears in small numbers on a weekly or monthly cadence), it might be part of a housekeeping or maintenance process.\n- Examine the request parameters. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n\n### False Positive Analysis\n- False positives can occur if activity is coming from new employees based in a country with no previous history in AWS,\ntherefore it's important to validate the activity listed in the investigation steps above.\n\n### Related Rules\n- Unusual City For an AWS Command\n- Unusual AWS Command for a User\n- Rare AWS Error Code\n\n### Response and Remediation\n- If activity is observed as suspicious or malicious, immediate response should be looked into rotating and deleting AWS IAM access keys\n- Validate if any unauthorized new users were created, remove these accounts and request password resets for other IAM users\n- Look into enabling multi-factor authentication for users\n- Follow security best practices [outlined](https://aws.amazon.com/premiumsupport/knowledge-center/security-best-practices/) by AWS\n", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n## Triage and analysis\n\n### Investigating an Unusual Country For an AWS Command\n\nCloudTrail logging provides visibility on actions taken within an AWS environment. By monitoring these events and understanding\nwhat is considered normal behavior within an organization, suspicious or malicious activity can be spotted when deviations\nare observed. This example rule focuses on AWS command activity where the country from the source of the activity has been\nconsidered unusual based on previous history.\n\n#### Possible investigation steps:\n- Consider the source IP address and geolocation for the calling user who issued the command. Do they look normal for the calling user? If the source is an EC2 IP address, is it associated with an EC2 instance in one of your accounts, or could it be sourcing from an EC2 instance that's not under your control? If it is an authorized EC2 instance, is the activity associated with normal behavior for the instance role or roles? Are there any other alerts or signs of suspicious activity involving this instance?\n- Consider the user as identified by the `user.name` field. Is this command part of an expected workflow for the user context? Examine the user identity in the `aws.cloudtrail.user_identity.arn` field and the access key ID in the `aws.cloudtrail.user_identity.access_key_id` field, which can help identify the precise user context. The user agent details in the `user_agent.original` field may also indicate what kind of a client made the request.\n- Consider the time of day. If the user is a human, not a program or script, did the activity take place during a normal time of day?\n- Examine the history of the command. If the command, which is visible in the `event.action field`, only manifested recently, it might be part of a new automation module or script. If it has a consistent cadence (for example, if it appears in small numbers on a weekly or monthly cadence), it might be part of a housekeeping or maintenance process.\n- Examine the request parameters. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n\n### False Positive Analysis\n- False positives can occur if activity is coming from new employees based in a country with no previous history in AWS,\ntherefore it's important to validate the activity listed in the investigation steps above.\n\n### Related Rules\n- Unusual City For an AWS Command\n- Unusual AWS Command for a User\n- Rare AWS Error Code\n\n### Response and Remediation\n- If suspicious or malicious activity is observed, immediately rotate and delete relevant AWS IAM access keys\n- Validate if any unauthorized new users were created, remove these accounts and request password resets for other IAM users\n- Look into enabling multi-factor authentication for users\n- Follow security best practices [outlined](https://aws.amazon.com/premiumsupport/knowledge-center/security-best-practices/) by AWS\n", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" ], @@ -26,5 +26,5 @@ "ML" ], "type": "machine_learning", - "version": 7 + "version": 8 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json index d8bf26884b16f..85b3ec0d846e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json @@ -15,7 +15,7 @@ "v2_rare_process_by_host_windows_ecs" ], "name": "Unusual Process For a Windows Host", - "note": "## Triage and analysis\n\n### Investigating an Unusual Windows Process\n\nSearching for abnormal Windows processes is a good methodology to find potentially malicious activity within a network.\nBy understanding what is commonly run within an environment and developing baselines for legitimate activity can help\nuncover potential malware and suspicious behaviors.\n\n#### Possible investigation steps:\n- Consider the user as identified by the `user.name` field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process only manifested recently, it might be part of a new software package. If it has a consistent cadence (for example if it runs monthly or quarterly), it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package.\n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools.\n\n### False Positive Analysis\n- Validate the unusual Windows process is not related to new benign software installation activity. If related to\nlegitimate software, this can be done by leveraging the exception workflow in the Kibana Security App or Elasticsearch\nAPI to tune this rule to your environment\n- Try to understand the context of the execution by thinking about the user, machine, or business purpose. It's possible that a small number of endpoints\nsuch as servers that have very unique software that might appear to be unusual, but satisfy a specific business need.\n\n### Related Rules\n- Anomalous Windows Process Creation\n- Unusual Windows Path Activity\n- Unusual Windows Process Calling the Metadata Service\n\n### Response and Remediation\n- This rule is related to process execution events and should be immediately reviewed and investigated to determine if malicious\n- Based on validation and if malicious, the impacted machine should be isolated and analyzed to determine other post-compromise\nbehavior such as setting up persistence or performing lateral movement.\n- Look into preventive measures such as Windows Defender Application Control and AppLocker to gain better control on\nwhat is allowed to run on Windows infrastructure.\n", + "note": "## Triage and analysis\n\n### Investigating an Unusual Windows Process\n\nSearching for abnormal Windows processes is a good methodology to find potentially malicious activity within a network.\nUnderstanding what is commonly run within an environment and developing baselines for legitimate activity can help\nuncover potential malware and suspicious behaviors.\n\n#### Possible investigation steps:\n- Consider the user as identified by the `user.name` field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process only manifested recently, it might be part of a new software package. If it has a consistent cadence (for example if it runs monthly or quarterly), it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package.\n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools.\n\n### False Positive Analysis\n- Validate the unusual Windows process is not related to new benign software installation activity. If related to\nlegitimate software, this can be done by leveraging the exception workflow in the Kibana Security App or Elasticsearch\nAPI to tune this rule to your environment\n- Try to understand the context of the execution by thinking about the user, machine, or business purpose. It's possible that a small number of endpoints\nsuch as servers that have very unique software that might appear to be unusual, but satisfy a specific business need.\n\n### Related Rules\n- Anomalous Windows Process Creation\n- Unusual Windows Path Activity\n- Unusual Windows Process Calling the Metadata Service\n\n### Response and Remediation\n- This rule is related to process execution events and should be immediately reviewed and investigated to determine if malicious.\n- Based on validation and if malicious, the impacted machine should be isolated and analyzed to determine other post-compromise\nbehavior such as setting up persistence or performing lateral movement.\n- Look into preventive measures such as Windows Defender Application Control and AppLocker to gain better control on\nwhat is allowed to run on Windows infrastructure.\n", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" ], @@ -30,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ad_adminsdholder.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ad_adminsdholder.json new file mode 100644 index 0000000000000..2aa6e71b4f845 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ad_adminsdholder.json @@ -0,0 +1,45 @@ +{ + "author": [ + "Elastic" + ], + "description": "Detects modifications in the AdminSDHolder object. Attackers can abuse the SDProp process to implement a persistent backdoor in Active Directory. SDProp compares the permissions on protected objects with those defined on the AdminSDHolder object. If the permissions on any of the protected accounts and groups do not match, the permissions on the protected accounts and groups are reset to match those of the domain's AdminSDHolder object, regaining their Administrative Privileges.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*", + "logs-system.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "AdminSDHolder Backdoor", + "query": "event.action:\"Directory Service Changes\" and event.code:5136 and winlog.event_data.ObjectDN:CN=AdminSDHolder,CN=System*\n", + "references": [ + "https://adsecurity.org/?p=1906", + "https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory#adminsdholder" + ], + "risk_score": 73, + "rule_id": "6e9130a5-9be6-48e5-943a-9628bfc74b18", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Persistence", + "Active Directory" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_appcertdlls_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_appcertdlls_registry.json index a154bc4e60bfb..dee8ce22bed2a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_appcertdlls_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_appcertdlls_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Registry Persistence via AppCert DLL", - "query": "registry where\n/* uncomment once stable length(bytes_written_string) > 0 and */\n registry.path : \"HKLM\\\\SYSTEM\\\\ControlSet*\\\\Control\\\\Session Manager\\\\AppCertDLLs\\\\*\"\n", + "query": "registry where\n/* uncomment once stable length(bytes_written_string) > 0 and */\n registry.path : \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Session Manager\\\\AppCertDLLs\\\\*\"\n", "risk_score": 47, "rule_id": "513f0ffd-b317-4b9c-9494-92ce861f22c7", "severity": "medium", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_global_administrator_role_assigned.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_global_administrator_role_assigned.json new file mode 100644 index 0000000000000..c5420012e7a39 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_global_administrator_role_assigned.json @@ -0,0 +1,57 @@ +{ + "author": [ + "Elastic" + ], + "description": "In Azure Active Directory (Azure AD), permissions to manage resources are assigned using Roles. The Global Administrator is a role that enables users to have access to all administrative features in Azure AD and services that use Azure Active Directory identities like the Microsoft 365 Defender portal, the Microsoft 365 compliance center, Exchange, SharePoint Online, and Skype for Business Online. Attackers can add users as Global Administrators to maintain access and manage all subscriptions and their settings and resources.", + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-azure*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Azure AD Global Administrator Role Assigned", + "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and\nazure.auditlogs.operation_name:\"Add member to role\" and\nazure.auditlogs.properties.target_resources.0.modified_properties.1.new_value:\"\\\"Global Administrator\\\"\"\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/active-directory/roles/permissions-reference#global-administrator" + ], + "risk_score": 47, + "rule_id": "04c5a96f-19c5-44fd-9571-a0b033f9086f", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Azure", + "Continuous Monitoring", + "SecOps", + "Identity and Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1098", + "name": "Account Manipulation", + "reference": "https://attack.mitre.org/techniques/T1098/", + "subtechnique": [ + { + "id": "T1098.003", + "name": "Add Office 365 Global Administrator Role", + "reference": "https://attack.mitre.org/techniques/T1098/003/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json index a545ae77d03ea..9002924a3df32 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies the creation of an AWS Elastic Compute Cloud (EC2) network access control list (ACL) or an entry in a network ACL with a specified rule number.", "false_positives": [ - "Network ACL's may be created by a network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Network ACL creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Network ACL's may be created by a network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Network ACL creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_security_group_configuration_change_detection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_security_group_configuration_change_detection.json index b7421934ba8e8..5856c5a7a0111 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_security_group_configuration_change_detection.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_security_group_configuration_change_detection.json @@ -5,7 +5,7 @@ ], "description": "Identifies a change to an AWS Security Group Configuration. A security group is like a virtual firewall, and modifying configurations may allow unauthorized access. Threat actors may abuse this to establish persistence, exfiltrate data, or pivot in an AWS environment.", "false_positives": [ - "A security group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A security group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-30m", "index": [ @@ -67,5 +67,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_ifeo_injection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_ifeo_injection.json index 3da2a6e436686..3acae337041b3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_ifeo_injection.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_ifeo_injection.json @@ -5,9 +5,7 @@ "description": "The Debugger and SilentProcessExit registry keys can allow an adversary to intercept the execution of files, causing a different process to be executed. This functionality can be abused by an adversary to establish persistence.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -52,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_startup_shell_folder_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_startup_shell_folder_modified.json index 21ad9c5161541..a658ae60cd03d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_startup_shell_folder_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_evasion_registry_startup_shell_folder_modified.json @@ -5,14 +5,12 @@ "description": "Identifies suspicious startup shell folder modifications to change the default Startup directory in order to bypass detections monitoring file creation in the Windows Startup folder.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", "name": "Suspicious Startup Shell Folder Modification", - "note": "## Triage and analysis\n\n### Investigating Suspicious Startup Shell Activity\n\nTechniques used within malware and by adversaries often leverage the Windows registry to store malicious programs for\npersistence. Startup shell folders are often targeted as they are not as prevalent as normal Startup folder paths so this\nbehavior may evade existing AV/EDR solutions. Another preference is that these programs might run with higher privileges\nwhich can be ideal for an attacker.\n\n#### Possible investigation steps:\n- Review the source process and related file tied to the Windows Registry entry\n- Validate the activity is not related to planned patches, updates, network administrator activity or legitimate software\ninstallations\n- Determine if activity is unique by validating if other machines in same organization have similar entry\n\n### False Positive Analysis\n- There is a high possibility of benign legitimate programs being added to Shell folders. This activity could be based\non new software installations, patches, or any kind of network administrator related activity. Before entering further\ninvestigation, this activity should be validated that is it not related to benign activity\n\n### Related Rules\n- Startup or Run Key Registry Modification\n- Persistent Scripts in the Startup Directory\n\n### Response and Remediation\n- Activity should first be validated as a true positive event if so then immediate response should be taken to review,\ninvestigate and potentially isolate activity to prevent further post-compromise behavior\n- The respective binary or program tied to this persistence method should be further analyzed and reviewed to understand\nit's behavior and capabilities\n- Since this activity is considered post-exploitation behavior, it's important to understand how the behavior was first\ninitialized such as through a macro-enabled document that was attached in a phishing email. By understanding the source\nof the attack, this information can then be used to search for similar indicators on other machines in the same environment.\n", + "note": "## Triage and analysis\n\n### Investigating Suspicious Startup Shell Activity\n\nTechniques used within malware and by adversaries often leverage the Windows registry to store malicious programs for\npersistence. Startup shell folders are often targeted as they are not as prevalent as normal Startup folder paths so this\nbehavior may evade existing AV/EDR solutions. These programs may also run with higher privileges which can be ideal for\nan attacker.\n\n#### Possible investigation steps:\n- Review the source process and related file tied to the Windows Registry entry\n- Validate the activity is not related to planned patches, updates, network administrator activity or legitimate software\ninstallations\n- Determine if activity is unique by validating if other machines in same organization have similar entry\n\n### False Positive Analysis\n- There is a high possibility of benign legitimate programs being added to Shell folders. This activity could be based\non new software installations, patches, or any kind of network administrator related activity. Before entering further\ninvestigation, it should be verified that this activity is not benign.\n\n### Related Rules\n- Startup or Run Key Registry Modification\n- Persistent Scripts in the Startup Directory\n\n### Response and Remediation\n- Activity should first be validated as a true positive event if so then take immediate action to review,\ninvestigate and potentially isolate activity to prevent further post-compromise behavior\n- The respective binary or program tied to this persistence method should be further analyzed and reviewed to understand\nits behavior and capabilities\n- Since this activity is considered post-exploitation behavior, it's important to understand how the behavior was first\ninitialized such as through a macro-enabled document that was attached in a phishing email. By understanding the source\nof the attack, this information can then be used to search for similar indicators on other machines in the same environment.\n", "query": "registry where\n registry.path : (\n \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\User Shell Folders\\\\Common Startup\",\n \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Shell Folders\\\\Common Startup\",\n \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\User Shell Folders\\\\Startup\",\n \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Shell Folders\\\\Startup\"\n ) and\n registry.data.strings != null and\n /* Normal Startup Folder Paths */\n not registry.data.strings : (\n \"C:\\\\ProgramData\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs\\\\Startup\",\n \"%ProgramData%\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs\\\\Startup\",\n \"%USERPROFILE%\\\\AppData\\\\Roaming\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs\\\\Startup\",\n \"C:\\\\Users\\\\*\\\\AppData\\\\Roaming\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs\\\\Startup\"\n )\n", "risk_score": 73, "rule_id": "c8b150f0-0164-475b-a75e-74b47800a9ff", @@ -50,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 2 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_exchange_suspicious_mailbox_right_delegation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_exchange_suspicious_mailbox_right_delegation.json index e950569f19878..6946dd97761b6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_exchange_suspicious_mailbox_right_delegation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_exchange_suspicious_mailbox_right_delegation.json @@ -3,7 +3,7 @@ "Elastic", "Austin Songer" ], - "description": "Identifies the assignment of rights to accesss content from another mailbox. An adversary may use the compromised account to send messages to other accounts in the network of the target business while creating inbox rules, so messages can evade spam/phishing detection mechanisms.", + "description": "Identifies the assignment of rights to access content from another mailbox. An adversary may use the compromised account to send messages to other accounts in the network of the target organization while creating inbox rules, so messages can evade spam/phishing detection mechanisms.", "false_positives": [ "Assignment of rights to a service account." ], @@ -14,8 +14,8 @@ "language": "kuery", "license": "Elastic License v2", "name": "O365 Exchange Suspicious Mailbox Right Delegation", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.action:Add-MailboxPermission and \no365.audit.Parameters.AccessRights:(FullAccess or SendAs or SendOnBehalf) and event.outcome:success\n", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.action:Add-MailboxPermission and \no365.audit.Parameters.AccessRights:(FullAccess or SendAs or SendOnBehalf) and event.outcome:success and\nnot user.id : \"NT AUTHORITY\\SYSTEM (Microsoft.Exchange.Servicehost)\"\n", "risk_score": 21, "rule_id": "0ce6487d-8069-4888-9ddd-61b52490cebc", "severity": "low", @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json index 07372389f48c3..d586982dcf513 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json @@ -4,7 +4,7 @@ ], "description": "Identifies the deletion of an Identity and Access Management (IAM) service account key in Google Cloud Platform (GCP). Each service account is associated with two sets of public/private RSA key pairs that are used to authenticate. If a key is deleted, the application will no longer be able to access Google Cloud resources using that key. A security best practice is to rotate your service account keys regularly.", "false_positives": [ - "Service account key deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Key deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Service account key deletions may be done by a system or network administrator. Verify whether the user email, resource name, and/or hostname should be making changes in your environment. Key deletions by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "index": [ "filebeat-*", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json index 084ccb4da74f2..bced9ad8da3b2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies the creation of a group in AWS Identity and Access Management (IAM). Groups specify permissions for multiple users. Any user in a group automatically has the permissions that are assigned to the group.", "false_positives": [ - "A group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Group creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Group creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json index 3c9626dcf5513..0c58ee2696e58 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Local Scheduled Task Creation", - "query": "sequence with maxspan=1m\n [process where event.type != \"end\" and\n ((process.name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\", \"winrshost.exe\") or\n process.pe.original_file_name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\",\n \"winrshost.exe\")) or\n process.code_signature.trusted == false)] by process.entity_id\n [process where event.type == \"start\" and\n (process.name : \"schtasks.exe\" or process.pe.original_file_name == \"schtasks.exe\") and\n process.args : (\"/create\", \"-create\") and process.args : (\"/RU\", \"/SC\", \"/TN\", \"/TR\", \"/F\", \"/XML\") and\n /* exclude SYSTEM SIDs - look for task creations by non-SYSTEM user */\n not user.id : (\"S-1-5-18\", \"S-1-5-19\", \"S-1-5-20\")] by process.parent.entity_id\n", + "query": "sequence with maxspan=1m\n [process where event.type != \"end\" and\n ((process.name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\", \"winrshost.exe\") or\n process.pe.original_file_name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\",\n \"winrshost.exe\")) or\n process.code_signature.trusted == false)] by process.entity_id\n [process where event.type == \"start\" and\n (process.name : \"schtasks.exe\" or process.pe.original_file_name == \"schtasks.exe\") and\n process.args : (\"/create\", \"-create\") and process.args : (\"/RU\", \"/SC\", \"/TN\", \"/TR\", \"/F\", \"/XML\") and\n /* exclude SYSTEM Integrity Level - look for task creations by non-SYSTEM user */\n not (process.Ext.token.integrity_level_name : \"System\" or winlog.event_data.IntegrityLevel : \"System\")\n ] by process.parent.entity_id\n", "risk_score": 21, "rule_id": "afcce5ad-65de-4ed2-8516-5e093d3ac99a", "severity": "low", @@ -52,5 +52,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json index b145642a01968..832677a04f32b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Exchange Management Group Role Assignment", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-ManagementRoleAssignment\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/new-managementroleassignment?view=exchange-ps", @@ -50,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_global_administrator_role_assign.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_global_administrator_role_assign.json new file mode 100644 index 0000000000000..701a4f8cfad0c --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_global_administrator_role_assign.json @@ -0,0 +1,57 @@ +{ + "author": [ + "Elastic" + ], + "description": "In Azure Active Directory (Azure AD), permissions to manage resources are assigned using Roles. The Global Administrator is a role that enables users to have access to all administrative features in Azure AD and services that use Azure Active Directory identities like the Microsoft 365 Defender portal, the Microsoft 365 compliance center, Exchange, SharePoint Online, and Skype for Business Online. Attackers can add users as Global Administrators to maintain access and manage all subscriptions and their settings and resources.", + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-o365*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Microsoft 365 Global Administrator Role Assigned", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:o365.audit and event.code:\"AzureActiveDirectory\" and event.action:\"Add member to role.\" and\no365.audit.ModifiedProperties.Role_DisplayName.NewValue:\"Global Administrator\"\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/active-directory/roles/permissions-reference#global-administrator" + ], + "risk_score": 47, + "rule_id": "88671231-6626-4e1b-abb7-6e361a171fbb", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Microsoft 365", + "Continuous Monitoring", + "SecOps", + "Identity and Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1098", + "name": "Account Manipulation", + "reference": "https://attack.mitre.org/techniques/T1098/", + "subtechnique": [ + { + "id": "T1098.003", + "name": "Add Office 365 Global Administrator Role", + "reference": "https://attack.mitre.org/techniques/T1098/003/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json index f3ad4d22cf14c..c622572b8a796 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Teams External Access Enabled", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:(SkypeForBusiness or MicrosoftTeams) and\nevent.category:web and event.action:\"Set-CsTenantFederationConfiguration\" and\no365.audit.Parameters.AllowFederatedUsers:True and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/microsoftteams/manage-external-access" @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json index 93f72b401d51e..81af49294a639 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Microsoft 365 Teams Guest Access Enabled", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:(SkypeForBusiness or MicrosoftTeams) and\nevent.category:web and event.action:\"Set-CsTeamsClientConfiguration\" and\no365.audit.Parameters.AllowGuestUser:True and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/skype/get-csteamsclientconfiguration?view=skype-ps" @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_msds_alloweddelegateto_krbtgt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_msds_alloweddelegateto_krbtgt.json new file mode 100644 index 0000000000000..5d5b7b2c10236 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_msds_alloweddelegateto_krbtgt.json @@ -0,0 +1,67 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies the modification of the msDS-AllowedToDelegateTo attribute to KRBTGT. Attackers can use this technique to maintain persistence to the domain by having the ability to request tickets for the KRBTGT service.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*", + "logs-system.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "KRBTGT Delegation Backdoor", + "note": "## Config\n\nThe 'Audit User Account Management' logging policy must be configured for (Success, Failure).\nSteps to implement the logging policy with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nAccount Management > \nAudit User Account Management (Success,Failure)\n```\n", + "query": "event.action:modified-user-account and event.code:4738 and winlog.event_data.AllowedToDelegateTo:*krbtgt*\n", + "references": [ + "https://skyblue.team/posts/delegate-krbtgt", + "https://github.com/atc-project/atomic-threat-coverage/blob/master/Atomic_Threat_Coverage/Logging_Policies/LP_0026_windows_audit_user_account_management.md" + ], + "risk_score": 73, + "rule_id": "e052c845-48d0-4f46-8a13-7d0aba05df82", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Persistence", + "Active Directory" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1098", + "name": "Account Manipulation", + "reference": "https://attack.mitre.org/techniques/T1098/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1558", + "name": "Steal or Forge Kerberos Tickets", + "reference": "https://attack.mitre.org/techniques/T1558/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json index 4f28f277d21e1..864827b99f31e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json @@ -4,7 +4,7 @@ ], "description": "Identifies the creation of a new Amazon Relational Database Service (RDS) Aurora DB cluster or global database spread across multiple regions.", "false_positives": [ - "Valid clusters may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Cluster creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "Valid clusters may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Cluster creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -62,5 +62,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_group_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_group_creation.json index fc72e25299dba..f5a8b12e5485a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_group_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_group_creation.json @@ -5,7 +5,7 @@ ], "description": "Identifies the creation of an Amazon Relational Database Service (RDS) Security group.", "false_positives": [ - "An RDS security group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "An RDS security group may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Security group creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -58,5 +58,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_instance_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_instance_creation.json index 4ea6631025c11..0bc967072e0c9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_instance_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_instance_creation.json @@ -5,7 +5,7 @@ ], "description": "Identifies the creation of an Amazon Relational Database Service (RDS) Aurora database instance.", "false_positives": [ - "A database instance may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Instances creations from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "A database instance may be created by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Instances creations by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-60m", "index": [ @@ -45,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_registry_uncommon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_registry_uncommon.json index 2b94ded55e7d4..70f46879835fd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_registry_uncommon.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_registry_uncommon.json @@ -5,9 +5,7 @@ "description": "Detects changes to registry persistence keys that are uncommonly used or modified by legitimate programs. This could be an indication of an adversary's attempt to persist in a stealthy manner.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -67,5 +65,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_remote_password_reset.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_remote_password_reset.json index 6db40da8bf9ef..cb79c3be9968a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_remote_password_reset.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_remote_password_reset.json @@ -14,7 +14,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Account Password Reset Remotely", - "query": "sequence by host.id with maxspan=5m\n [authentication where event.action == \"logged-in\" and\n /* event 4624 need to be logged */\n winlog.logon.type : \"Network\" and event.outcome == \"success\" and source.ip != null and\n not source.ip in (\"127.0.0.1\", \"::1\")] by winlog.event_data.TargetLogonId\n /* event 4724 need to be logged */\n [iam where event.action == \"reset-password\"] by winlog.event_data.SubjectLogonId\n", + "query": "sequence by host.id with maxspan=5m\n [authentication where event.action == \"logged-in\" and\n /* event 4624 need to be logged */\n winlog.logon.type : \"Network\" and event.outcome == \"success\" and source.ip != null and\n source.ip != \"127.0.0.1\" and source.ip != \"::1\"] by winlog.event_data.TargetLogonId\n /* event 4724 need to be logged */\n [iam where event.action == \"reset-password\"] by winlog.event_data.SubjectLogonId\n", "references": [ "https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4724", "https://stealthbits.com/blog/manipulating-user-passwords-with-mimikatz/", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json index 1784c34feb085..3b7ab83f4f289 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json @@ -5,7 +5,7 @@ ], "description": "Identifies when an AWS Route Table has been created.", "false_positives": [ - "Route Table being created may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Route Table being created from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule. Automated processes that uses Terraform may lead to false positives." + "Route Tables may be created by a system or network administrators. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Route Table creation by unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule. Automated processes that use Terraform may lead to false positives." ], "from": "now-60m", "index": [ @@ -47,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_modified_or_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_modified_or_deleted.json index 54180a3a59a54..51ac1d7e37760 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_modified_or_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_modified_or_deleted.json @@ -5,7 +5,7 @@ ], "description": "Identifies when an AWS Route Table has been modified or deleted.", "false_positives": [ - "Route Table could be modified or deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Route Table being modified from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule. Also automated processes that uses Terraform may lead to false positives." + "Route Table could be modified or deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Route Table being modified from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule. Also automated processes that use Terraform may lead to false positives." ], "from": "now-60m", "index": [ @@ -51,5 +51,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_run_key_and_startup_broad.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_run_key_and_startup_broad.json index 46bbeb00f4d05..06405f2497f2c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_run_key_and_startup_broad.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_run_key_and_startup_broad.json @@ -5,9 +5,7 @@ "description": "Identifies run key or startup key registry modifications. In order to survive reboots and other system interrupts, attackers will modify run keys within the registry or leverage startup folder items as a form of persistence.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -49,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_screensaver_engine_unexpected_child_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_screensaver_engine_unexpected_child_process.json index 544049d2c2df1..a81074f4f866a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_screensaver_engine_unexpected_child_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_screensaver_engine_unexpected_child_process.json @@ -11,7 +11,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Unexpected Child Process of macOS Screensaver Engine", - "note": "## Triage and analysis\n\n- Analyze the descendant processes of the ScreenSaverEngine process for malicious code and suspicious behavior such\nas downloading a payload from a server\n- Review the installed and activated screensaver on the host. Triage the screensaver (.saver) file that was triggered to\nidentify whether the file is malicious or not.\n", + "note": "## Triage and analysis\n\n- Analyze the descendant processes of the ScreenSaverEngine process for malicious code and suspicious behavior such\nas a download of a payload from a server\n- Review the installed and activated screensaver on the host. Triage the screensaver (.saver) file that was triggered to\nidentify whether the file is malicious or not.\n", "query": "process where event.type == \"start\" and process.parent.name == \"ScreenSaverEngine\"\n", "references": [ "https://posts.specterops.io/saving-your-access-d562bf5bf90b", @@ -46,5 +46,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_services_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_services_registry.json index 64b9aba81551d..c44e78f95845d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_services_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_services_registry.json @@ -5,9 +5,7 @@ "description": "Identifies processes modifying the services registry key directly, instead of through the expected Windows APIs. This could be an indication of an adversary attempting to stealthily persist through abnormal service creation or modification of an existing service.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -49,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json index 2545dec90f75d..150b886c70b87 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json @@ -5,9 +5,7 @@ "description": "Identifies Component Object Model (COM) hijacking via registry modification. Adversaries may establish persistence by executing malicious content triggered by hijacked references to COM objects.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -52,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_service_created_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_service_created_registry.json index 117bf78d76287..11e7195a8de4b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_service_created_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_service_created_registry.json @@ -5,9 +5,7 @@ "description": "Identifies the creation of a suspicious ImagePath value. This could be an indication of an adversary attempting to stealthily persist or escalate privileges through abnormal service creation.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -49,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_time_provider_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_time_provider_mod.json index 4abba51668c0f..30900394ec9c3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_time_provider_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_time_provider_mod.json @@ -5,9 +5,7 @@ "description": "Windows operating systems are utilizing the time provider architecture in order to obtain accurate time stamps from other network devices or clients in the network. Time providers are implemented in the form of a DLL file which resides in System32 folder. The service W32Time initiates during the startup of Windows and loads w32time.dll. Adversaries may abuse this architecture to establish persistence, specifically by registering and enabling a malicious DLL as a time provider.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -52,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_hidden_run_key_valuename.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_hidden_run_key_valuename.json index da32a291e3574..f7589be60ff6e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_hidden_run_key_valuename.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_hidden_run_key_valuename.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Persistence via Hidden Run Key Detected", - "query": "/* Registry Path ends with backslash */\nregistry where /* length(registry.data.strings) > 0 and */\n registry.path : (\"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\", \n \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\", \n \"HKLM\\\\Software\\\\WOW6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\", \n \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer\\\\Run\\\\\", \n \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer\\\\Run\\\\\")\n", + "query": "/* Registry Path ends with backslash */\nregistry where /* length(registry.data.strings) > 0 and */\n registry.path : (\"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\",\n \"HKU\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\",\n \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\", \n \"HKLM\\\\Software\\\\WOW6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\\", \n \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer\\\\Run\\\\\",\n \"HKU\\\\*\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer\\\\Run\\\\\",\n \"HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer\\\\Run\\\\\")\n", "references": [ "https://github.com/outflanknl/SharpHide", "https://github.com/ewhitehats/InvisiblePersistence/blob/master/InvisibleRegValues_Whitepaper.pdf" @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_lsa_security_support_provider_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_lsa_security_support_provider_registry.json index 7375dbce0f795..5e796de0460aa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_lsa_security_support_provider_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_lsa_security_support_provider_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Installation of Security Support Provider", - "query": "registry where\n registry.path : (\"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\\\\Security Packages*\", \n \"HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\\\\OSConfig\\\\Security Packages*\") and\n not process.executable : (\"C:\\\\Windows\\\\System32\\\\msiexec.exe\", \"C:\\\\Windows\\\\SysWOW64\\\\msiexec.exe\")\n", + "query": "registry where\n registry.path : (\"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Lsa\\\\Security Packages*\", \n \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Lsa\\\\OSConfig\\\\Security Packages*\") and\n not process.executable : (\"C:\\\\Windows\\\\System32\\\\msiexec.exe\", \"C:\\\\Windows\\\\SysWOW64\\\\msiexec.exe\")\n", "risk_score": 47, "rule_id": "e86da94d-e54b-4fb5-b96c-cecff87e8787", "severity": "medium", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_wmi_stdregprov_run_services.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_wmi_stdregprov_run_services.json index 3fdb1e1ebc96d..d35fbf97ee846 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_wmi_stdregprov_run_services.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_wmi_stdregprov_run_services.json @@ -5,9 +5,7 @@ "description": "Identifies use of the Windows Management Instrumentation StdRegProv (registry provider) to modify commonly abused registry locations for persistence.", "from": "now-9m", "index": [ - "logs-endpoint.events.*", - "winlogbeat-*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -79,5 +77,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json index 22e3aa6cce8d9..de17b7a5b30a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json @@ -4,7 +4,7 @@ ], "description": "Identifies when SAML activity has occurred in AWS. An adversary could manipulate SAML to maintain access to the target.", "false_positives": [ - "SAML Provider could be updated by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. SAML Provider being updated from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + "SAML Provider could be updated by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. SAML Provider updates by unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." ], "from": "now-25m", "index": [ @@ -72,5 +72,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_disable_uac_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_disable_uac_registry.json index 26dbed5e681d3..c31cec2aeaa40 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_disable_uac_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_disable_uac_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Disabling User Account Control via Registry Modification", - "query": "registry where event.type == \"change\" and\n registry.path :\n (\n \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System\\\\EnableLUA\",\n \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System\\\\ConsentPromptBehaviorAdmin\",\n \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System\\\\PromptOnSecureDesktop\"\n ) and\n registry.data.strings : \"0\"\n", + "query": "registry where event.type == \"change\" and\n registry.path :\n (\n \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System\\\\EnableLUA\",\n \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System\\\\ConsentPromptBehaviorAdmin\",\n \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System\\\\PromptOnSecureDesktop\"\n ) and\n registry.data.strings : (\"0\", \"0x00000000\")\n", "references": [ "https://www.greyhathacker.net/?p=796", "https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/user-account-control-group-policy-and-registry-key-settings", @@ -76,5 +76,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json index fbba3ff429579..bc44e9cf35116 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json @@ -3,7 +3,7 @@ "Elastic", "Austin Songer" ], - "description": "Identifies the creation or patching of potential malicious rolebinding. You can assign these roles to Kubernetes subjects (users, groups, or service accounts) with role bindings and cluster role bindings.", + "description": "Identifies the creation or patching of potentially malicious role bindings. Users can use role bindings and cluster role bindings to assign roles to Kubernetes subjects (users, groups, or service accounts).", "from": "now-20m", "index": [ "filebeat-*", @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "GCP Kubernetes Rolebindings Created or Patched", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:(io.k8s.authorization.rbac.v*.clusterrolebindings.create or \nio.k8s.authorization.rbac.v*.rolebindings.create or io.k8s.authorization.rbac.v*.clusterrolebindings.patch or \nio.k8s.authorization.rbac.v*.rolebindings.patch) and event.outcome:success\n", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:(io.k8s.authorization.rbac.v*.clusterrolebindings.create or \nio.k8s.authorization.rbac.v*.rolebindings.create or io.k8s.authorization.rbac.v*.clusterrolebindings.patch or \nio.k8s.authorization.rbac.v*.rolebindings.patch) and event.outcome:success and\nnot gcp.audit.authentication_info.principal_email:\"system:addon-manager\"\n", "references": [ "https://cloud.google.com/kubernetes-engine/docs/how-to/audit-logging", "https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/", @@ -43,5 +43,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_iniscript.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_iniscript.json index df4716596039d..f08fc5979a24c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_iniscript.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_iniscript.json @@ -13,7 +13,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Startup/Logon Script added to Group Policy Object", - "note": "## Triage and analysis\n\n### Investigating Scheduled Task Execution at Scale via GPO\n\nGroup Policy Objects can be used by attackers as a mechanism for an attacker to instruct an arbitrarily large group of clients to\nexecute specified commands at Startup, Logon, Shutdown, and Logoff. This is done by creating/modifying the `scripts.ini` or \n`psscripts.ini` files. The scripts are stored in the following path: `\\Machine\\Scripts\\`, `\\User\\Scripts\\`\n\n#### Possible investigation steps:\n- This attack abuses a legitimate mechanism of the Active Directory, so it is important to determine whether the activity is legitimate\nand the administrator is authorized to perform this operation.\n- Retrieve the contents of the script file, check for any potentially malicious commands and binaries.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n- Verify if the execution is allowed and done under change management, and legitimate.\n\n### Related Rules\n- Group Policy Abuse for Privilege Addition - b9554892-5e0e-424b-83a0-5aef95aa43bf\n- Scheduled Task Execution at Scale via GPO - 15a8ba77-1c13-4274-88fe-6bd14133861e\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'Audit Detailed File Share' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nObject Access > \nAudit Detailed File Share (Success,Failure)\n```\n\nThe 'Audit Directory Service Changes' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n", + "note": "## Triage and analysis\n\n### Investigating Scheduled Task Execution at Scale via GPO\n\nGroup Policy Objects can be used by attackers as a mechanism for an attacker to instruct an arbitrarily large group of clients to\nexecute specified commands at startup, logon, shutdown, and logoff. This is done by creating/modifying the `scripts.ini` or \n`psscripts.ini` files. The scripts are stored in the following path: `\\Machine\\Scripts\\`, `\\User\\Scripts\\`\n\n#### Possible investigation steps:\n- This attack abuses a legitimate mechanism of the Active Directory, so it is important to determine whether the activity is legitimate\nand the administrator is authorized to perform this operation.\n- Retrieve the contents of the script file, and check for any potentially malicious commands and binaries.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n- Verify if the execution is allowed and done under change management, and legitimate.\n\n### Related Rules\n- Group Policy Abuse for Privilege Addition - b9554892-5e0e-424b-83a0-5aef95aa43bf\n- Scheduled Task Execution at Scale via GPO - 15a8ba77-1c13-4274-88fe-6bd14133861e\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate, and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'Audit Detailed File Share' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nObject Access > \nAudit Detailed File Share (Success,Failure)\n```\n\nThe 'Audit Directory Service Changes' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n", "query": "(\n event.code:5136 and winlog.event_data.AttributeLDAPDisplayName:(gPCMachineExtensionNames or gPCUserExtensionNames) and\n winlog.event_data.AttributeValue:(*42B5FAAE-6536-11D2-AE5A-0000F87571E3* and\n (*40B66650-4972-11D1-A7CA-0000F87571E3* or *40B6664F-4972-11D1-A7CA-0000F87571E3*))\n)\nor\n(\n event.code:5145 and winlog.event_data.ShareName:\\\\\\\\*\\\\SYSVOL and\n winlog.event_data.RelativeTargetName:(*\\\\scripts.ini or *\\\\psscripts.ini) and\n (message:WriteData or winlog.event_data.AccessList:*%%4417*)\n)\n", "references": [ "https://github.com/atc-project/atc-data/blob/master/docs/Logging_Policies/LP_0025_windows_audit_directory_service_changes.md", @@ -62,5 +62,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_privileged_groups.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_privileged_groups.json index d25b729d967c3..e2f46bc0dd897 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_privileged_groups.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_privileged_groups.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "This rule detects the first occurrence of a modification to Group Policy Object Attributes to add privileges to user accounts or use them to add users as local admins.", + "description": "Detects the first occurrence of a modification to Group Policy Object Attributes to add privileges to user accounts or use them to add users as local admins.", "index": [ "winlogbeat-*", "logs-system.*" @@ -10,7 +10,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Group Policy Abuse for Privilege Addition", - "note": "## Triage and analysis\n\n### Investigating Group Policy Abuse for Privilege Addition\n\nGroup Policy Objects can be used to add rights and/or modify Group Membership on GPOs by changing the contents of an INF file named\nGptTmpl.inf, which is responsible for storing every setting under the Security Settings container in the GPO, this file is unique\nfor each GPO, and only exists if the GPO contains security settings.\nExample Path: \"\\\\DC.com\\SysVol\\DC.com\\Policies\\{21B9B880-B2FB-4836-9C2D-2013E0D832E9}\\Machine\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf\"\n\n#### Possible investigation steps:\n- This attack abuses a legitimate mechanism of the Active Directory, so it is important to determine whether the activity is legitimate\nand the administrator is authorized to perform this operation.\n- Retrieve the contents of the `GptTmpl.inf` file, under the `Privilege Rights` section, look for potentially dangerous high privileges,\nfor example: SeTakeOwnershipPrivilege, SeEnableDelegationPrivilege, etc.\n- Inspect the user SIDs associated with these privileges\n\n### False Positive Analysis\n- Verify if these User SIDs should have these privileges enabled.\n- Inspect whether the user that has done these modifications should be allowed to do it. The user name can be found in the\n`winlog.event_data.SubjectUserName` field\n\n### Related Rules\n- Scheduled Task Execution at Scale via GPO\n- Startup/Logon Script added to Group Policy Object\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'Audit Directory Service Changes' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n", + "note": "## Triage and analysis\n\n### Investigating Group Policy Abuse for Privilege Addition\n\nGroup Policy Objects can be used to add rights and/or modify Group Membership on GPOs by changing the contents of an INF\nfile named GptTmpl.inf, which is responsible for storing every setting under the Security Settings container in the GPO.\nThis file is unique for each GPO, and only exists if the GPO contains security settings.\nExample Path: \"\\\\DC.com\\SysVol\\DC.com\\Policies\\{21B9B880-B2FB-4836-9C2D-2013E0D832E9}\\Machine\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf\"\n\n#### Possible investigation steps:\n- This attack abuses a legitimate mechanism of the Active Directory, so it is important to determine whether the activity\nis legitimate and the administrator is authorized to perform this operation.\n- Retrieve the contents of the `GptTmpl.inf` file, and under the `Privilege Rights` section, look for potentially\ndangerous high privileges, for example: SeTakeOwnershipPrivilege, SeEnableDelegationPrivilege, etc.\n- Inspect the user SIDs associated with these privileges\n\n### False Positive Analysis\n- Verify if these User SIDs should have these privileges enabled.\n- Inspect whether the user that has done these modifications should be allowed to do it. The user name can be found in the\n`winlog.event_data.SubjectUserName` field.\n\n### Related Rules\n- Scheduled Task Execution at Scale via GPO\n- Startup/Logon Script added to Group Policy Object\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate, and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'Audit Directory Service Changes' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n", "query": "event.code: \"5136\" and winlog.event_data.AttributeLDAPDisplayName:\"gPCMachineExtensionNames\" and \nwinlog.event_data.AttributeValue:(*827D319E-6EAC-11D2-A4EA-00C04F79F83A* and *803E14A0-B4FB-11D0-A0D0-00A0C90F574B*)\n", "references": [ "https://github.com/atc-project/atc-data/blob/master/docs/Logging_Policies/LP_0025_windows_audit_directory_service_changes.md", @@ -53,5 +53,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_scheduled_task.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_scheduled_task.json index bad9948b08e1c..01586f1b7409c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_scheduled_task.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_group_policy_scheduled_task.json @@ -10,7 +10,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Scheduled Task Execution at Scale via GPO", - "note": "## Triage and analysis\n\n### Investigating Scheduled Task Execution at Scale via GPO\n\nGroup Policy Objects can be used by attackers to execute Scheduled Tasks at scale to compromise Objects controlled by a given GPO,\nthis is done by changing the contents of the `\\Machine\\Preferences\\ScheduledTasks\\ScheduledTasks.xml` file.\n\n#### Possible investigation steps:\n- This attack abuses a legitimate mechanism of the Active Directory, so it is important to determine whether the activity is legitimate\nand the administrator is authorized to perform this operation.\n- Retrieve the contents of the `ScheduledTasks.xml` file, check the `` and `` XML tags for any potentially malicious\ncommands and binaries.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n- Verify if the execution is allowed and done under change management, and if the execution is legitimate.\n\n### Related Rules\n- Group Policy Abuse for Privilege Addition\n- Startup/Logon Script added to Group Policy Object\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'Audit Detailed File Share' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nObject Access > \nAudit Detailed File Share (Success,Failure)\n```\n\nThe 'Audit Directory Service Changes' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n", + "note": "## Triage and analysis\n\n### Investigating Scheduled Task Execution at Scale via GPO\n\nGroup Policy Objects can be used by attackers to execute scheduled tasks at scale to compromise objects controlled by a\ngiven GPO. This is done by changing the contents of the `\\Machine\\Preferences\\ScheduledTasks\\ScheduledTasks.xml`\nfile.\n\n#### Possible investigation steps:\n- This attack abuses a legitimate mechanism of the Active Directory, so it is important to determine whether the activity\nis legitimate and the administrator is authorized to perform this operation.\n- Retrieve the contents of the `ScheduledTasks.xml` file, \u00e1nd check the `` and `` XML tags for any\npotentially malicious commands and binaries.\n- If the action is suspicious for the user, check for any other activities done by the user in the last 48 hours.\n\n### False Positive Analysis\n- Verify if the execution is allowed and done under change management, and if the execution is legitimate.\n\n### Related Rules\n- Group Policy Abuse for Privilege Addition\n- Startup/Logon Script added to Group Policy Object\n\n### Response and Remediation\n- Immediate response should be taken to validate activity, investigate, and potentially isolate activity to prevent further\npost-compromise behavior.\n\n## Config\n\nThe 'Audit Detailed File Share' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nObject Access > \nAudit Detailed File Share (Success,Failure)\n```\n\nThe 'Audit Directory Service Changes' audit policy is required be configured (Success Failure).\nSteps to implement the logging policy with with Advanced Audit Configuration:\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nDS Access > \nAudit Directory Service Changes (Success,Failure)\n```\n", "query": "(event.code: \"5136\" and winlog.event_data.AttributeLDAPDisplayName:(\"gPCMachineExtensionNames\" or \"gPCUserExtensionNames\") and \n winlog.event_data.AttributeValue:(*CAB54552-DEEA-4691-817E-ED4A4D1AFC72* and *AADCED64-746C-4633-A97C-D61349046527*)) \nor\n(event.code: \"5145\" and winlog.event_data.ShareName: \"\\\\\\\\*\\\\SYSVOL\" and winlog.event_data.RelativeTargetName: *ScheduledTasks.xml and\n (message: WriteData or winlog.event_data.AccessList: *%%4417*))\n", "references": [ "https://github.com/atc-project/atc-data/blob/master/docs/Logging_Policies/LP_0025_windows_audit_directory_service_changes.md", @@ -68,5 +68,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_installertakeover.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_installertakeover.json index a8ad50511283a..6681bac66c053 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_installertakeover.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_installertakeover.json @@ -12,8 +12,8 @@ "language": "eql", "license": "Elastic License v2", "name": "Potential Privilege Escalation via InstallerFileTakeOver", - "note": "## Triage and analysis.\n\n### Investigating Potential Priivilege Escalation via InstallerFileTakeOver\n\nInstallerFileTakeOver is a weaponized EoP PoC to the CVE-2021-41379 vulnerability. Upon successful exploitation,\nan unprivileged user will escalate privileges to SYSTEM/NT AUTHORITY.\n\nThis rule detects the default execution of the PoC, which overwrites the `elevation_service.exe` DACL and copy itself\nto the location to escalate privileges. An attacker is able to still take over any file that is not in use (locked), which is outside the scope of this rule.\n\n#### Possible investigation steps:\n\n- Check for the digital signature of the executable\n- Look for additional processes spawned by the process, command lines and network communications.\n- Look for additional alerts involving the host and the user.\n\n### False Positive Analysis\n\n- Verify whether the digital signature exists in the executable, and if it is valid.\n\n### Related Rules\n\n- Suspicious DLL Loaded for Persistence or Privilege Escalation - bfeaf89b-a2a7-48a3-817f-e41829dc61ee\n\n### Response and Remediation\n\n- Immediate response should be taken to validate activity, investigate and potentially isolate activity to prevent further\npost-compromise behavior.\n", - "query": "/* This rule is compatible with both Sysmon and Elastic Endpoint */\n\nprocess where event.type == \"start\" and \n user.id : \"S-1-5-18\" and\n (\n (process.name : \"elevation_service.exe\" and \n not process.pe.original_file_name == \"elevation_service.exe\") or\n\n (process.parent.name : \"elevation_service.exe\" and \n process.name : (\"rundll32.exe\", \"cmd.exe\", \"powershell.exe\")) \n )\n", + "note": "## Triage and analysis.\n\n### Investigating Potential Priivilege Escalation via InstallerFileTakeOver\n\nInstallerFileTakeOver is a weaponized EoP PoC to the CVE-2021-41379 vulnerability. Upon successful exploitation,\nan unprivileged user will escalate privileges to SYSTEM/NT AUTHORITY.\n\nThis rule detects the default execution of the PoC, which overwrites the `elevation_service.exe` DACL and copies itself\nto the location to escalate privileges. An attacker is able to still take over any file that is not in use (locked), which is outside the scope of this rule.\n\n#### Possible investigation steps:\n\n- Check for the digital signature of the executable.\n- Look for additional processes spawned by the process, command lines, and network communications.\n- Look for additional alerts involving the host and the user.\n\n### False Positive Analysis\n\n- Verify whether the digital signature exists in the executable, and if it is valid.\n\n### Related Rules\n\n- Suspicious DLL Loaded for Persistence or Privilege Escalation - bfeaf89b-a2a7-48a3-817f-e41829dc61ee\n\n### Response and Remediation\n\n- Immediate response should be taken to validate activity, investigate, and potentially isolate activity to prevent further\npost-compromise behavior.\n", + "query": "/* This rule is compatible with both Sysmon and Elastic Endpoint */\n\nprocess where event.type == \"start\" and \n (process.Ext.token.integrity_level_name : \"System\" or\n winlog.event_data.IntegrityLevel : \"System\") and\n (\n (process.name : \"elevation_service.exe\" and \n not process.pe.original_file_name == \"elevation_service.exe\") or\n\n (process.parent.name : \"elevation_service.exe\" and \n process.name : (\"rundll32.exe\", \"cmd.exe\", \"powershell.exe\")) \n )\n", "references": [ "https://github.com/klinix5/InstallerFileTakeOver" ], @@ -46,5 +46,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_lsa_auth_package.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_lsa_auth_package.json index ef92d2179a60c..9b5ae8b997b74 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_lsa_auth_package.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_lsa_auth_package.json @@ -5,9 +5,7 @@ "description": "Adversaries can use the autostart mechanism provided by the Local Security Authority (LSA) authentication packages for privilege escalation or persistence by placing a reference to a binary in the Windows registry. The binary will then be executed by SYSTEM when the authentication packages are loaded.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -71,5 +69,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_new_or_modified_federation_domain.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_new_or_modified_federation_domain.json index 2a1231e96d8a5..c808635f20fb7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_new_or_modified_federation_domain.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_new_or_modified_federation_domain.json @@ -10,7 +10,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "New or Modified Federation Domain", - "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "note": "## Config\n\nThe Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Set-AcceptedDomain\" or \n\"Set-MsolDomainFederationSettings\" or \"Add-FederatedDomain\" or \"New-AcceptedDomain\" or \"Remove-AcceptedDomain\" or \"Remove-FederatedDomain\") and \nevent.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-accepteddomain?view=exchange-ps", @@ -57,5 +57,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_pkexec_envar_hijack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_pkexec_envar_hijack.json new file mode 100644 index 0000000000000..402876ab4ccf7 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_pkexec_envar_hijack.json @@ -0,0 +1,70 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies attempt to exploit a local privilege escalation in polkit pkexec (CVE-2021-4034) via unsecure environment variable injection. Successful exploitation allows an unprivileged user to escalate to the root user.", + "from": "now-9m", + "index": [ + "logs-endpoint.events.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Potential Privilege Escalation via PKEXEC", + "query": "file where file.path : \"/*GCONV_PATH*\"\n", + "references": [ + "https://seclists.org/oss-sec/2022/q1/80", + "https://haxx.in/files/blasty-vs-pkexec.c" + ], + "risk_score": 73, + "rule_id": "8da41fc9-7735-4b24-9cc6-c78dfc9fc9c9", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Linux", + "Threat Detection", + "Privilege Escalation" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1068", + "name": "Exploitation for Privilege Escalation", + "reference": "https://attack.mitre.org/techniques/T1068/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1574", + "name": "Hijack Execution Flow", + "reference": "https://attack.mitre.org/techniques/T1574/", + "subtechnique": [ + { + "id": "T1574.007", + "name": "Path Interception by PATH Environment Variable", + "reference": "https://attack.mitre.org/techniques/T1574/007/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_port_monitor_print_pocessor_abuse.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_port_monitor_print_pocessor_abuse.json index aa9f0c21ec272..0eb2a7e01a1d1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_port_monitor_print_pocessor_abuse.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_port_monitor_print_pocessor_abuse.json @@ -5,14 +5,12 @@ "description": "Identifies port monitor and print processor registry modifications. Adversaries may abuse port monitor and print processors to run malicious DLLs during system boot that will be executed as SYSTEM for privilege escalation and/or persistence, if permissions allow writing a fully-qualified pathname for that DLL.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", "name": "Potential Port Monitor or Print Processor Registration Abuse", - "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path : (\"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Print\\\\Monitors\\\\*\",\n \"HLLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Print\\\\Environments\\\\Windows*\\\\Print Processors\\\\*\") and\n registry.data.strings : \"*.dll\" and\n /* exclude SYSTEM SID - look for changes by non-SYSTEM user */\n not user.id : \"S-1-5-18\"\n", + "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path : (\"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Print\\\\Monitors\\\\*\",\n \"HKLM\\\\SYSTEM\\\\*ControlSet*\\\\Control\\\\Print\\\\Environments\\\\Windows*\\\\Print Processors\\\\*\") and\n registry.data.strings : \"*.dll\" and\n /* exclude SYSTEM SID - look for changes by non-SYSTEM user */\n not user.id : \"S-1-5-18\"\n", "references": [ "https://www.welivesecurity.com/2020/05/21/no-game-over-winnti-group/" ], @@ -74,5 +72,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_malicious_registry_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_malicious_registry_modification.json index c0ebdf3cac6b3..7f76c27f369af 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_malicious_registry_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_malicious_registry_modification.json @@ -5,8 +5,7 @@ "description": "Detects attempts to exploit privilege escalation vulnerabilities related to the Print Spooler service. For more information refer to CVE-2021-34527 and verify that the impacted system is investigated.", "from": "now-9m", "index": [ - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -45,5 +44,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_registry_copyfiles.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_registry_copyfiles.json index 2f7ea1a1869e1..3d84e33c83791 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_registry_copyfiles.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_registry_copyfiles.json @@ -5,9 +5,7 @@ "description": "Detects attempts to exploit a privilege escalation vulnerability (CVE-2020-1030) related to the print spooler service. Exploitation involves chaining multiple primitives to load an arbitrary DLL into the print spooler process running as SYSTEM.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -46,5 +44,5 @@ } ], "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_rogue_windir_environment_var.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_rogue_windir_environment_var.json index c07f9aa3467d1..d94fdbc846847 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_rogue_windir_environment_var.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_rogue_windir_environment_var.json @@ -5,9 +5,7 @@ "description": "Identifies a privilege escalation attempt via a rogue Windows directory (Windir) environment variable. This is a known primitive that is often combined with other vulnerabilities to elevate privileges.", "from": "now-9m", "index": [ - "winlogbeat-*", - "logs-endpoint.events.*", - "logs-windows.*" + "logs-endpoint.events.*" ], "language": "eql", "license": "Elastic License v2", @@ -52,5 +50,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_samaccountname_spoofing_attack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_samaccountname_spoofing_attack.json new file mode 100644 index 0000000000000..b84b434e1d221 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_samaccountname_spoofing_attack.json @@ -0,0 +1,75 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies a suspicious computer account name rename event, which may indicate an attempt to exploit CVE-2021-42278 to elevate privileges from a standard domain user to a user with domain admin privileges. CVE-2021-42278 is a security vulnerability that allows potential attackers to impersonate a domain controller via samAccountName attribute spoofing.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Potential Privileged Escalation via SamAccountName Spoofing", + "query": "iam where event.action == \"renamed-user-account\" and\n /* machine account name renamed to user like account name */\n winlog.event_data.OldTargetUserName : \"*$\" and not winlog.event_data.NewTargetUserName : \"*$\"\n", + "references": [ + "https://support.microsoft.com/en-us/topic/kb5008102-active-directory-security-accounts-manager-hardening-changes-cve-2021-42278-5975b463-4c95-45e1-831a-d120004e258e", + "https://cloudbrothers.info/en/exploit-kerberos-samaccountname-spoofing/", + "https://github.com/cube0x0/noPac", + "https://twitter.com/exploitph/status/1469157138928914432", + "https://exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.html" + ], + "risk_score": 73, + "rule_id": "bdcf646b-08d4-492c-870a-6c04e3700034", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Persistence", + "Privilege Escalation" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1078", + "name": "Valid Accounts", + "reference": "https://attack.mitre.org/techniques/T1078/", + "subtechnique": [ + { + "id": "T1078.002", + "name": "Domain Accounts", + "reference": "https://attack.mitre.org/techniques/T1078/002/" + } + ] + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1098", + "name": "Account Manipulation", + "reference": "https://attack.mitre.org/techniques/T1098/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json index 37fcef44719af..4688d4cb79b81 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json @@ -4,7 +4,7 @@ ], "description": "Identifies the use of AssumeRole. AssumeRole returns a set of temporary security credentials that can be used to access AWS resources. An adversary could use those credentials to move laterally and escalate privileges.", "false_positives": [ - "Automated processes that uses Terraform may lead to false positives." + "Automated processes that use Terraform may lead to false positives." ], "index": [ "filebeat-*", @@ -70,5 +70,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_printspooler_childprocess.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_printspooler_childprocess.json index 10115d932fc07..17b5df39f8835 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_printspooler_childprocess.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_printspooler_childprocess.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Unusual Print Spooler Child Process", - "query": "process where event.type == \"start\" and\n process.parent.name : \"spoolsv.exe\" and user.id : \"S-1-5-18\" and\n\n /* exclusions for FP control below */\n not process.name : (\"splwow64.exe\", \"PDFCreator.exe\", \"acrodist.exe\", \"spoolsv.exe\", \"msiexec.exe\", \"route.exe\", \"WerFault.exe\") and\n not process.command_line : \"*\\\\WINDOWS\\\\system32\\\\spool\\\\DRIVERS*\" and\n not (process.name : \"net.exe\" and process.command_line : (\"*stop*\", \"*start*\")) and\n not (process.name : (\"cmd.exe\", \"powershell.exe\") and process.command_line : (\"*.spl*\", \"*\\\\program files*\", \"*route add*\")) and\n not (process.name : \"netsh.exe\" and process.command_line : (\"*add portopening*\", \"*rule name*\")) and\n not (process.name : \"regsvr32.exe\" and process.command_line : \"*PrintConfig.dll*\")\n", + "query": "process where event.type == \"start\" and\n process.parent.name : \"spoolsv.exe\" and\n (process.Ext.token.integrity_level_name : \"System\" or\n winlog.event_data.IntegrityLevel : \"System\") and\n\n /* exclusions for FP control below */\n not process.name : (\"splwow64.exe\", \"PDFCreator.exe\", \"acrodist.exe\", \"spoolsv.exe\", \"msiexec.exe\", \"route.exe\", \"WerFault.exe\") and\n not process.command_line : \"*\\\\WINDOWS\\\\system32\\\\spool\\\\DRIVERS*\" and\n not (process.name : \"net.exe\" and process.command_line : (\"*stop*\", \"*start*\")) and\n not (process.name : (\"cmd.exe\", \"powershell.exe\") and process.command_line : (\"*.spl*\", \"*\\\\program files*\", \"*route add*\")) and\n not (process.name : \"netsh.exe\" and process.command_line : (\"*add portopening*\", \"*rule name*\")) and\n not (process.name : \"regsvr32.exe\" and process.command_line : \"*PrintConfig.dll*\")\n", "references": [ "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34527", "https://github.com/afwu/PrintNightmare" @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_windows_service_via_unusual_client.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_windows_service_via_unusual_client.json new file mode 100644 index 0000000000000..469b1a4e9096f --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_windows_service_via_unusual_client.json @@ -0,0 +1,58 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies the creation of a Windows service by an unusual client process. Services may be created with administrator privileges but are executed under SYSTEM privileges, so an adversary may also use a service to escalate privileges from administrator to SYSTEM.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-system.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Windows Service Installed via an Unusual Client", + "note": "## Config\n\nThe 'Audit Security System Extension' logging policy must be configured for (Success)\nSteps to implement the logging policy with with Advanced Audit Configuration:\n\n```\nComputer Configuration > \nPolicies > \nWindows Settings > \nSecurity Settings > \nAdvanced Audit Policies Configuration > \nAudit Policies > \nSystem > \nAudit Security System Extension (Success)\n```\n", + "query": "event.action:\"service-installed\" and (winlog.event_data.ClientProcessId:\"0\" or winlog.event_data.ParentProcessId:\"0\")\n", + "references": [ + "https://www.x86matthew.com/view_post?id=create_svc_rpc", + "https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4697", + "https://github.com/atc-project/atomic-threat-coverage/blob/master/Atomic_Threat_Coverage/Logging_Policies/LP_0100_windows_audit_security_system_extension.md" + ], + "risk_score": 73, + "rule_id": "55c2bf58-2a39-4c58-a384-c8b1978153c2", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Privilege Escalation" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1543", + "name": "Create or Modify System Process", + "reference": "https://attack.mitre.org/techniques/T1543/", + "subtechnique": [ + { + "id": "T1543.003", + "name": "Windows Service", + "reference": "https://attack.mitre.org/techniques/T1543/003/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_filebeat8x.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_filebeat8x.json index 426e37c3e904c..a4d5c9b315e0d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_filebeat8x.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_filebeat8x.json @@ -16,7 +16,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Threat Intel Filebeat Module (v8.x) Indicator Match", - "note": "## Triage and Analysis\n\n### Investigating Threat Intel Indicator Matches\n\nThreat Intel indicator match rules allow matching from a local observation such as an endpoint event that records a file\nhash with an entry of a file hash stored within the Threat Intel integrations. Other examples of matches can occur on\nan IP address, registry path, URL and imphash.\n\nThe matches will be based on the incoming last 30 days feed data so it's important to validate the data and review the results by\ninvestigating the associated activity to determine if it requires further investigation.\n\nIf an indicator matches a local observation, the following enriched fields will be generated to identify the indicator, field, and type matched.\n\n- `threat.indicator.matched.atomic` - this identifies the atomic indicator that matched the local observation\n- `threat.indicator.matched.field` - this identifies the indicator field that matched the local observation\n- `threat.indicator.matched.type` - this identifies the indicator type that matched the local observation\n\n#### Possible investigation steps:\n- Investigation should be validated and reviewed based on the data (file hash, registry path, URL, imphash) that was matched\nand viewing the source of that activity.\n- Consider the history of the indicator that was matched. Has it happened before? Is it happening on multiple machines?\nThese kinds of questions can help understand if the activity is related to legitimate behavior.\n- Consider the user and their role within the company, is this something related to their job or work function?\n\n### False Positive Analysis\n- For any matches found, it's important to consider the initial release date of that indicator. Threat intelligence can\nbe a great tool for augmenting existing security processes, while at the same time it should be understood that threat\nintelligence can represent a specific set of activity observed at a point in time. For example, an IP address\nmay have hosted malware observed in a Dridex campaign month ago, but it's possible that IP has been remediated and\nno longer represents any threat.\n- Adversaries often use legitimate tools as network administrators such as `PsExec` or `AdFind`, these tools often find their\nway into indicator lists creating the potential for false positives.\n- It's possible after large and publicly written campaigns, curious employees might end up going directly to attacker infrastructure and generating these rules\n\n### Response and Remediation\n- If suspicious or malicious behavior is observed, immediate response should be taken to isolate activity to prevent further\npost-compromise behavior.\n- One example of a response if a machine matched a command and control IP address would be to add an entry to a network\ndevice such as a firewall or proxy appliance to prevent any outbound activity from leaving that machine.\n- Another example of a response with a malicious file hash match would involve validating if the file was properly quarantined,\nreview current running processes looking for any abnormal activity, and investigating for any other follow-up actions such as persistence or lateral movement\n", + "note": "## Triage and Analysis\n\n### Investigating Threat Intel Indicator Matches\n\nThreat Intel indicator match rules allow matching from a local observation such as an endpoint event that records a file\nhash with an entry of a file hash stored within the Threat Intel integrations. Matches can also occur on\nan IP address, registry path, URL, or imphash.\n\nThe matches will be based on the incoming last 30 days feed data so it's important to validate the data and review the results by\ninvestigating the associated activity to determine if it requires further investigation.\n\nIf an indicator matches a local observation, the following enriched fields will be generated to identify the indicator, field, and type matched.\n\n- `threat.indicator.matched.atomic` - this identifies the atomic indicator that matched the local observation\n- `threat.indicator.matched.field` - this identifies the indicator field that matched the local observation\n- `threat.indicator.matched.type` - this identifies the indicator type that matched the local observation\n\n#### Possible investigation steps:\n- Investigation should be validated and reviewed based on the data (file hash, registry path, URL, imphash) that was matched\nand by viewing the source of that activity.\n- Consider the history of the indicator that was matched. Has it happened before? Is it happening on multiple machines?\nThese kinds of questions can help understand if the activity is related to legitimate behavior.\n- Consider the user and their role within the company: is this something related to their job or work function?\n\n### False Positive Analysis\n- For any matches found, it's important to consider the initial release date of that indicator. Threat intelligence can\nbe a great tool for augmenting existing security processes, while at the same time it should be understood that threat\nintelligence can represent a specific set of activity observed at a point in time. For example, an IP address\nmay have hosted malware observed in a Dridex campaign months ago, but it's possible that IP has been remediated and\nno longer represents any threat.\n- Adversaries often use legitimate tools as network administrators such as `PsExec` or `AdFind`; these tools often find their\nway into indicator lists creating the potential for false positives.\n- It's possible after large and publicly written campaigns, curious employees might end up going directly to attacker infrastructure and triggering these rules.\n\n### Response and Remediation\n- If suspicious or malicious behavior is observed, take immediate action to isolate activity to prevent further\npost-compromise behavior.\n- One example of a response if a machine matched a command and control IP address would be to add an entry to a network\ndevice such as a firewall or proxy appliance to prevent any outbound activity from leaving that machine.\n- Another example of a response with a malicious file hash match would involve validating if the file was properly quarantined,\nreviewing current running processes for any abnormal activity, and investigating for any other follow-up actions such as persistence or lateral movement.\n", "query": "file.hash.*:* or file.pe.imphash:* or source.ip:* or destination.ip:* or url.full:* or registry.path:*\n", "references": [ "https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-threatintel.html" @@ -40,16 +40,16 @@ }, "meta": { "disabled": false, - "key": "event.dataset", + "key": "event.module", "negate": false, "params": { - "query": "ti_*" + "query": "threatintel" }, "type": "phrase" }, "query": { "match_phrase": { - "event.dataset": "ti_*" + "event.module": "threatintel" } } }, @@ -190,9 +190,9 @@ ] } ], - "threat_query": "@timestamp >= \"now-30d\" and event.dataset:ti_* and (threat.indicator.file.hash.*:* or threat.indicator.file.pe.imphash:* or threat.indicator.ip:* or threat.indicator.registry.path:* or threat.indicator.url.full:*)", + "threat_query": "@timestamp >= \"now-30d/d\" and event.module:threatintel and (threat.indicator.file.hash.*:* or threat.indicator.file.pe.imphash:* or threat.indicator.ip:* or threat.indicator.registry.path:* or threat.indicator.url.full:*)", "timeline_id": "495ad7a7-316e-4544-8a0f-9c098daee76e", "timeline_title": "Generic Threat Match Timeline", "type": "threat_match", - "version": 1 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_fleet_integrations.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_fleet_integrations.json index 21f1029f4c8aa..2612a8139e30e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_fleet_integrations.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_fleet_integrations.json @@ -2,7 +2,7 @@ "author": [ "Elastic" ], - "description": "This rule is triggered when indicators from the Threat Intel integrations has a match against local file or network observations.", + "description": "This rule is triggered when indicators from the Threat Intel integrations have a match against local file or network observations.", "from": "now-65m", "index": [ "auditbeat-*", @@ -16,7 +16,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Threat Intel Indicator Match", - "note": "## Triage and Analysis\n\n### Investigating Threat Intel Indicator Matches\n\nThreat Intel indicator match rules allow matching from a local observation such as an endpoint event that records a file\nhash with an entry of a file hash stored within the Threat Intel integrations. Other examples of matches can occur on\nan IP address, registry path, URL and imphash.\n\nThe matches will be based on the incoming last 30 days feed data so it's important to validate the data and review the results by\ninvestigating the associated activity to determine if it requires further investigation.\n\nIf an indicator matches a local observation, the following enriched fields will be generated to identify the indicator, field, and type matched.\n\n- `threat.indicator.matched.atomic` - this identifies the atomic indicator that matched the local observation\n- `threat.indicator.matched.field` - this identifies the indicator field that matched the local observation\n- `threat.indicator.matched.type` - this identifies the indicator type that matched the local observation\n\n#### Possible investigation steps:\n- Investigation should be validated and reviewed based on the data (file hash, registry path, URL, imphash) that was matched\nand viewing the source of that activity.\n- Consider the history of the indicator that was matched. Has it happened before? Is it happening on multiple machines?\nThese kinds of questions can help understand if the activity is related to legitimate behavior.\n- Consider the user and their role within the company, is this something related to their job or work function?\n\n### False Positive Analysis\n- For any matches found, it's important to consider the initial release date of that indicator. Threat intelligence can\nbe a great tool for augmenting existing security processes, while at the same time it should be understood that threat\nintelligence can represent a specific set of activity observed at a point in time. For example, an IP address\nmay have hosted malware observed in a Dridex campaign month ago, but it's possible that IP has been remediated and\nno longer represents any threat.\n- Adversaries often use legitimate tools as network administrators such as `PsExec` or `AdFind`, these tools often find their\nway into indicator lists creating the potential for false positives.\n- It's possible after large and publicly written campaigns, curious employees might end up going directly to attacker infrastructure and generating these rules\n\n### Response and Remediation\n- If suspicious or malicious behavior is observed, immediate response should be taken to isolate activity to prevent further\npost-compromise behavior.\n- One example of a response if a machine matched a command and control IP address would be to add an entry to a network\ndevice such as a firewall or proxy appliance to prevent any outbound activity from leaving that machine.\n- Another example of a response with a malicious file hash match would involve validating if the file was properly quarantined,\nreview current running processes looking for any abnormal activity, and investigating for any other follow-up actions such as persistence or lateral movement\n", + "note": "## Triage and Analysis\n\n### Investigating Threat Intel Indicator Matches\n\nThreat Intel indicator match rules allow matching from a local observation such as an endpoint event that records a file\nhash with an entry of a file hash stored within the Threat Intel integrations. Matches can also occur on\nan IP address, registry path, URL, or imphash.\n\nThe matches will be based on the incoming last 30 days feed data so it's important to validate the data and review the results by\ninvestigating the associated activity to determine if it requires further investigation.\n\nIf an indicator matches a local observation, the following enriched fields will be generated to identify the indicator, field, and type matched.\n\n- `threat.indicator.matched.atomic` - this identifies the atomic indicator that matched the local observation\n- `threat.indicator.matched.field` - this identifies the indicator field that matched the local observation\n- `threat.indicator.matched.type` - this identifies the indicator type that matched the local observation\n\n#### Possible investigation steps:\n- Investigation should be validated and reviewed based on the data (file hash, registry path, URL, imphash) that was matched\nand by viewing the source of that activity.\n- Consider the history of the indicator that was matched. Has it happened before? Is it happening on multiple machines?\nThese kinds of questions can help understand if the activity is related to legitimate behavior.\n- Consider the user and their role within the company: is this something related to their job or work function?\n\n### False Positive Analysis\n- For any matches found, it's important to consider the initial release date of that indicator. Threat intelligence can\nbe a great tool for augmenting existing security processes, while at the same time it should be understood that threat\nintelligence can represent a specific set of activity observed at a point in time. For example, an IP address\nmay have hosted malware observed in a Dridex campaign months ago, but it's possible that IP has been remediated and\nno longer represents any threat.\n- Adversaries often use legitimate tools as network administrators such as `PsExec` or `AdFind`; these tools often find their\nway into indicator lists creating the potential for false positives.\n- It's possible after large and publicly written campaigns, curious employees might end up going directly to attacker infrastructure and triggering these rules.\n\n### Response and Remediation\n- If suspicious or malicious behavior is observed, take immediate action to isolate activity to prevent further\npost-compromise behavior.\n- One example of a response if a machine matched a command and control IP address would be to add an entry to a network\ndevice such as a firewall or proxy appliance to prevent any outbound activity from leaving that machine.\n- Another example of a response with a malicious file hash match would involve validating if the file was properly quarantined,\nreviewing current running processes for any abnormal activity, and investigating for any other follow-up actions such as persistence or lateral movement.\n", "query": "file.hash.*:* or file.pe.imphash:* or source.ip:* or destination.ip:* or url.full:* or registry.path:*\n", "references": [ "https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-threatintel.html" @@ -190,9 +190,9 @@ ] } ], - "threat_query": "@timestamp >= \"now-30d\" and event.dataset:ti_* and (threat.indicator.file.hash.*:* or threat.indicator.file.pe.imphash:* or threat.indicator.ip:* or threat.indicator.registry.path:* or threat.indicator.url.full:*)", + "threat_query": "@timestamp >= \"now-30d/d\" and event.dataset:ti_* and (threat.indicator.file.hash.*:* or threat.indicator.file.pe.imphash:* or threat.indicator.ip:* or threat.indicator.registry.path:* or threat.indicator.url.full:*)", "timeline_id": "495ad7a7-316e-4544-8a0f-9c098daee76e", "timeline_title": "Generic Threat Match Timeline", "type": "threat_match", - "version": 1 + "version": 3 } From d0135481a85fd9225c507560f9c219fbc3f111d6 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 14:17:41 -0700 Subject: [PATCH 033/104] unify skipped suites for es promotion (#125851) --- .../security_and_spaces/tests/create_ml.ts | 3 ++- .../test/rule_registry/spaces_only/tests/trial/create_rule.ts | 2 +- .../spaces_only/tests/trial/lifecycle_executor.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts index 343db03c2ae27..e2ce3922f2d3f 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts @@ -92,7 +92,8 @@ export default ({ getService }: FtrProviderContext) => { return body; } - describe('Generating signals from ml anomalies', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('Generating signals from ml anomalies', () => { before(async () => { // Order is critical here: auditbeat data must be loaded before attempting to start the ML job, // as the job looks for certain indices on start diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts index 5d0e73f6f07a5..4df3ff6b20649 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/create_rule.ts @@ -39,7 +39,7 @@ const SPACE_ID = 'space1'; export default function registryRulesApiTest({ getService }: FtrProviderContext) { const es = getService('es'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125848 + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 describe.skip('Rule Registry API', () => { describe('with write permissions', () => { it('does not bootstrap indices on plugin startup', async () => { diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts index 281be665301d6..8fabaf9151d53 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts @@ -59,7 +59,7 @@ export default function createLifecycleExecutorApiTest({ getService }: FtrProvid return Promise.resolve(client); }; - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125848 + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 describe.skip('createLifecycleExecutor', () => { let ruleDataClient: IRuleDataClient; before(async () => { From 0a850d87e98aedf7806a707f5f747b3736b467fd Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 15:12:34 -0700 Subject: [PATCH 034/104] skip more suits failing es promotion (#125851) --- .../security_and_spaces/tests/create_threat_matching.ts | 3 ++- x-pack/test/security_solution_endpoint/apps/endpoint/index.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts index 346998e7af261..b5b232f70ec89 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts @@ -69,7 +69,8 @@ export default ({ getService }: FtrProviderContext) => { /** * Specific api integration tests for threat matching rule type */ - describe('create_threat_matching', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('create_threat_matching', () => { describe('creating threat match rule', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index 70d60ba5c1b67..4aeaf7fa9ff63 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -15,7 +15,8 @@ import { export default function (providerContext: FtrProviderContext) { const { loadTestFile, getService } = providerContext; - describe('endpoint', function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('endpoint', function () { const ingestManager = getService('ingestManager'); const log = getService('log'); const endpointTestResources = getService('endpointTestResources'); From 60722f6260a95ce14be8f8699186fa36c6c3dfda Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 16:05:20 -0700 Subject: [PATCH 035/104] skip suite failing es promotion (#125881) --- .../apps/uptime/synthetics_integration.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts b/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts index dd8afd4d414a6..1cf32b4abf040 100644 --- a/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts +++ b/x-pack/test/functional_synthetics/apps/uptime/synthetics_integration.ts @@ -131,7 +131,8 @@ export default function (providerContext: FtrProviderContext) { type: `synthetics/${monitorType}`, use_output: 'default', }); - describe('When on the Synthetics Integration Policy Create Page', function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125881 + describe.skip('When on the Synthetics Integration Policy Create Page', function () { skipIfNoDockerRegistry(providerContext); const basicConfig = { name: monitorName, From c115547186d5da046d8b693b019a2f7a52ff753f Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 16:08:41 -0700 Subject: [PATCH 036/104] skip another suite failing es promotion (#125851) --- .../security_and_spaces/tests/create_exceptions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_exceptions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_exceptions.ts index 0dfc753be402c..818ba3b366e40 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_exceptions.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_exceptions.ts @@ -63,7 +63,8 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); const es = getService('es'); - describe('create_rules_with_exceptions', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('create_rules_with_exceptions', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); }); From f64a0d64bde527c41ffade8e861a2457770cc4b7 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 16:37:29 -0700 Subject: [PATCH 037/104] skip another security solution suite blocking es promotion (#125851) --- .../security_and_spaces/tests/generating_signals.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts index f9c4a1bac9d24..761792e29ea1d 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts @@ -71,7 +71,8 @@ export default ({ getService }: FtrProviderContext) => { const es = getService('es'); const log = getService('log'); - describe('Generating signals from source indexes', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('Generating signals from source indexes', () => { beforeEach(async () => { await deleteSignalsIndex(supertest, log); await createSignalsIndex(supertest, log); From 104d1197d47169ade04de48c0ff47291908363aa Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 16:38:32 -0700 Subject: [PATCH 038/104] skip another security solution suite blocking es promotion (#125851) --- .../test/security_solution_endpoint_api_int/apis/metadata.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts index 86c8e32f3bdf9..4eee8cd3d3bd7 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts @@ -37,7 +37,8 @@ export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const endpointTestResources = getService('endpointTestResources'); - describe('test metadata apis', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('test metadata apis', () => { before(async () => { await endpointTestResources.setMetadataTransformFrequency('1s'); }); From 98a0e183d8c6fe7a3786ddcb86b77adb748cabbd Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 17:08:53 -0700 Subject: [PATCH 039/104] skip another security solution suite blocking es promotion (#125851) --- .../security_solution_endpoint_api_int/apis/endpoint_authz.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts index 1b9ce8911c5bf..ccd50f447e010 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts @@ -18,7 +18,8 @@ export default function ({ getService }: FtrProviderContext) { const endpointTestResources = getService('endpointTestResources'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - describe('When attempting to call an endpoint api with no authz', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('When attempting to call an endpoint api with no authz', () => { let loadedData: IndexedHostsAndAlertsResponse; before(async () => { From 889c68add129ad92e1973c64b25a589bbdd9a6a7 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 17:32:59 -0700 Subject: [PATCH 040/104] skip another security solution suite blocking es promotion (#125851) --- .../apis/endpoint_artifacts/trusted_apps.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/trusted_apps.ts b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/trusted_apps.ts index 7caf4f085694a..3425bc7deea98 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/trusted_apps.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/trusted_apps.ts @@ -25,7 +25,8 @@ export default function ({ getService }: FtrProviderContext) { const endpointPolicyTestResources = getService('endpointPolicyTestResources'); const endpointArtifactTestResources = getService('endpointArtifactTestResources'); - describe('Endpoint artifacts (via lists plugin): Trusted Applications', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('Endpoint artifacts (via lists plugin): Trusted Applications', () => { let fleetEndpointPolicy: PolicyTestResourceInfo; before(async () => { From 485ab50302247984a239b07d07fdfc5b86dc03b9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 16 Feb 2022 18:08:25 -0700 Subject: [PATCH 041/104] [maps] fix Dashboards with by-value maps are broken when copied to new space (#125599) * extract and inject * add unit tests * simplify tests * add extract and inject to server map embeddable * add dashboard migration * do not add embeddable prefix * eslint * remove embeddable migration from dashboard and put in maps * clean up comment * fix jest test * remove 7.17 migration and harden inject method * clean-up test * clean up comment grammer Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../maps/common/embeddable/extract.test.ts | 49 ++++++++++++++++++ .../plugins/maps/common/embeddable/extract.ts | 34 +++++++++++++ .../plugins/maps/common/embeddable/index.ts | 9 ++++ .../maps/common/embeddable/inject.test.ts | 51 +++++++++++++++++++ .../plugins/maps/common/embeddable/inject.ts | 44 ++++++++++++++++ .../plugins/maps/common/embeddable/types.ts | 13 +++++ .../embeddable/map_embeddable_factory.ts | 19 ++----- .../maps/server/embeddable_migrations.test.ts | 5 +- .../maps/server/embeddable_migrations.ts | 26 +++++++--- x-pack/plugins/maps/server/plugin.ts | 3 ++ 10 files changed, 231 insertions(+), 22 deletions(-) create mode 100644 x-pack/plugins/maps/common/embeddable/extract.test.ts create mode 100644 x-pack/plugins/maps/common/embeddable/extract.ts create mode 100644 x-pack/plugins/maps/common/embeddable/index.ts create mode 100644 x-pack/plugins/maps/common/embeddable/inject.test.ts create mode 100644 x-pack/plugins/maps/common/embeddable/inject.ts create mode 100644 x-pack/plugins/maps/common/embeddable/types.ts diff --git a/x-pack/plugins/maps/common/embeddable/extract.test.ts b/x-pack/plugins/maps/common/embeddable/extract.test.ts new file mode 100644 index 0000000000000..b7440d5f4a098 --- /dev/null +++ b/x-pack/plugins/maps/common/embeddable/extract.test.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { extract } from './extract'; + +test('Should return original state and empty references with by-reference embeddable state', () => { + const mapByReferenceInput = { + id: '2192e502-0ec7-4316-82fb-c9bbf78525c4', + type: 'map', + }; + + expect(extract!(mapByReferenceInput)).toEqual({ + state: mapByReferenceInput, + references: [], + }); +}); + +test('Should update state with refNames with by-value embeddable state', () => { + const mapByValueInput = { + id: '8d62c3f0-c61f-4c09-ac24-9b8ee4320e20', + attributes: { + layerListJSON: + '[{"sourceDescriptor":{"indexPatternId":"90943e30-9a47-11e8-b64d-95841ca0b247"}}]', + }, + type: 'map', + }; + + expect(extract!(mapByValueInput)).toEqual({ + references: [ + { + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + name: 'layer_0_source_index_pattern', + type: 'index-pattern', + }, + ], + state: { + id: '8d62c3f0-c61f-4c09-ac24-9b8ee4320e20', + attributes: { + layerListJSON: + '[{"sourceDescriptor":{"indexPatternRefName":"layer_0_source_index_pattern"}}]', + }, + type: 'map', + }, + }); +}); diff --git a/x-pack/plugins/maps/common/embeddable/extract.ts b/x-pack/plugins/maps/common/embeddable/extract.ts new file mode 100644 index 0000000000000..54cbefadaaede --- /dev/null +++ b/x-pack/plugins/maps/common/embeddable/extract.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EmbeddableRegistryDefinition } from 'src/plugins/embeddable/server'; +import { MapEmbeddablePersistableState } from './types'; +import { MapSavedObjectAttributes } from '../map_saved_object_type'; +import { extractReferences } from '../migrations/references'; + +export const extract: EmbeddableRegistryDefinition['extract'] = (state) => { + const typedState = state as MapEmbeddablePersistableState; + + // by-reference embeddable + if (!('attributes' in typedState) || typedState.attributes === undefined) { + // No references to extract for by-reference embeddable since all references are stored with by-reference saved object + return { state, references: [] }; + } + + // by-value embeddable + const { attributes, references } = extractReferences({ + attributes: typedState.attributes as MapSavedObjectAttributes, + }); + + return { + state: { + ...state, + attributes, + }, + references, + }; +}; diff --git a/x-pack/plugins/maps/common/embeddable/index.ts b/x-pack/plugins/maps/common/embeddable/index.ts new file mode 100644 index 0000000000000..16577df879fbc --- /dev/null +++ b/x-pack/plugins/maps/common/embeddable/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { extract } from './extract'; +export { inject } from './inject'; diff --git a/x-pack/plugins/maps/common/embeddable/inject.test.ts b/x-pack/plugins/maps/common/embeddable/inject.test.ts new file mode 100644 index 0000000000000..2a9a162c948dd --- /dev/null +++ b/x-pack/plugins/maps/common/embeddable/inject.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { inject } from './inject'; + +test('Should return original state with by-reference embeddable state', () => { + const mapByReferenceInput = { + id: '2192e502-0ec7-4316-82fb-c9bbf78525c4', + type: 'map', + }; + + const refernces = [ + { + name: 'panel_2192e502-0ec7-4316-82fb-c9bbf78525c4', + type: 'map', + id: '7f92d7d0-8e5f-11ec-9477-312c8a6de896', + }, + ]; + + expect(inject!(mapByReferenceInput, refernces)).toEqual(mapByReferenceInput); +}); + +test('Should inject refNames with by-value embeddable state', () => { + const mapByValueInput = { + id: '8d62c3f0-c61f-4c09-ac24-9b8ee4320e20', + attributes: { + layerListJSON: + '[{"sourceDescriptor":{"indexPatternRefName":"layer_0_source_index_pattern"}}]', + }, + type: 'map', + }; + const refernces = [ + { + name: 'layer_0_source_index_pattern', + type: 'index-pattern', + id: 'changed_index_pattern_id', + }, + ]; + + expect(inject!(mapByValueInput, refernces)).toEqual({ + id: '8d62c3f0-c61f-4c09-ac24-9b8ee4320e20', + attributes: { + layerListJSON: '[{"sourceDescriptor":{"indexPatternId":"changed_index_pattern_id"}}]', + }, + type: 'map', + }); +}); diff --git a/x-pack/plugins/maps/common/embeddable/inject.ts b/x-pack/plugins/maps/common/embeddable/inject.ts new file mode 100644 index 0000000000000..d8d5da2568df9 --- /dev/null +++ b/x-pack/plugins/maps/common/embeddable/inject.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EmbeddableRegistryDefinition } from 'src/plugins/embeddable/server'; +import { MapEmbeddablePersistableState } from './types'; +import { MapSavedObjectAttributes } from '../map_saved_object_type'; +import { extractReferences, injectReferences } from '../migrations/references'; + +export const inject: EmbeddableRegistryDefinition['inject'] = (state, references) => { + const typedState = state as MapEmbeddablePersistableState; + + // by-reference embeddable + if (!('attributes' in typedState) || typedState.attributes === undefined) { + return typedState; + } + + // by-value embeddable + try { + // run embeddable state through extract logic to ensure any state with hard coded ids is replace with refNames + // refName generation will produce consistent values allowing inject logic to then replace refNames with current ids. + const { attributes: attributesWithNoHardCodedIds } = extractReferences({ + attributes: typedState.attributes as MapSavedObjectAttributes, + }); + + const { attributes: attributesWithInjectedIds } = injectReferences({ + attributes: attributesWithNoHardCodedIds, + references, + }); + return { + ...typedState, + attributes: attributesWithInjectedIds, + }; + } catch (error) { + // inject exception prevents entire dashboard from display + // Instead of throwing, swallow error and let dashboard display + // Errors will surface in map panel. Any layer that failed injection will surface the error in the legend + // Users can then manually edit map to resolve any problems. + return typedState; + } +}; diff --git a/x-pack/plugins/maps/common/embeddable/types.ts b/x-pack/plugins/maps/common/embeddable/types.ts new file mode 100644 index 0000000000000..5684ea83e0d54 --- /dev/null +++ b/x-pack/plugins/maps/common/embeddable/types.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SerializableRecord } from '@kbn/utility-types'; +import { EmbeddableStateWithType } from 'src/plugins/embeddable/common'; + +export type MapEmbeddablePersistableState = EmbeddableStateWithType & { + attributes: SerializableRecord; +}; diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts b/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts index a4ce76b702d13..4a2048fc40e63 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts @@ -6,16 +6,15 @@ */ import { i18n } from '@kbn/i18n'; -import { EmbeddableStateWithType } from 'src/plugins/embeddable/common'; import { EmbeddableFactoryDefinition, IContainer, } from '../../../../../src/plugins/embeddable/public'; import { MAP_SAVED_OBJECT_TYPE, APP_ICON } from '../../common/constants'; import { getMapEmbeddableDisplayName } from '../../common/i18n_getters'; -import { MapByReferenceInput, MapEmbeddableInput, MapByValueInput } from './types'; +import { extract, inject } from '../../common/embeddable'; +import { MapByReferenceInput, MapEmbeddableInput } from './types'; import { lazyLoadMapModules } from '../lazy_load_bundle'; -import { extractReferences } from '../../common/migrations/references'; export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { type = MAP_SAVED_OBJECT_TYPE; @@ -63,17 +62,7 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { ); }; - extract(state: EmbeddableStateWithType) { - const maybeMapByValueInput = state as EmbeddableStateWithType | MapByValueInput; + inject = inject; - if ((maybeMapByValueInput as MapByValueInput).attributes !== undefined) { - const { references } = extractReferences({ - attributes: (maybeMapByValueInput as MapByValueInput).attributes, - }); - - return { state, references }; - } - - return { state, references: [] }; - } + extract = extract; } diff --git a/x-pack/plugins/maps/server/embeddable_migrations.test.ts b/x-pack/plugins/maps/server/embeddable_migrations.test.ts index 306f716d5171d..4cf2642bb545c 100644 --- a/x-pack/plugins/maps/server/embeddable_migrations.test.ts +++ b/x-pack/plugins/maps/server/embeddable_migrations.test.ts @@ -15,7 +15,10 @@ describe('saved object migrations and embeddable migrations', () => { const savedObjectMigrationVersions = Object.keys(savedObjectMigrations).filter((version) => { return semverGte(version, '7.13.0'); }); - const embeddableMigrationVersions = Object.keys(embeddableMigrations); + const embeddableMigrationVersions = Object.keys(embeddableMigrations).filter((key) => { + // filter out embeddable only migration keys + return !['8.0.1'].includes(key); + }); expect(savedObjectMigrationVersions.sort()).toEqual(embeddableMigrationVersions.sort()); }); }); diff --git a/x-pack/plugins/maps/server/embeddable_migrations.ts b/x-pack/plugins/maps/server/embeddable_migrations.ts index f5356e5eb29a5..9c17889e0c33c 100644 --- a/x-pack/plugins/maps/server/embeddable_migrations.ts +++ b/x-pack/plugins/maps/server/embeddable_migrations.ts @@ -10,6 +10,7 @@ import { MapSavedObjectAttributes } from '../common/map_saved_object_type'; import { moveAttribution } from '../common/migrations/move_attribution'; import { setEmsTmsDefaultModes } from '../common/migrations/set_ems_tms_default_modes'; import { renameLayerTypes } from '../common/migrations/rename_layer_types'; +import { extractReferences } from '../common/migrations/references'; /* * Embeddables such as Maps, Lens, and Visualize can be embedded by value or by reference on a dashboard. @@ -26,8 +27,8 @@ export const embeddableMigrations = { attributes: moveAttribution(state as { attributes: MapSavedObjectAttributes }), } as SerializableRecord; } catch (e) { - // Do not fail migration for invalid layerListJSON - // Maps application can display invalid layerListJSON error when saved object is viewed + // Do not fail migration + // Maps application can display error when viewed return state; } }, @@ -38,8 +39,21 @@ export const embeddableMigrations = { attributes: setEmsTmsDefaultModes(state as { attributes: MapSavedObjectAttributes }), } as SerializableRecord; } catch (e) { - // Do not fail migration for invalid layerListJSON - // Maps application can display invalid layerListJSON error when saved object is viewed + // Do not fail migration + // Maps application can display error when viewed + return state; + } + }, + '8.0.1': (state: SerializableRecord) => { + try { + const { attributes } = extractReferences(state as { attributes: MapSavedObjectAttributes }); + return { + ...state, + attributes, + } as SerializableRecord; + } catch (e) { + // Do not fail migration + // Maps application can display error when viewed return state; } }, @@ -50,8 +64,8 @@ export const embeddableMigrations = { attributes: renameLayerTypes(state as { attributes: MapSavedObjectAttributes }), } as SerializableRecord; } catch (e) { - // Do not fail migration for invalid layerListJSON - // Maps application can display invalid layerListJSON error when saved object is viewed + // Do not fail migration + // Maps application can display error when viewed return state; } }, diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 48b3969043566..92d0f08fb51ab 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -22,6 +22,7 @@ import { getFlightsSavedObjects } from './sample_data/flights_saved_objects.js'; import { getWebLogsSavedObjects } from './sample_data/web_logs_saved_objects.js'; import { registerMapsUsageCollector } from './maps_telemetry/collectors/register'; import { APP_ID, APP_ICON, MAP_SAVED_OBJECT_TYPE, getFullPath } from '../common/constants'; +import { extract, inject } from '../common/embeddable'; import { mapSavedObjects, mapsTelemetrySavedObjects } from './saved_objects'; import { MapsXPackConfig } from '../config'; import { setStartServices } from './kibana_server_services'; @@ -198,6 +199,8 @@ export class MapsPlugin implements Plugin { plugins.embeddable.registerEmbeddableFactory({ id: MAP_SAVED_OBJECT_TYPE, migrations: embeddableMigrations, + inject, + extract, }); return { From 8f03c791e0fa44efad3111fd26aa1f6553c517db Mon Sep 17 00:00:00 2001 From: Madison Caldwell Date: Wed, 16 Feb 2022 22:08:56 -0500 Subject: [PATCH 042/104] [Security Solution][Upgrade] Add tag for disabled rules on upgrade (#125448) * Add tag for disabled rules on upgrade * Resiliency * Restore 8.0 AAD migration and add 8.0.1 migration for auto-disabled tags * Add integration test for migration Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/saved_objects/migrations.test.ts | 167 +++++++++++++-- .../server/saved_objects/migrations.ts | 32 +++ .../spaces_only/tests/alerting/migrations.ts | 36 +++- .../functional/es_archives/alerts/data.json | 191 ++++++++++++++++++ .../es_archives/alerts/mappings.json | 2 +- 5 files changed, 413 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts index 5e2d8efedbcb3..1d7d3d2a362a9 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts @@ -2063,31 +2063,172 @@ describe('successful migrations', () => { { params: { outputIndex: 'output-index', type: 'query' }, alertTypeId: 'not.siem.signals' }, true ); - expect(migration800(alert, migrationContext).attributes.alertTypeId).toEqual( - 'not.siem.signals' - ); - expect(migration800(alert, migrationContext).attributes.enabled).toEqual(true); - expect(migration800(alert, migrationContext).attributes.params.outputIndex).toEqual( - 'output-index' - ); + const migratedAlert = migration800(alert, migrationContext); + expect(migratedAlert.attributes.alertTypeId).toEqual('not.siem.signals'); + expect(migratedAlert.attributes.enabled).toEqual(true); + expect(migratedAlert.attributes.tags).toEqual(['foo']); + expect(migratedAlert.attributes.params.outputIndex).toEqual('output-index'); }); test.each(Object.keys(ruleTypeMappings) as RuleType[])( - 'Changes AAD rule params accordingly if rule is a siem.signals %p rule', + 'changes AAD rule params accordingly if rule is a siem.signals %p rule', (ruleType) => { const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0']; const alert = getMockData( { params: { outputIndex: 'output-index', type: ruleType }, alertTypeId: 'siem.signals' }, true ); - expect(migration800(alert, migrationContext).attributes.alertTypeId).toEqual( - ruleTypeMappings[ruleType] - ); - expect(migration800(alert, migrationContext).attributes.enabled).toEqual(false); - expect(migration800(alert, migrationContext).attributes.params.outputIndex).toEqual(''); + const migratedAlert = migration800(alert, migrationContext); + expect(migratedAlert.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]); + expect(migratedAlert.attributes.enabled).toEqual(false); + expect(migratedAlert.attributes.tags).toEqual(['foo']); + expect(migratedAlert.attributes.params.outputIndex).toEqual(''); } ); + describe('8.0.1', () => { + describe.each(Object.keys(ruleTypeMappings) as RuleType[])( + 'auto_disabled %p rule tags', + (ruleType) => { + const alert717Enabled = getMockData( + { + params: { outputIndex: 'output-index', type: ruleType }, + alertTypeId: 'siem.signals', + enabled: true, + scheduledTaskId: 'abcd', + }, + true + ); + const alert717Disabled = getMockData( + { + params: { outputIndex: 'output-index', type: ruleType }, + alertTypeId: 'siem.signals', + enabled: false, + }, + true + ); + const alert800 = getMockData( + { + params: { outputIndex: '', type: ruleType }, + alertTypeId: ruleTypeMappings[ruleType], + enabled: false, + scheduledTaskId: 'abcd', + }, + true + ); + + test('Does not update rule tags if rule has already been enabled', () => { + const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured); + const migration800 = migrations['8.0.0']; + const migration801 = migrations['8.0.1']; + + // migrate to 8.0.0 + const migratedAlert800 = migration800(alert717Enabled, migrationContext); + expect(migratedAlert800.attributes.enabled).toEqual(false); + + // reenable rule + migratedAlert800.attributes.enabled = true; + + // migrate to 8.0.1 + const migratedAlert801 = migration801(migratedAlert800, migrationContext); + + expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]); + expect(migratedAlert801.attributes.enabled).toEqual(true); + expect(migratedAlert801.attributes.params.outputIndex).toEqual(''); + + // tags not updated + expect(migratedAlert801.attributes.tags).toEqual(['foo']); + }); + + test('Does not update rule tags if rule was already disabled before upgrading to 8.0', () => { + const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured); + const migration800 = migrations['8.0.0']; + const migration801 = migrations['8.0.1']; + + // migrate to 8.0.0 + const migratedAlert800 = migration800(alert717Disabled, migrationContext); + expect(migratedAlert800.attributes.enabled).toEqual(false); + + // migrate to 8.0.1 + const migratedAlert801 = migration801(migratedAlert800, migrationContext); + + expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]); + expect(migratedAlert801.attributes.enabled).toEqual(false); + expect(migratedAlert801.attributes.params.outputIndex).toEqual(''); + + // tags not updated + expect(migratedAlert801.attributes.tags).toEqual(['foo']); + }); + + test('Updates rule tags if rule was auto-disabled in 8.0 upgrade and not reenabled', () => { + const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured); + const migration800 = migrations['8.0.0']; + const migration801 = migrations['8.0.1']; + + // migrate to 8.0.0 + const migratedAlert800 = migration800(alert717Enabled, migrationContext); + expect(migratedAlert800.attributes.enabled).toEqual(false); + + // migrate to 8.0.1 + const migratedAlert801 = migration801(migratedAlert800, migrationContext); + + expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]); + expect(migratedAlert801.attributes.enabled).toEqual(false); + expect(migratedAlert801.attributes.params.outputIndex).toEqual(''); + + // tags updated + expect(migratedAlert801.attributes.tags).toEqual(['foo', 'auto_disabled_8.0']); + }); + + test('Updates rule tags correctly if tags are undefined', () => { + const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured); + const migration801 = migrations['8.0.1']; + + const alert = { + ...alert800, + attributes: { + ...alert800.attributes, + tags: undefined, + }, + }; + + // migrate to 8.0.1 + const migratedAlert801 = migration801(alert, migrationContext); + + expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]); + expect(migratedAlert801.attributes.enabled).toEqual(false); + expect(migratedAlert801.attributes.params.outputIndex).toEqual(''); + + // tags updated + expect(migratedAlert801.attributes.tags).toEqual(['auto_disabled_8.0']); + }); + + test('Updates rule tags correctly if tags are null', () => { + const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured); + const migration801 = migrations['8.0.1']; + + const alert = { + ...alert800, + attributes: { + ...alert800.attributes, + tags: null, + }, + }; + + // migrate to 8.0.1 + const migratedAlert801 = migration801(alert, migrationContext); + + expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]); + expect(migratedAlert801.attributes.enabled).toEqual(false); + expect(migratedAlert801.attributes.params.outputIndex).toEqual(''); + + // tags updated + expect(migratedAlert801.attributes.tags).toEqual(['auto_disabled_8.0']); + }); + } + ); + }); + describe('Metrics Inventory Threshold rule', () => { test('Migrates incorrect action group spelling', () => { const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0']; diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts index e664095e8c846..6e6c886d91b53 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations.ts @@ -58,6 +58,9 @@ export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc): boolean => doc.attributes.alertTypeId === 'siem.signals'; +export const isDetectionEngineAADRuleType = (doc: SavedObjectUnsanitizedDoc): boolean => + (Object.values(ruleTypeMappings) as string[]).includes(doc.attributes.alertTypeId); + /** * Returns true if the alert type is that of "siem.notifications" which is a legacy notification system that was deprecated in 7.16.0 * in favor of using the newer alerting notifications system. @@ -136,6 +139,12 @@ export function getMigrations( ) ); + const migrationRules801 = createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations(addSecuritySolutionAADRuleTypeTags) + ); + return { '7.10.0': executeMigrationWithErrorHandling(migrationWhenRBACWasIntroduced, '7.10.0'), '7.11.0': executeMigrationWithErrorHandling(migrationAlertUpdatedAtAndNotifyWhen, '7.11.0'), @@ -145,6 +154,7 @@ export function getMigrations( '7.15.0': executeMigrationWithErrorHandling(migrationSecurityRules715, '7.15.0'), '7.16.0': executeMigrationWithErrorHandling(migrateRules716, '7.16.0'), '8.0.0': executeMigrationWithErrorHandling(migrationRules800, '8.0.0'), + '8.0.1': executeMigrationWithErrorHandling(migrationRules801, '8.0.1'), }; } @@ -672,6 +682,28 @@ function addSecuritySolutionAADRuleTypes( : doc; } +function addSecuritySolutionAADRuleTypeTags( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const ruleType = doc.attributes.params.type; + return isDetectionEngineAADRuleType(doc) && isRuleType(ruleType) + ? { + ...doc, + attributes: { + ...doc.attributes, + // If the rule is disabled at this point, then the rule has not been re-enabled after + // running the 8.0.0 migrations. If `doc.attributes.scheduledTaskId` exists, then the + // rule was enabled prior to running the migration. Thus we know we should add the + // tag to indicate it was auto-disabled. + tags: + !doc.attributes.enabled && doc.attributes.scheduledTaskId + ? [...(doc.attributes.tags ?? []), 'auto_disabled_8.0'] + : doc.attributes.tags ?? [], + }, + } + : doc; +} + function addThreatIndicatorPathToThreatMatchRules( doc: SavedObjectUnsanitizedDoc ): SavedObjectUnsanitizedDoc { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts index baa9eeb3ce036..5077c8d720c24 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts @@ -181,7 +181,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.15.0 migrates security_solution alerts with exceptionLists to be saved object references', async () => { - // NOTE: We hae to use elastic search directly against the ".kibana" index because alerts do not expose the references which we want to test exists + // NOTE: We have to use elasticsearch directly against the ".kibana" index because alerts do not expose the references which we want to test exists const response = await es.get<{ references: [{}] }>( { index: '.kibana', @@ -373,5 +373,39 @@ export default function createGetTests({ getService }: FtrProviderContext) { expect(response.body._source?.alert?.alertTypeId).to.be('siem.queryRule'); expect(response.body._source?.alert?.enabled).to.be(false); }); + + it('8.0.1 migrates and adds tags to disabled rules in 8.0', async () => { + const responseEnabledBeforeMigration = await es.get<{ alert: RawRule }>( + { + index: '.kibana', + id: 'alert:1efdfa40-8ec7-11ec-a700-5524407a7653', + }, + { meta: true } + ); + expect(responseEnabledBeforeMigration.statusCode).to.eql(200); + const responseDisabledBeforeMigration = await es.get<{ alert: RawRule }>( + { + index: '.kibana', + id: 'alert:13fdfa40-8ec7-11ec-a700-5524407a7667', + }, + { meta: true } + ); + expect(responseDisabledBeforeMigration.statusCode).to.eql(200); + + // Both should be disabled + expect(responseEnabledBeforeMigration.body._source?.alert?.enabled).to.be(false); + expect(responseDisabledBeforeMigration.body._source?.alert?.enabled).to.be(false); + + // Only the rule that was enabled should be tagged + expect(responseEnabledBeforeMigration.body._source?.alert?.tags).to.eql([ + '__internal_rule_id:064e3fed-6328-416b-bb85-c08265088f41', + '__internal_immutable:false', + 'auto_disabled_8.0', + ]); + expect(responseDisabledBeforeMigration.body._source?.alert?.tags).to.eql([ + '__internal_rule_id:364e3fed-6328-416b-bb85-c08265088f41', + '__internal_immutable:false', + ]); + }); }); } diff --git a/x-pack/test/functional/es_archives/alerts/data.json b/x-pack/test/functional/es_archives/alerts/data.json index afa54208512f4..96dad21732d0d 100644 --- a/x-pack/test/functional/es_archives/alerts/data.json +++ b/x-pack/test/functional/es_archives/alerts/data.json @@ -663,3 +663,194 @@ } } +{ + "type":"doc", + "value":{ + "id":"alert:1efdfa40-8ec7-11ec-a700-5524407a7653", + "index":".kibana_1", + "source":{ + "alert":{ + "name":"enabled 7.16.1 query rule", + "tags":[ + "__internal_rule_id:064e3fed-6328-416b-bb85-c08265088f41", + "__internal_immutable:false" + ], + "alertTypeId":"siem.signals", + "consumer":"siem", + "params":{ + "author":[ + + ], + "description":"enabled 7.16.1 query rule", + "ruleId":"064e3fed-6328-416b-bb85-c08265088f41", + "falsePositives":[ + + ], + "from":"now-36000060s", + "immutable":false, + "license":"", + "outputIndex":".siem-signals-default", + "meta":{ + "from":"10000h" + }, + "maxSignals":100, + "riskScore":21, + "riskScoreMapping":[ + + ], + "severity":"low", + "severityMapping":[ + + ], + "threat":[ + + ], + "to":"now", + "references":[ + + ], + "version":4, + "exceptionsList":[ + ], + "type":"query", + "language":"kuery", + "index":[ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*", + "test-index-3" + ], + "query":"*:*", + "filters":[ + + ] + }, + "schedule":{ + "interval":"1m" + }, + "enabled":true, + "actions":[ + + ], + "throttle":null, + "apiKeyOwner":"3270256467", + "apiKey":"UnFCyd4CthfIw6Mv5SRRbhYC7NPD2Jn8L+aCT/JfPQ5/poIsrwkh0plDAllpBYjFYhGXTQPtSPgu9yAwsuuaUhXxtFcnFHPleQeLvmu8VICueSxgMnK25Oqku8hfSQw9ETf9WZ3yXQOwvD9i8fkIUx84zt5q2LMuZv826fY9433/seVoCWspTj5qm2DchMDgTWzMKQaR2zbvRA==", + "createdBy":"3270256467", + "updatedBy":"3270256467", + "createdAt":"2022-02-16T01:24:02.121Z", + "muteAll":true, + "mutedInstanceIds":[ + + ], + "scheduledTaskId":"2030ade0-8ec7-11ec-a700-5524407a7653" + }, + "type":"alert", + "references":[], + "migrationVersion":{ + "alert":"7.16.0" + }, + "updated_at":"2022-02-16T16:20:19.375Z" + } + } +} + +{ + "type":"doc", + "value":{ + "id":"alert:13fdfa40-8ec7-11ec-a700-5524407a7667", + "index":".kibana_1", + "source":{ + "alert":{ + "name":"disabled 7.16.1 query rule", + "tags":[ + "__internal_rule_id:364e3fed-6328-416b-bb85-c08265088f41", + "__internal_immutable:false" + ], + "alertTypeId":"siem.signals", + "consumer":"siem", + "params":{ + "author":[ + + ], + "description":"disabled 7.16.1 query rule", + "ruleId":"364e3fed-6328-416b-bb85-c08265088f41", + "falsePositives":[ + + ], + "from":"now-36000060s", + "immutable":false, + "license":"", + "outputIndex":".siem-signals-default", + "meta":{ + "from":"10000h" + }, + "maxSignals":100, + "riskScore":21, + "riskScoreMapping":[ + + ], + "severity":"low", + "severityMapping":[ + + ], + "threat":[ + + ], + "to":"now", + "references":[ + + ], + "version":4, + "exceptionsList":[ + ], + "type":"query", + "language":"kuery", + "index":[ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*", + "test-index-3" + ], + "query":"*:*", + "filters":[ + + ] + }, + "schedule":{ + "interval":"1m" + }, + "enabled":true, + "actions":[ + + ], + "throttle":null, + "apiKeyOwner":"3270256467", + "apiKey":"UnFCyd4CthfIw6Mv5SRRbhYC7NPD2Jn8L+aCT/JfPQ5/poIsrwkh0plDAllpBYjFYhGXTQPtSPgu9yAwsuuaUhXxtFcnFHPleQeLvmu8VICueSxgMnK25Oqku8hfSQw9ETf9WZ3yXQOwvD9i8fkIUx84zt5q2LMuZv826fY9433/seVoCWspTj5qm2DchMDgTWzMKQaR2zbvRA==", + "createdBy":"3270256467", + "updatedBy":"3270256467", + "createdAt":"2022-02-16T01:25:02.121Z", + "muteAll":true, + "mutedInstanceIds":[ + + ], + "scheduledTaskId":null + }, + "type":"alert", + "references":[], + "migrationVersion":{ + "alert":"7.16.0" + }, + "updated_at":"2022-02-16T16:21:19.375Z" + } + } +} diff --git a/x-pack/test/functional/es_archives/alerts/mappings.json b/x-pack/test/functional/es_archives/alerts/mappings.json index ecaf138a0cdc4..babc00babc838 100644 --- a/x-pack/test/functional/es_archives/alerts/mappings.json +++ b/x-pack/test/functional/es_archives/alerts/mappings.json @@ -341,4 +341,4 @@ } } } -} \ No newline at end of file +} From a813c53c307ab1bf8c2b439781b13af4b1f2ddee Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Thu, 17 Feb 2022 12:09:17 +0900 Subject: [PATCH 043/104] Show how to use FTR on a single file (#125891) --- .../contributing/development-functional-tests.asciidoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/developer/contributing/development-functional-tests.asciidoc b/docs/developer/contributing/development-functional-tests.asciidoc index 1c44daf60f973..af88754b316fa 100644 --- a/docs/developer/contributing/development-functional-tests.asciidoc +++ b/docs/developer/contributing/development-functional-tests.asciidoc @@ -105,7 +105,9 @@ There are also command line flags for `--bail` and `--grep`, which behave just l Logging can also be customized with `--quiet`, `--debug`, or `--verbose` flags. -Use the `--help` flag for more options. +There are also options like `--include` to run only the tests defined in a single file or set of files. + +Run `node scripts/functional_test_runner --help` to see all available options. [discrete] From de042afce9f12d5914ba0061655283dfed3eab46 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 16 Feb 2022 20:20:53 -0700 Subject: [PATCH 044/104] skip more security solution suites blocking es promotion (#125851) --- .../security_and_spaces/tests/index.ts | 3 ++- .../apis/endpoint_artifacts/event_filters.ts | 3 ++- .../apis/endpoint_artifacts/host_isolation_exceptions.ts | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts index a9bda19638041..d234c70de5240 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts @@ -9,7 +9,8 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { - describe('detection engine api security and spaces enabled', function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('detection engine api security and spaces enabled', function () { describe('', function () { this.tags('ciGroup11'); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/event_filters.ts b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/event_filters.ts index 8ef3aaf9509dd..2c9414513ec0c 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/event_filters.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/event_filters.ts @@ -29,7 +29,8 @@ export default function ({ getService }: FtrProviderContext) { const endpointPolicyTestResources = getService('endpointPolicyTestResources'); const endpointArtifactTestResources = getService('endpointArtifactTestResources'); - describe('Endpoint artifacts (via lists plugin): Event Filters', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('Endpoint artifacts (via lists plugin): Event Filters', () => { const USER = ROLES.detections_admin; let fleetEndpointPolicy: PolicyTestResourceInfo; diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/host_isolation_exceptions.ts b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/host_isolation_exceptions.ts index ffa7473e95416..0f8db9a1e0765 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/host_isolation_exceptions.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_artifacts/host_isolation_exceptions.ts @@ -39,7 +39,8 @@ export default function ({ getService }: FtrProviderContext) { getBody: () => BodyReturnType; }>; - describe('Endpoint Host Isolation Exceptions artifacts (via lists plugin)', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125851 + describe.skip('Endpoint Host Isolation Exceptions artifacts (via lists plugin)', () => { let fleetEndpointPolicy: PolicyTestResourceInfo; let existingExceptionData: ArtifactTestData; From 01a87e040bf439d213db93b9ad9cab57df77f4b7 Mon Sep 17 00:00:00 2001 From: Marshall Main <55718608+marshallmain@users.noreply.github.com> Date: Wed, 16 Feb 2022 21:46:28 -0800 Subject: [PATCH 045/104] Populate kibana.alert.uuid in eql sequence alerts (#125890) --- .../factories/utils/build_alert_group_from_sequence.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts index 4dd2903994085..180494f9209dd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts @@ -71,8 +71,9 @@ export const buildAlertGroupFromSequence = ( // we can build the signal that links the building blocks together // and also insert the group id (which is also the "shell" signal _id) in each building block const doc = buildAlertRoot(wrappedBuildingBlocks, completeRule, spaceId, buildReasonMessage); + const sequenceAlertId = generateAlertId(doc); const sequenceAlert = { - _id: generateAlertId(doc), + _id: sequenceAlertId, _index: '', _source: doc, }; @@ -82,6 +83,8 @@ export const buildAlertGroupFromSequence = ( block._source[ALERT_GROUP_INDEX] = i; }); + sequenceAlert._source[ALERT_UUID] = sequenceAlertId; + return [...wrappedBuildingBlocks, sequenceAlert]; }; From 5b752653f4a30c35e5f3badc0ea1c4adbb43b7bb Mon Sep 17 00:00:00 2001 From: Marshall Main <55718608+marshallmain@users.noreply.github.com> Date: Wed, 16 Feb 2022 21:47:36 -0800 Subject: [PATCH 046/104] [Security Solution] Apply field aliases to all legacy indices, not just <= version 45 (#125888) * Apply field aliases to all legacy indices, not just <= version 45 * Update unit tests --- .../get_signals_template.test.ts.snap | 519 +++++++++++++++++- .../routes/index/create_index_route.ts | 4 + .../routes/index/get_signals_template.ts | 5 +- 3 files changed, 522 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap index b826ed83d34ed..b1737b1efe6a9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/__snapshots__/get_signals_template.test.ts.snap @@ -3,7 +3,7 @@ exports[`get_signals_template backwards compatibility mappings for version 45 should match snapshot 1`] = ` Object { "_meta": Object { - "aliases_version": 2, + "aliases_version": 3, "version": 45, }, "properties": Object { @@ -533,9 +533,522 @@ Object { exports[`get_signals_template backwards compatibility mappings for version 57 should match snapshot 1`] = ` Object { "_meta": Object { - "aliases_version": 2, + "aliases_version": 3, "version": 57, }, + "properties": Object { + "kibana.alert.ancestors.depth": Object { + "path": "signal.ancestors.depth", + "type": "alias", + }, + "kibana.alert.ancestors.id": Object { + "path": "signal.ancestors.id", + "type": "alias", + }, + "kibana.alert.ancestors.index": Object { + "path": "signal.ancestors.index", + "type": "alias", + }, + "kibana.alert.ancestors.type": Object { + "path": "signal.ancestors.type", + "type": "alias", + }, + "kibana.alert.building_block_type": Object { + "path": "signal.rule.building_block_type", + "type": "alias", + }, + "kibana.alert.depth": Object { + "path": "signal.depth", + "type": "alias", + }, + "kibana.alert.group.id": Object { + "path": "signal.group.id", + "type": "alias", + }, + "kibana.alert.group.index": Object { + "path": "signal.group.index", + "type": "alias", + }, + "kibana.alert.original_event.action": Object { + "path": "signal.original_event.action", + "type": "alias", + }, + "kibana.alert.original_event.category": Object { + "path": "signal.original_event.category", + "type": "alias", + }, + "kibana.alert.original_event.code": Object { + "path": "signal.original_event.code", + "type": "alias", + }, + "kibana.alert.original_event.created": Object { + "path": "signal.original_event.created", + "type": "alias", + }, + "kibana.alert.original_event.dataset": Object { + "path": "signal.original_event.dataset", + "type": "alias", + }, + "kibana.alert.original_event.duration": Object { + "path": "signal.original_event.duration", + "type": "alias", + }, + "kibana.alert.original_event.end": Object { + "path": "signal.original_event.end", + "type": "alias", + }, + "kibana.alert.original_event.hash": Object { + "path": "signal.original_event.hash", + "type": "alias", + }, + "kibana.alert.original_event.id": Object { + "path": "signal.original_event.id", + "type": "alias", + }, + "kibana.alert.original_event.kind": Object { + "path": "signal.original_event.kind", + "type": "alias", + }, + "kibana.alert.original_event.module": Object { + "path": "signal.original_event.module", + "type": "alias", + }, + "kibana.alert.original_event.outcome": Object { + "path": "signal.original_event.outcome", + "type": "alias", + }, + "kibana.alert.original_event.provider": Object { + "path": "signal.original_event.provider", + "type": "alias", + }, + "kibana.alert.original_event.reason": Object { + "path": "signal.original_event.reason", + "type": "alias", + }, + "kibana.alert.original_event.risk_score": Object { + "path": "signal.original_event.risk_score", + "type": "alias", + }, + "kibana.alert.original_event.risk_score_norm": Object { + "path": "signal.original_event.risk_score_norm", + "type": "alias", + }, + "kibana.alert.original_event.sequence": Object { + "path": "signal.original_event.sequence", + "type": "alias", + }, + "kibana.alert.original_event.severity": Object { + "path": "signal.original_event.severity", + "type": "alias", + }, + "kibana.alert.original_event.start": Object { + "path": "signal.original_event.start", + "type": "alias", + }, + "kibana.alert.original_event.timezone": Object { + "path": "signal.original_event.timezone", + "type": "alias", + }, + "kibana.alert.original_event.type": Object { + "path": "signal.original_event.type", + "type": "alias", + }, + "kibana.alert.original_time": Object { + "path": "signal.original_time", + "type": "alias", + }, + "kibana.alert.reason": Object { + "path": "signal.reason", + "type": "alias", + }, + "kibana.alert.risk_score": Object { + "path": "signal.rule.risk_score", + "type": "alias", + }, + "kibana.alert.rule.author": Object { + "path": "signal.rule.author", + "type": "alias", + }, + "kibana.alert.rule.created_at": Object { + "path": "signal.rule.created_at", + "type": "alias", + }, + "kibana.alert.rule.created_by": Object { + "path": "signal.rule.created_by", + "type": "alias", + }, + "kibana.alert.rule.description": Object { + "path": "signal.rule.description", + "type": "alias", + }, + "kibana.alert.rule.enabled": Object { + "path": "signal.rule.enabled", + "type": "alias", + }, + "kibana.alert.rule.false_positives": Object { + "path": "signal.rule.false_positives", + "type": "alias", + }, + "kibana.alert.rule.from": Object { + "path": "signal.rule.from", + "type": "alias", + }, + "kibana.alert.rule.immutable": Object { + "path": "signal.rule.immutable", + "type": "alias", + }, + "kibana.alert.rule.interval": Object { + "path": "signal.rule.interval", + "type": "alias", + }, + "kibana.alert.rule.license": Object { + "path": "signal.rule.license", + "type": "alias", + }, + "kibana.alert.rule.max_signals": Object { + "path": "signal.rule.max_signals", + "type": "alias", + }, + "kibana.alert.rule.name": Object { + "path": "signal.rule.name", + "type": "alias", + }, + "kibana.alert.rule.note": Object { + "path": "signal.rule.note", + "type": "alias", + }, + "kibana.alert.rule.references": Object { + "path": "signal.rule.references", + "type": "alias", + }, + "kibana.alert.rule.rule_id": Object { + "path": "signal.rule.rule_id", + "type": "alias", + }, + "kibana.alert.rule.rule_name_override": Object { + "path": "signal.rule.rule_name_override", + "type": "alias", + }, + "kibana.alert.rule.tags": Object { + "path": "signal.rule.tags", + "type": "alias", + }, + "kibana.alert.rule.threat.framework": Object { + "path": "signal.rule.threat.framework", + "type": "alias", + }, + "kibana.alert.rule.threat.tactic.id": Object { + "path": "signal.rule.threat.tactic.id", + "type": "alias", + }, + "kibana.alert.rule.threat.tactic.name": Object { + "path": "signal.rule.threat.tactic.name", + "type": "alias", + }, + "kibana.alert.rule.threat.tactic.reference": Object { + "path": "signal.rule.threat.tactic.reference", + "type": "alias", + }, + "kibana.alert.rule.threat.technique.id": Object { + "path": "signal.rule.threat.technique.id", + "type": "alias", + }, + "kibana.alert.rule.threat.technique.name": Object { + "path": "signal.rule.threat.technique.name", + "type": "alias", + }, + "kibana.alert.rule.threat.technique.reference": Object { + "path": "signal.rule.threat.technique.reference", + "type": "alias", + }, + "kibana.alert.rule.threat.technique.subtechnique.id": Object { + "path": "signal.rule.threat.technique.subtechnique.id", + "type": "alias", + }, + "kibana.alert.rule.threat.technique.subtechnique.name": Object { + "path": "signal.rule.threat.technique.subtechnique.name", + "type": "alias", + }, + "kibana.alert.rule.threat.technique.subtechnique.reference": Object { + "path": "signal.rule.threat.technique.subtechnique.reference", + "type": "alias", + }, + "kibana.alert.rule.timeline_id": Object { + "path": "signal.rule.timeline_id", + "type": "alias", + }, + "kibana.alert.rule.timeline_title": Object { + "path": "signal.rule.timeline_title", + "type": "alias", + }, + "kibana.alert.rule.timestamp_override": Object { + "path": "signal.rule.timestamp_override", + "type": "alias", + }, + "kibana.alert.rule.to": Object { + "path": "signal.rule.to", + "type": "alias", + }, + "kibana.alert.rule.type": Object { + "path": "signal.rule.type", + "type": "alias", + }, + "kibana.alert.rule.updated_at": Object { + "path": "signal.rule.updated_at", + "type": "alias", + }, + "kibana.alert.rule.updated_by": Object { + "path": "signal.rule.updated_by", + "type": "alias", + }, + "kibana.alert.rule.uuid": Object { + "path": "signal.rule.id", + "type": "alias", + }, + "kibana.alert.rule.version": Object { + "path": "signal.rule.version", + "type": "alias", + }, + "kibana.alert.severity": Object { + "path": "signal.rule.severity", + "type": "alias", + }, + "kibana.alert.threshold_result.cardinality.field": Object { + "path": "signal.threshold_result.cardinality.field", + "type": "alias", + }, + "kibana.alert.threshold_result.cardinality.value": Object { + "path": "signal.threshold_result.cardinality.value", + "type": "alias", + }, + "kibana.alert.threshold_result.count": Object { + "path": "signal.threshold_result.count", + "type": "alias", + }, + "kibana.alert.threshold_result.from": Object { + "path": "signal.threshold_result.from", + "type": "alias", + }, + "kibana.alert.threshold_result.terms.field": Object { + "path": "signal.threshold_result.terms.field", + "type": "alias", + }, + "kibana.alert.threshold_result.terms.value": Object { + "path": "signal.threshold_result.terms.value", + "type": "alias", + }, + "kibana.alert.workflow_status": Object { + "path": "signal.status", + "type": "alias", + }, + "signal": Object { + "properties": Object { + "_meta": Object { + "properties": Object { + "version": Object { + "type": "long", + }, + }, + "type": "object", + }, + "ancestors": Object { + "properties": Object { + "depth": Object { + "type": "long", + }, + "id": Object { + "type": "keyword", + }, + "index": Object { + "type": "keyword", + }, + "rule": Object { + "type": "keyword", + }, + "type": Object { + "type": "keyword", + }, + }, + }, + "depth": Object { + "type": "integer", + }, + "group": Object { + "properties": Object { + "id": Object { + "type": "keyword", + }, + "index": Object { + "type": "integer", + }, + }, + "type": "object", + }, + "original_event": Object { + "properties": Object { + "reason": Object { + "type": "keyword", + }, + }, + "type": "object", + }, + "reason": Object { + "type": "keyword", + }, + "rule": Object { + "properties": Object { + "author": Object { + "type": "keyword", + }, + "building_block_type": Object { + "type": "keyword", + }, + "license": Object { + "type": "keyword", + }, + "note": Object { + "type": "text", + }, + "risk_score_mapping": Object { + "properties": Object { + "field": Object { + "type": "keyword", + }, + "operator": Object { + "type": "keyword", + }, + "value": Object { + "type": "keyword", + }, + }, + "type": "object", + }, + "rule_name_override": Object { + "type": "keyword", + }, + "severity_mapping": Object { + "properties": Object { + "field": Object { + "type": "keyword", + }, + "operator": Object { + "type": "keyword", + }, + "severity": Object { + "type": "keyword", + }, + "value": Object { + "type": "keyword", + }, + }, + "type": "object", + }, + "threat": Object { + "properties": Object { + "technique": Object { + "properties": Object { + "subtechnique": Object { + "properties": Object { + "id": Object { + "type": "keyword", + }, + "name": Object { + "type": "keyword", + }, + "reference": Object { + "type": "keyword", + }, + }, + "type": "object", + }, + }, + "type": "object", + }, + }, + "type": "object", + }, + "threat_index": Object { + "type": "keyword", + }, + "threat_indicator_path": Object { + "type": "keyword", + }, + "threat_language": Object { + "type": "keyword", + }, + "threat_mapping": Object { + "properties": Object { + "entries": Object { + "properties": Object { + "field": Object { + "type": "keyword", + }, + "type": Object { + "type": "keyword", + }, + "value": Object { + "type": "keyword", + }, + }, + "type": "object", + }, + }, + "type": "object", + }, + "threat_query": Object { + "type": "keyword", + }, + "threshold": Object { + "properties": Object { + "field": Object { + "type": "keyword", + }, + "value": Object { + "type": "float", + }, + }, + "type": "object", + }, + "timestamp_override": Object { + "type": "keyword", + }, + }, + "type": "object", + }, + "threshold_result": Object { + "properties": Object { + "cardinality": Object { + "properties": Object { + "field": Object { + "type": "keyword", + }, + "value": Object { + "type": "long", + }, + }, + }, + "count": Object { + "type": "long", + }, + "from": Object { + "type": "date", + }, + "terms": Object { + "properties": Object { + "field": Object { + "type": "keyword", + }, + "value": Object { + "type": "keyword", + }, + }, + }, + }, + }, + }, + "type": "object", + }, + }, } `; @@ -552,7 +1065,7 @@ Object { }, "mappings": Object { "_meta": Object { - "aliases_version": 2, + "aliases_version": 3, "version": 67, }, "dynamic": false, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts index 9bb848b2f7d34..5ff76179eeb03 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts @@ -145,6 +145,10 @@ const addFieldAliasesToIndices = async ({ const indicesByVersion: Record = {}; const versions: Set = new Set(); for (const [indexName, mapping] of Object.entries(indexMappings)) { + // The `version` tells us which set of backwards compatibility mappings to apply: `version` never changes + // and represents what was actually shipped. `aliases_version` tells us if the most up to date backwards + // compatibility mappings have already been applied to the index. `aliases_version` DOES get updated when we apply + // new compatibility mappings like runtime fields and aliases. const version: number = get(mapping.mappings?._meta, 'version') ?? 0; const aliasesVersion: number = get(mapping.mappings?._meta, ALIAS_VERSION_FIELD) ?? 0; // Only attempt to add backwards compatibility mappings to indices whose names start with the alias diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts index 1f02fcde67184..642236f950308 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts @@ -47,7 +47,7 @@ export const SIGNALS_TEMPLATE_VERSION = 67; UI will call create_index_route and and go through the index update process. Increment this number if making changes to the field aliases we use to make signals forwards-compatible. */ -export const SIGNALS_FIELD_ALIASES_VERSION = 2; +export const SIGNALS_FIELD_ALIASES_VERSION = 3; /** @constant @@ -154,7 +154,6 @@ export const backwardsCompatibilityMappings = [ }, }, }, - properties, }, }, ]; @@ -171,7 +170,7 @@ export const createBackwardsCompatibilityMapping = (version: number) => { }, }; - return merge({}, ...mappings, meta); + return merge({ properties }, ...mappings, meta); }; export const getRbacRequiredFields = (spaceId: string) => { From 24ea50eeb895de531d97255ca4bc67816b9ebc24 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Thu, 17 Feb 2022 07:49:00 +0100 Subject: [PATCH 047/104] DeprecationService: add timeout when resolving deprecations (#125769) --- .../deprecations_registry.test.ts | 19 ++++++++++++++ .../deprecations/deprecations_registry.ts | 26 ++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/core/server/deprecations/deprecations_registry.test.ts b/src/core/server/deprecations/deprecations_registry.test.ts index 0e4f48b18a0a9..0f7e2704d934a 100644 --- a/src/core/server/deprecations/deprecations_registry.test.ts +++ b/src/core/server/deprecations/deprecations_registry.test.ts @@ -65,6 +65,25 @@ describe('DeprecationsRegistry', () => { ]); }); + it('rejects deprecations when reaching the timeout', async () => { + const deprecationsRegistry = new DeprecationsRegistry({ timeout: 100 }); + const mockContext = {} as unknown as GetDeprecationsContext; + const deprecationsConfigA = { + getDeprecations: jest.fn().mockReturnValue(new Promise(() => {})), + }; + deprecationsRegistry.registerDeprecations(deprecationsConfigA); + const deprecations = await deprecationsRegistry.getDeprecations(mockContext); + expect(deprecations).toStrictEqual([ + { + status: 'rejected', + reason: expect.any(Error), + }, + ]); + expect((deprecations[0] as PromiseRejectedResult).reason.message).toEqual( + 'Deprecations did not resolve in 10sec.' + ); + }); + it('passes dependencies to registered getDeprecations function', async () => { const deprecationsRegistry = new DeprecationsRegistry(); const mockContext = {} as unknown as GetDeprecationsContext; diff --git a/src/core/server/deprecations/deprecations_registry.ts b/src/core/server/deprecations/deprecations_registry.ts index cc05473923ac8..e979bb94712e6 100644 --- a/src/core/server/deprecations/deprecations_registry.ts +++ b/src/core/server/deprecations/deprecations_registry.ts @@ -6,15 +6,23 @@ * Side Public License, v 1. */ +import { withTimeout, isPromise } from '@kbn/std'; import type { DeprecationsDetails, RegisterDeprecationsConfig, GetDeprecationsContext, } from './types'; +const MsInSec = 1000; + export class DeprecationsRegistry { + private readonly timeout: number; private readonly deprecationContexts: RegisterDeprecationsConfig[] = []; + constructor({ timeout = 10 * MsInSec }: { timeout?: number } = {}) { + this.timeout = timeout; + } + public registerDeprecations = (deprecationContext: RegisterDeprecationsConfig) => { if (typeof deprecationContext.getDeprecations !== 'function') { throw new Error(`getDeprecations must be a function in registerDeprecations(context)`); @@ -27,9 +35,21 @@ export class DeprecationsRegistry { dependencies: GetDeprecationsContext ): Promise>> => { return await Promise.allSettled( - this.deprecationContexts.map( - async (deprecationContext) => await deprecationContext.getDeprecations(dependencies) - ) + this.deprecationContexts.map(async (deprecationContext) => { + const maybePromise = deprecationContext.getDeprecations(dependencies); + if (isPromise(maybePromise)) { + const resultOrTimeout = await withTimeout({ + promise: maybePromise, + timeoutMs: this.timeout, + }); + if (resultOrTimeout.timedout) { + throw new Error('Deprecations did not resolve in 10sec.'); + } + return resultOrTimeout.value; + } else { + return maybePromise; + } + }) ); }; } From dff2d94be7797052c439fe40a0031fbacee72733 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Thu, 17 Feb 2022 09:20:43 +0100 Subject: [PATCH 048/104] =?UTF-8?q?Upgrade=20`node-fetch`=20package=20(`2.?= =?UTF-8?q?6.1`=20=E2=86=92=20`2.6.7`).=20(#125643)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 9 ++++--- yarn.lock | 76 ++++++++++++++++++++++------------------------------ 2 files changed, 37 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index d8e2226ba944c..cf4582a4c7df3 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "**/handlebars/uglify-js": "^3.14.3", "**/hoist-non-react-statics": "^3.3.2", "**/html-minifier/uglify-js": "^3.14.3", - "**/isomorphic-fetch/node-fetch": "^2.6.1", + "**/isomorphic-fetch/node-fetch": "^2.6.7", "**/istanbul-lib-coverage": "^3.2.0", "**/json-schema": "^0.4.0", "**/minimist": "^1.2.5", @@ -93,7 +93,8 @@ "**/trim": "1.0.1", "**/typescript": "4.5.3", "**/underscore": "^1.13.1", - "globby/fast-glob": "3.2.7" + "globby/fast-glob": "3.2.7", + "puppeteer/node-fetch": "^2.6.7" }, "dependencies": { "@babel/runtime": "^7.17.2", @@ -305,7 +306,7 @@ "monaco-editor": "^0.22.3", "mustache": "^2.3.2", "nock": "12.0.3", - "node-fetch": "^2.6.1", + "node-fetch": "^2.6.7", "node-forge": "^1.2.1", "nodemailer": "^6.6.2", "normalize-path": "^3.0.0", @@ -643,7 +644,7 @@ "@types/ncp": "^2.0.1", "@types/nock": "^10.0.3", "@types/node": "16.10.2", - "@types/node-fetch": "^2.5.7", + "@types/node-fetch": "^2.6.0", "@types/node-forge": "^1.0.0", "@types/nodemailer": "^6.4.0", "@types/normalize-path": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index 252b2a8cc6775..e37c4804500e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4643,15 +4643,6 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request-error@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0" - integrity sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw== - dependencies: - "@octokit/types" "^5.0.1" - deprecation "^2.0.0" - once "^1.4.0" - "@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" @@ -4673,21 +4664,7 @@ once "^1.4.0" universal-user-agent "^2.0.1" -"@octokit/request@^5.2.0", "@octokit/request@^5.3.0": - version "5.4.12" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.12.tgz#b04826fa934670c56b135a81447be2c1723a2ffc" - integrity sha512-MvWYdxengUWTGFpfpefBBpVmmEYfkwMoxonIB3sUGp5rhdgwjXL1ejo6JbgzG/QD9B/NYt/9cJX1pxXeSIUCkg== - dependencies: - "@octokit/endpoint" "^6.0.1" - "@octokit/request-error" "^2.0.0" - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - is-plain-object "^5.0.0" - node-fetch "^2.6.1" - once "^1.4.0" - universal-user-agent "^6.0.0" - -"@octokit/request@^5.6.0": +"@octokit/request@^5.2.0", "@octokit/request@^5.3.0", "@octokit/request@^5.6.0": version "5.6.2" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== @@ -4756,7 +4733,7 @@ dependencies: "@types/node" ">= 8" -"@octokit/types@^5.0.0", "@octokit/types@^5.0.1": +"@octokit/types@^5.0.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== @@ -7196,13 +7173,13 @@ dependencies: "@types/node" "*" -"@types/node-fetch@^2.5.7": - version "2.5.7" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" - integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== +"@types/node-fetch@^2.5.7", "@types/node-fetch@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.0.tgz#bf854a36a0d0d99436fd199e06612ef4e73591b6" + integrity sha512-HT+uU6V27wJFXgEqTk/+rVE1MWcp5bg7Yuz//43TZ2PjpQbQ8vDLwVmB+fSpgs83j/+p+rMIlDRo9TL3IexWMA== dependencies: "@types/node" "*" - form-data "^3.0.0" + form-data "^2.3.3" "@types/node-forge@^1.0.0": version "1.0.0" @@ -15489,7 +15466,7 @@ fork-ts-checker-webpack-plugin@^6.0.4: semver "^7.3.2" tapable "^1.0.0" -form-data@^2.3.1: +form-data@^2.3.1, form-data@^2.3.3: version "2.5.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.0.tgz#094ec359dc4b55e7d62e0db4acd76e89fe874d37" integrity sha512-WXieX3G/8side6VIqx44ablyULoGruSde5PNTxoUyo5CeyAMX6nVWUd0rgist/EuX655cjhUhTo1Fo3tRYqbcA== @@ -15498,15 +15475,6 @@ form-data@^2.3.1: combined-stream "^1.0.6" mime-types "^2.1.12" -form-data@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" - integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -21577,10 +21545,12 @@ node-emoji@^1.10.0: dependencies: lodash.toarray "^4.4.0" -node-fetch@2.6.1, node-fetch@^1.0.1, node-fetch@^2.3.0, node-fetch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@2.6.1, node-fetch@^1.0.1, node-fetch@^2.3.0, node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-forge@^0.10.0, node-forge@^1.2.1: version "1.2.1" @@ -28778,6 +28748,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + traceparent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/traceparent/-/traceparent-1.0.0.tgz#9b14445cdfe5c19f023f1c04d249c3d8e003a5ce" @@ -30534,6 +30509,11 @@ web-streams-polyfill@^3.0.0: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.0.1.tgz#1f836eea307e8f4af15758ee473c7af755eb879e" integrity sha512-M+EmTdszMWINywOZaqpZ6VIEDUmNpRaTOuizF0ZKPjSDC8paMRe/jBBwFv0Yeyn5WYnM5pMqMQa82vpaE+IJRw== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -30739,6 +30719,14 @@ whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" From e1280a4b1b82626d6b6a1a6076318af123ea4b4e Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 17 Feb 2022 11:47:37 +0200 Subject: [PATCH 049/104] [TSVB] Decrease the bundle size (#125777) * Async get series * Async load getExtents * Load async 1 level up * Remove comment Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/vis_types/timeseries/public/metrics_type.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/vis_types/timeseries/public/metrics_type.ts b/src/plugins/vis_types/timeseries/public/metrics_type.ts index ff613c0eadb06..0c5b365938058 100644 --- a/src/plugins/vis_types/timeseries/public/metrics_type.ts +++ b/src/plugins/vis_types/timeseries/public/metrics_type.ts @@ -26,7 +26,6 @@ import { } from '../../../visualizations/public'; import { getDataStart } from './services'; import type { TimeseriesVisDefaultParams, TimeseriesVisParams } from './types'; -import { triggerTSVBtoLensConfiguration } from './trigger_action'; import type { IndexPatternValue, Panel } from '../common/types'; import { RequestAdapter } from '../../../inspector/public'; @@ -169,6 +168,8 @@ export const metricsVisDefinition: VisTypeDefinition< return []; }, navigateToLens: async (params?: VisParams) => { + const { triggerTSVBtoLensConfiguration } = await import('./trigger_action'); + const triggerConfiguration = params ? await triggerTSVBtoLensConfiguration(params as Panel) : null; From 077b4e0de0213fb1722ebd965021179f5627c38f Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 17 Feb 2022 02:03:52 -0800 Subject: [PATCH 050/104] Add mlr-docs to codeowners (#125721) --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a8619643d1b2e..2efcf3b27b18d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -344,8 +344,8 @@ /x-pack/plugins/triggers_actions_ui/ @elastic/response-ops /x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/response-ops /x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/response-ops -/docs/user/alerting/ @elastic/response-ops -/docs/management/connectors/ @elastic/response-ops +/docs/user/alerting/ @elastic/response-ops @elastic/mlr-docs +/docs/management/connectors/ @elastic/response-ops @elastic/mlr-docs #CC# /x-pack/plugins/stack_alerts @elastic/response-ops /x-pack/plugins/cases/ @elastic/response-ops /x-pack/test/cases_api_integration/ @elastic/response-ops From 53c5a42d609b078061df392b5af53a86a4b4ad14 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 17 Feb 2022 12:35:13 +0200 Subject: [PATCH 051/104] [TSVB2Lens] Supports positive only as clamp (#125771) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/trigger_action/get_series.test.ts | 26 +++++++++++++++++++ .../public/trigger_action/get_series.ts | 8 ++++++ .../public/trigger_action/metrics_helpers.ts | 22 ++++++++++++---- .../trigger_action/supported_metrics.ts | 4 +++ 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts index 7410c95677cff..12de3248794ab 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts @@ -84,6 +84,32 @@ describe('getSeries', () => { ]); }); + test('should return the correct formula config for a positive only function', () => { + const metric = [ + { + field: 'day_of_week_i', + id: '123456', + type: 'max', + }, + { + id: '891011', + type: 'positive_only', + field: '123456', + }, + ] as Metric[]; + const config = getSeries(metric); + expect(config).toStrictEqual([ + { + agg: 'formula', + fieldName: 'document', + isFullReference: true, + params: { + formula: 'clamp(max(day_of_week_i), 0, max(day_of_week_i))', + }, + }, + ]); + }); + test('should return the correct config for the cumulative sum on count', () => { const metric = [ { diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts index eed1594300b92..021ccff7c8d71 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts @@ -125,6 +125,14 @@ export const getSeries = (metrics: Metric[]): VisualizeEditorLayersContext['metr } break; } + case 'positive_only': { + const formula = getSiblingPipelineSeriesFormula(aggregation, metrics[metricIdx], metrics); + if (!formula) { + return null; + } + metricsArray = getFormulaSeries(formula) as VisualizeEditorLayersContext['metrics']; + break; + } case 'avg_bucket': case 'max_bucket': case 'min_bucket': diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/metrics_helpers.ts b/src/plugins/vis_types/timeseries/public/trigger_action/metrics_helpers.ts index 07140c9fdd9d1..dc9457ac1fafc 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/metrics_helpers.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/metrics_helpers.ts @@ -192,20 +192,31 @@ export const getSiblingPipelineSeriesFormula = ( return null; } const aggregationMap = SUPPORTED_METRICS[aggregation]; - const subMetricField = subFunctionMetric.field; + const subMetricField = subFunctionMetric.type !== 'count' ? subFunctionMetric.field : ''; // support nested aggs with formula const additionalSubFunction = metrics.find((metric) => metric.id === subMetricField); let formula = `${aggregationMap.name}(`; + let minMax = ''; if (additionalSubFunction) { const additionalPipelineAggMap = SUPPORTED_METRICS[additionalSubFunction.type]; if (!additionalPipelineAggMap) { return null; } + const additionalSubFunctionField = + additionalSubFunction.type !== 'count' ? additionalSubFunction.field : ''; + if (currentMetric.type === 'positive_only') { + minMax = `, 0, ${pipelineAggMap.name}(${additionalPipelineAggMap.name}(${ + additionalSubFunctionField ?? '' + }))`; + } formula += `${pipelineAggMap.name}(${additionalPipelineAggMap.name}(${ - additionalSubFunction.field ?? '' - })))`; + additionalSubFunctionField ?? '' + }))${minMax})`; } else { - formula += `${pipelineAggMap.name}(${subFunctionMetric.field ?? ''}))`; + if (currentMetric.type === 'positive_only') { + minMax = `, 0, ${pipelineAggMap.name}(${subMetricField ?? ''})`; + } + formula += `${pipelineAggMap.name}(${subMetricField ?? ''})${minMax})`; } return formula; }; @@ -262,7 +273,8 @@ export const getFormulaEquivalent = ( case 'avg_bucket': case 'max_bucket': case 'min_bucket': - case 'sum_bucket': { + case 'sum_bucket': + case 'positive_only': { return getSiblingPipelineSeriesFormula(currentMetric.type, currentMetric, metrics); } case 'count': { diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts b/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts index b3d58d81105ab..74bb4e4d1dc15 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts @@ -84,4 +84,8 @@ export const SUPPORTED_METRICS: { [key: string]: AggOptions } = { name: 'formula', isFullReference: true, }, + positive_only: { + name: 'clamp', + isFullReference: true, + }, }; From 962ff44cc74e5227319ce59abb8c1fabd53c0f9f Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Thu, 17 Feb 2022 11:47:41 +0100 Subject: [PATCH 052/104] [Fleet] Hide advanced tab in Integrations when role is Fleet All Integrations Read (#125819) --- .../integrations/sections/epm/screens/detail/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx index 2a1c9a29f289d..2ba625ea420e3 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx @@ -514,7 +514,7 @@ export function Detail() { }); } - if (showCustomTab) { + if (canReadPackageSettings && showCustomTab) { tabs.push({ id: 'custom', name: ( From 3ff03fcdf99e9c1721b1d3c3798321572ae0d0c2 Mon Sep 17 00:00:00 2001 From: Josh Dover <1813008+joshdover@users.noreply.github.com> Date: Thu, 17 Feb 2022 11:57:32 +0100 Subject: [PATCH 053/104] [Fleet] Fix GITHUB_TOKEN for Fleet QA labeling action (#125918) --- .github/workflows/label-qa-fixed-in.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/label-qa-fixed-in.yml b/.github/workflows/label-qa-fixed-in.yml index 7ef6b0666e6c6..bb203d7d17c43 100644 --- a/.github/workflows/label-qa-fixed-in.yml +++ b/.github/workflows/label-qa-fixed-in.yml @@ -37,7 +37,8 @@ jobs: } } prnumber: ${{ github.event.number }} - token: ${{ secrets.FLEET_TECH_KIBANA_USER_TOKEN }} + env: + GITHUB_TOKEN: ${{ secrets.FLEET_TECH_KIBANA_USER_TOKEN }} - uses: sergeysova/jq-action@v2 id: issues_to_label with: @@ -75,4 +76,5 @@ jobs: } issueid: ${{ matrix.issueNodeId }} labelids: ${{ needs.fetch_issues_to_label.outputs.label_ids }} - token: ${{ secrets.FLEET_TECH_KIBANA_USER_TOKEN }} + env: + GITHUB_TOKEN: ${{ secrets.FLEET_TECH_KIBANA_USER_TOKEN }} From cc4282a1d2b349b1e5d9b6fdf8daa253f2517fec Mon Sep 17 00:00:00 2001 From: Katerina Patticha Date: Thu, 17 Feb 2022 13:05:43 +0100 Subject: [PATCH 054/104] [APM] e2e for integrations settings when apm server is not installed (#125641) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apm_server_not_installed.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/integration_settings/apm_server_not_installed.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/integration_settings/apm_server_not_installed.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/integration_settings/apm_server_not_installed.ts new file mode 100644 index 0000000000000..354ffa5e42e18 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/integration_settings/apm_server_not_installed.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +const integrationsPath = '/app/integrations/browse'; + +describe('when navigating to the integrations browse page', () => { + beforeEach(() => { + cy.loginAsReadOnlyUser(); + cy.visit(integrationsPath); + }); + + it('should display Elastic APM integration option', () => { + cy.get('[data-test-subj="integration-card:epr:apm:featured').should( + 'exist' + ); + cy.contains('Elastic APM'); + }); + + describe('when clicking on the Elastic APM option but Fleet is not installed', () => { + it('should display Elastic APM in Fleet tab', () => { + cy.get('[data-test-subj="integration-card:epr:apm:featured').click(); + cy.get('[aria-selected="true"]').contains('Elastic APM in Fleet'); + cy.contains('Elastic APM now available in Fleet!'); + cy.contains('APM integration'); + }); + + it('should display no APM server detected when checking the apm server status', () => { + cy.intercept('POST', '/api/home/hits_status', { + count: 0, + }).as('hitsStatus'); + + cy.get('[data-test-subj="integration-card:epr:apm:featured').click(); + cy.contains('Check APM Server status').click(); + cy.wait('@hitsStatus'); + cy.contains( + 'No APM Server detected. Please make sure it is running and you have updated to 7.0 or higher.' + ); + }); + }); +}); From d047765c8b3cb79b433c84ea92d7cd20f4774be5 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Thu, 17 Feb 2022 13:17:36 +0100 Subject: [PATCH 055/104] ExecutionContext: encode all context fields when converting to header (#125783) * ExecutionContext: encode all context fields when converting to header value * switch back to using the vis type name instead of title for the execution context name * adapt FTR tests * fix server-side tests too --- .../execution_context_container.test.ts | 30 ++++++++++++++-- .../execution_context_container.ts | 7 +++- .../integration_tests/tracing.test.ts | 36 +++++++++++++++++++ .../embeddable/visualize_embeddable.tsx | 2 +- .../tests/browser.ts | 17 ++++----- .../tests/server.ts | 4 +-- 6 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/core/server/execution_context/execution_context_container.test.ts b/src/core/server/execution_context/execution_context_container.test.ts index 8e9f46ee78a68..678c2e7134eca 100644 --- a/src/core/server/execution_context/execution_context_container.test.ts +++ b/src/core/server/execution_context/execution_context_container.test.ts @@ -91,16 +91,40 @@ describe('KibanaExecutionContext', () => { expect(value).toBe('type:name:41;child-test-type:child-test-name:42'); }); - it('returns an escaped string representation of provided execution contextStringified', () => { + it('returns an escaped string representation of provided execution context', () => { const context: KibanaExecutionContext = { id: 'Visualization☺漢字', + type: 'test☺type', + name: 'test漢name', + description: 'test字description', + }; + + const value = new ExecutionContextContainer(context).toString(); + expect(value).toBe( + 'test%E2%98%BAtype:test%E6%BC%A2name:Visualization%E2%98%BA%E6%BC%A2%E5%AD%97' + ); + }); + + it('returns an escaped string representation of provided execution context parent', () => { + const parentContext: KibanaExecutionContext = { + id: 'Dashboard☺漢字', + type: 'test☺type', + name: 'test漢name', + description: 'parent-descripton', + }; + const parentContainer = new ExecutionContextContainer(parentContext); + + const context: KibanaExecutionContext = { + id: 'Visualization', type: 'test-type', name: 'test-name', description: 'test-description', }; - const value = new ExecutionContextContainer(context).toString(); - expect(value).toBe('test-type:test-name:Visualization%E2%98%BA%E6%BC%A2%E5%AD%97'); + const value = new ExecutionContextContainer(context, parentContainer).toString(); + expect(value).toBe( + 'test%E2%98%BAtype:test%E6%BC%A2name:Dashboard%E2%98%BA%E6%BC%A2%E5%AD%97;test-type:test-name:Visualization' + ); }); it('trims a string representation of provided execution context if it is bigger max allowed size', () => { diff --git a/src/core/server/execution_context/execution_context_container.ts b/src/core/server/execution_context/execution_context_container.ts index 066248a26ad7b..de895bcff5ecb 100644 --- a/src/core/server/execution_context/execution_context_container.ts +++ b/src/core/server/execution_context/execution_context_container.ts @@ -50,18 +50,23 @@ export interface IExecutionContextContainer { } function stringify(ctx: KibanaExecutionContext): string { - const stringifiedCtx = `${ctx.type}:${ctx.name}:${encodeURIComponent(ctx.id!)}`; + const stringifiedCtx = `${encodeURIComponent(ctx.type)}:${encodeURIComponent( + ctx.name + )}:${encodeURIComponent(ctx.id!)}`; return ctx.child ? `${stringifiedCtx};${stringify(ctx.child)}` : stringifiedCtx; } export class ExecutionContextContainer implements IExecutionContextContainer { readonly #context: Readonly; + constructor(context: KibanaExecutionContext, parent?: IExecutionContextContainer) { this.#context = parent ? { ...parent.toJSON(), child: context } : context; } + toString(): string { return enforceMaxLength(stringify(this.#context)); } + toJSON() { return this.#context; } diff --git a/src/core/server/execution_context/integration_tests/tracing.test.ts b/src/core/server/execution_context/integration_tests/tracing.test.ts index c4fc88dd04dc9..15813529c358b 100644 --- a/src/core/server/execution_context/integration_tests/tracing.test.ts +++ b/src/core/server/execution_context/integration_tests/tracing.test.ts @@ -18,6 +18,13 @@ const parentContext = { description: 'test-description', }; +const withUtf8CharsContext = { + type: 'test字type', + name: 'test漢字name', + id: '9000☺', + description: 'test-description', +}; + describe('trace', () => { let esServer: kbnTestServer.TestElasticsearchUtils; let root: ReturnType; @@ -384,6 +391,35 @@ describe('trace', () => { expect(response.body).toEqual(parentContext); }); + it('supports UTF-8 characters', async () => { + const { http } = await root.setup(); + const { createRouter } = http; + + const router = createRouter(''); + router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { + const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping( + {}, + { meta: true } + ); + return res.ok({ body: headers || {} }); + }); + + await root.start(); + const response = await kbnTestServer.request + .get(root, '/execution-context') + .set('x-opaque-id', 'utf-test') + .set(new ExecutionContextContainer(withUtf8CharsContext).toHeader()) + .expect(200); + + const rawOpaqueId = response.body['x-opaque-id']; + expect(rawOpaqueId).toEqual( + 'utf-test;kibana:test%E5%AD%97type:test%E6%BC%A2%E5%AD%97name:9000%E2%98%BA' + ); + expect(decodeURIComponent(rawOpaqueId)).toEqual( + 'utf-test;kibana:test字type:test漢字name:9000☺' + ); + }); + it('execution context is the same for all the lifecycle events', async () => { const { executionContext, http } = await root.setup(); const { diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx index 24b451533532f..efc3bbf8314f8 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx @@ -401,7 +401,7 @@ export class VisualizeEmbeddable const parentContext = this.parent?.getInput().executionContext; const child: KibanaExecutionContext = { type: 'visualization', - name: this.vis.type.title, + name: this.vis.type.name, id: this.vis.id ?? 'an_unsaved_vis', description: this.vis.title || this.input.title || this.vis.type.name, url: this.output.editUrl, diff --git a/x-pack/test/functional_execution_context/tests/browser.ts b/x-pack/test/functional_execution_context/tests/browser.ts index e2578934cb00b..aa990dccda86c 100644 --- a/x-pack/test/functional_execution_context/tests/browser.ts +++ b/x-pack/test/functional_execution_context/tests/browser.ts @@ -252,7 +252,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { predicate: (record) => Boolean( record.http?.request?.id?.includes( - 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:TSVB:bcb63b50-4c89-11e8-b3d7-01146121b73d' + 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:metrics:bcb63b50-4c89-11e8-b3d7-01146121b73d' ) ), retry, @@ -269,7 +269,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d', child: { type: 'visualization', - name: 'TSVB', + name: 'metrics', id: 'bcb63b50-4c89-11e8-b3d7-01146121b73d', description: '[Flights] Delays & Cancellations', url: '/app/visualize#/edit/bcb63b50-4c89-11e8-b3d7-01146121b73d', @@ -279,13 +279,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); + // application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b it('propagates context for Vega visualizations', async () => { await assertLogContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: (record) => Boolean( record.http?.request?.id?.includes( - 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:Vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b' + 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b' ) ), retry, @@ -302,7 +303,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d', child: { type: 'visualization', - name: 'Vega', + name: 'vega', id: 'ed78a660-53a0-11e8-acbd-0be0ad9d822b', description: '[Flights] Airport Connections (Hover Over Airport)', url: '/app/visualize#/edit/ed78a660-53a0-11e8-acbd-0be0ad9d822b', @@ -318,7 +319,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { predicate: (record) => Boolean( record.http?.request?.id?.includes( - 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:Tag cloud:293b5a30-4c8f-11e8-b3d7-01146121b73d' + 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:tagcloud:293b5a30-4c8f-11e8-b3d7-01146121b73d' ) ), retry, @@ -335,7 +336,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d', child: { type: 'visualization', - name: 'Tag cloud', + name: 'tagcloud', id: '293b5a30-4c8f-11e8-b3d7-01146121b73d', description: '[Flights] Destination Weather', url: '/app/visualize#/edit/293b5a30-4c8f-11e8-b3d7-01146121b73d', @@ -351,7 +352,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { predicate: (record) => Boolean( record.http?.request?.id?.includes( - 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:Vertical bar:9886b410-4c8b-11e8-b3d7-01146121b73d' + 'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:histogram:9886b410-4c8b-11e8-b3d7-01146121b73d' ) ), retry, @@ -368,7 +369,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d', child: { type: 'visualization', - name: 'Vertical bar', + name: 'histogram', id: '9886b410-4c8b-11e8-b3d7-01146121b73d', description: '[Flights] Delay Buckets', url: '/app/visualize#/edit/9886b410-4c8b-11e8-b3d7-01146121b73d', diff --git a/x-pack/test/functional_execution_context/tests/server.ts b/x-pack/test/functional_execution_context/tests/server.ts index fd10118a03627..adb92fc6a2283 100644 --- a/x-pack/test/functional_execution_context/tests/server.ts +++ b/x-pack/test/functional_execution_context/tests/server.ts @@ -73,7 +73,7 @@ export default function ({ getService }: FtrProviderContext) { Boolean( // exclude part with taskId record.http?.request?.id?.includes( - `kibana:task manager:run alerting:test.executionContext:` + `kibana:task%20manager:run%20alerting%3Atest.executionContext:` ) ), retry, @@ -84,7 +84,7 @@ export default function ({ getService }: FtrProviderContext) { 'alerting execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: (record) => Boolean( - record.http?.request?.id?.includes(`alert:execute test.executionContext:${alertId}`) + record.http?.request?.id?.includes(`alert:execute%20test.executionContext:${alertId}`) ), retry, }); From d9a3e5e7f2c7325f727b5182ebefbfa062e8fa0e Mon Sep 17 00:00:00 2001 From: Vadim Kibana <82822460+vadimkibana@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:35:49 +0100 Subject: [PATCH 056/104] Delete Discover URL generator (#125824) * remove discover url generator * update mock * use locator in discover example plugin Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../main/services/discover_search_session.ts | 2 +- src/plugins/discover/public/constants.ts | 9 + src/plugins/discover/public/index.ts | 6 - src/plugins/discover/public/mocks.ts | 3 - src/plugins/discover/public/plugin.tsx | 36 +-- .../discover/public/url_generator.test.ts | 269 ------------------ src/plugins/discover/public/url_generator.ts | 162 ----------- .../drilldown.tsx | 6 +- 8 files changed, 15 insertions(+), 478 deletions(-) create mode 100644 src/plugins/discover/public/constants.ts delete mode 100644 src/plugins/discover/public/url_generator.test.ts delete mode 100644 src/plugins/discover/public/url_generator.ts diff --git a/src/plugins/discover/public/application/main/services/discover_search_session.ts b/src/plugins/discover/public/application/main/services/discover_search_session.ts index c864c06e4003c..98376d1e1391a 100644 --- a/src/plugins/discover/public/application/main/services/discover_search_session.ts +++ b/src/plugins/discover/public/application/main/services/discover_search_session.ts @@ -15,7 +15,7 @@ import { getQueryParams, removeQueryParam, } from '../../../../../kibana_utils/public'; -import { SEARCH_SESSION_ID_QUERY_PARAM } from '../../../url_generator'; +import { SEARCH_SESSION_ID_QUERY_PARAM } from '../../../constants'; export interface DiscoverSearchSessionManagerDeps { history: History; diff --git a/src/plugins/discover/public/constants.ts b/src/plugins/discover/public/constants.ts new file mode 100644 index 0000000000000..1a36ca6972a51 --- /dev/null +++ b/src/plugins/discover/public/constants.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const SEARCH_SESSION_ID_QUERY_PARAM = 'searchSessionId'; diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index 15707e4cda284..0ce755006b692 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -27,11 +27,5 @@ export type { ISearchEmbeddable, SearchInput } from './embeddable'; export { SEARCH_EMBEDDABLE_TYPE } from './embeddable'; export { loadSharingDataHelpers } from './utils'; -export type { DiscoverUrlGeneratorState } from './url_generator'; - -/** - * @deprecated - */ -export { DISCOVER_APP_URL_GENERATOR } from './url_generator'; export { DISCOVER_APP_LOCATOR } from './locator'; export type { DiscoverAppLocator, DiscoverAppLocatorParams } from './locator'; diff --git a/src/plugins/discover/public/mocks.ts b/src/plugins/discover/public/mocks.ts index 192c473f391a5..8e109c44864ac 100644 --- a/src/plugins/discover/public/mocks.ts +++ b/src/plugins/discover/public/mocks.ts @@ -24,9 +24,6 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { const startContract: Start = { - urlGenerator: { - createUrl: jest.fn(), - } as unknown as DiscoverStart['urlGenerator'], locator: sharePluginMock.createLocator(), }; return startContract; diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index e55158b0dad5e..aacbc1b58f3e9 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -22,7 +22,7 @@ import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public'; import { EmbeddableStart, EmbeddableSetup } from 'src/plugins/embeddable/public'; import { ChartsPluginStart } from 'src/plugins/charts/public'; import { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public'; -import { SharePluginStart, SharePluginSetup, UrlGeneratorContract } from 'src/plugins/share/public'; +import { SharePluginStart, SharePluginSetup } from 'src/plugins/share/public'; import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public'; import { HomePublicPluginSetup } from 'src/plugins/home/public'; import { Start as InspectorPublicPluginStart } from 'src/plugins/inspector/public'; @@ -31,7 +31,6 @@ import { DataPublicPluginStart, DataPublicPluginSetup, esFilters } from '../../d import { SavedObjectsStart } from '../../saved_objects/public'; import { createKbnUrlTracker } from '../../kibana_utils/public'; import { DEFAULT_APP_CATEGORIES } from '../../../core/public'; -import { UrlGeneratorState } from '../../share/public'; import { DocViewInput, DocViewInputFn } from './services/doc_views/doc_views_types'; import { DocViewsRegistry } from './services/doc_views/doc_views_registry'; import { @@ -45,12 +44,6 @@ import { } from './kibana_services'; import { registerFeature } from './register_feature'; import { buildServices } from './build_services'; -import { - DiscoverUrlGeneratorState, - DISCOVER_APP_URL_GENERATOR, - DiscoverUrlGenerator, - SEARCH_SESSION_ID_QUERY_PARAM, -} from './url_generator'; import { DiscoverAppLocatorDefinition, DiscoverAppLocator } from './locator'; import { SearchEmbeddableFactory } from './embeddable'; import { UsageCollectionSetup } from '../../usage_collection/public'; @@ -64,12 +57,7 @@ import { injectTruncateStyles } from './utils/truncate_styles'; import { DOC_TABLE_LEGACY, TRUNCATE_MAX_HEIGHT } from '../common'; import { DataViewEditorStart } from '../../../plugins/data_view_editor/public'; import { useDiscoverServices } from './utils/use_discover_services'; - -declare module '../../share/public' { - export interface UrlGeneratorStateMapping { - [DISCOVER_APP_URL_GENERATOR]: UrlGeneratorState; - } -} +import { SEARCH_SESSION_ID_QUERY_PARAM } from './constants'; const DocViewerLegacyTable = React.lazy( () => import('./services/doc_views/components/doc_viewer_table/legacy') @@ -123,11 +111,6 @@ export interface DiscoverSetup { } export interface DiscoverStart { - /** - * @deprecated Use URL locator instead. URL generator will be removed. - */ - readonly urlGenerator: undefined | UrlGeneratorContract<'DISCOVER_APP_URL_GENERATOR'>; - /** * `share` plugin URL locator for Discover app. Use it to generate links into * Discover application, for example, navigate: @@ -205,25 +188,11 @@ export class DiscoverPlugin private appStateUpdater = new BehaviorSubject(() => ({})); private docViewsRegistry: DocViewsRegistry | null = null; private stopUrlTracking: (() => void) | undefined = undefined; - - /** - * @deprecated - */ - private urlGenerator?: DiscoverStart['urlGenerator']; private locator?: DiscoverAppLocator; setup(core: CoreSetup, plugins: DiscoverSetupPlugins) { const baseUrl = core.http.basePath.prepend('/app/discover'); - if (plugins.share) { - this.urlGenerator = plugins.share.urlGenerators.registerUrlGenerator( - new DiscoverUrlGenerator({ - appBasePath: baseUrl, - useHash: core.uiSettings.get('state:storeInSessionStorage'), - }) - ); - } - if (plugins.share) { this.locator = plugins.share.url.locators.create( new DiscoverAppLocatorDefinition({ @@ -420,7 +389,6 @@ export class DiscoverPlugin injectTruncateStyles(core.uiSettings.get(TRUNCATE_MAX_HEIGHT)); return { - urlGenerator: this.urlGenerator, locator: this.locator, }; } diff --git a/src/plugins/discover/public/url_generator.test.ts b/src/plugins/discover/public/url_generator.test.ts deleted file mode 100644 index 765e8b36cc1ea..0000000000000 --- a/src/plugins/discover/public/url_generator.test.ts +++ /dev/null @@ -1,269 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { DiscoverUrlGenerator } from './url_generator'; -import { hashedItemStore, getStatesFromKbnUrl } from '../../kibana_utils/public'; -import { mockStorage } from '../../kibana_utils/public/storage/hashed_item_store/mock'; -import { FilterStateStore } from '../../data/common'; - -const appBasePath: string = 'xyz/app/discover'; -const indexPatternId: string = 'c367b774-a4c2-11ea-bb37-0242ac130002'; -const savedSearchId: string = '571aaf70-4c88-11e8-b3d7-01146121b73d'; - -interface SetupParams { - useHash?: boolean; -} - -const setup = async ({ useHash = false }: SetupParams = {}) => { - const generator = new DiscoverUrlGenerator({ - appBasePath, - useHash, - }); - - return { - generator, - }; -}; - -beforeEach(() => { - // @ts-expect-error - hashedItemStore.storage = mockStorage; -}); - -describe('Discover url generator', () => { - test('can create a link to Discover with no state and no saved search', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({}); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(url.startsWith(appBasePath)).toBe(true); - expect(_a).toEqual({}); - expect(_g).toEqual({}); - }); - - test('can create a link to a saved search in Discover', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ savedSearchId }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(url.startsWith(`${appBasePath}#/view/${savedSearchId}`)).toBe(true); - expect(_a).toEqual({}); - expect(_g).toEqual({}); - }); - - test('can specify specific index pattern', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - indexPatternId, - }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(_a).toEqual({ - index: indexPatternId, - }); - expect(_g).toEqual({}); - }); - - test('can specify specific time range', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - timeRange: { to: 'now', from: 'now-15m', mode: 'relative' }, - }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(_a).toEqual({}); - expect(_g).toEqual({ - time: { - from: 'now-15m', - mode: 'relative', - to: 'now', - }, - }); - }); - - test('can specify query', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - query: { - language: 'kuery', - query: 'foo', - }, - }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(_a).toEqual({ - query: { - language: 'kuery', - query: 'foo', - }, - }); - expect(_g).toEqual({}); - }); - - test('can specify local and global filters', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - filters: [ - { - meta: { - alias: 'foo', - disabled: false, - negate: false, - }, - $state: { - store: FilterStateStore.APP_STATE, - }, - }, - { - meta: { - alias: 'bar', - disabled: false, - negate: false, - }, - $state: { - store: FilterStateStore.GLOBAL_STATE, - }, - }, - ], - }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(_a).toEqual({ - filters: [ - { - $state: { - store: 'appState', - }, - meta: { - alias: 'foo', - disabled: false, - negate: false, - }, - }, - ], - }); - expect(_g).toEqual({ - filters: [ - { - $state: { - store: 'globalState', - }, - meta: { - alias: 'bar', - disabled: false, - negate: false, - }, - }, - ], - }); - }); - - test('can set refresh interval', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - refreshInterval: { - pause: false, - value: 666, - }, - }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(_a).toEqual({}); - expect(_g).toEqual({ - refreshInterval: { - pause: false, - value: 666, - }, - }); - }); - - test('can set time range', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - timeRange: { - from: 'now-3h', - to: 'now', - }, - }); - const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - - expect(_a).toEqual({}); - expect(_g).toEqual({ - time: { - from: 'now-3h', - to: 'now', - }, - }); - }); - - test('can specify a search session id', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - searchSessionId: '__test__', - }); - expect(url).toMatchInlineSnapshot(`"xyz/app/discover#/?_g=()&_a=()&searchSessionId=__test__"`); - expect(url).toContain('__test__'); - }); - - test('can specify columns, interval, sort and savedQuery', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - columns: ['_source'], - interval: 'auto', - sort: [['timestamp, asc']], - savedQuery: '__savedQueryId__', - }); - expect(url).toMatchInlineSnapshot( - `"xyz/app/discover#/?_g=()&_a=(columns:!(_source),interval:auto,savedQuery:__savedQueryId__,sort:!(!('timestamp,%20asc')))"` - ); - }); - - describe('useHash property', () => { - describe('when default useHash is set to false', () => { - test('when using default, sets index pattern ID in the generated URL', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(true); - }); - - test('when enabling useHash, does not set index pattern ID in the generated URL', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - useHash: true, - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(false); - }); - }); - - describe('when default useHash is set to true', () => { - test('when using default, does not set index pattern ID in the generated URL', async () => { - const { generator } = await setup({ useHash: true }); - const url = await generator.createUrl({ - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(false); - }); - - test('when disabling useHash, sets index pattern ID in the generated URL', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - useHash: false, - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(true); - }); - }); - }); -}); diff --git a/src/plugins/discover/public/url_generator.ts b/src/plugins/discover/public/url_generator.ts deleted file mode 100644 index 450ad15e3598b..0000000000000 --- a/src/plugins/discover/public/url_generator.ts +++ /dev/null @@ -1,162 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { UrlGeneratorsDefinition } from '../../share/public'; -import type { TimeRange, Filter, Query, QueryState, RefreshInterval } from '../../data/public'; -import { esFilters } from '../../data/public'; -import { setStateToKbnUrl } from '../../kibana_utils/public'; -import { VIEW_MODE } from './components/view_mode_toggle'; - -/** - * @deprecated - */ -export const DISCOVER_APP_URL_GENERATOR = 'DISCOVER_APP_URL_GENERATOR'; - -/** - * @deprecated - */ -export interface DiscoverUrlGeneratorState { - /** - * Optionally set saved search ID. - */ - savedSearchId?: string; - - /** - * Optionally set index pattern ID. - */ - indexPatternId?: string; - - /** - * Optionally set the time range in the time picker. - */ - timeRange?: TimeRange; - - /** - * Optionally set the refresh interval. - */ - refreshInterval?: RefreshInterval; - - /** - * Optionally apply filters. - */ - filters?: Filter[]; - - /** - * Optionally set a query. NOTE: if given and used in conjunction with `dashboardId`, and the - * saved dashboard has a query saved with it, this will _replace_ that query. - */ - query?: Query; - - /** - * If not given, will use the uiSettings configuration for `storeInSessionStorage`. useHash determines - * whether to hash the data in the url to avoid url length issues. - */ - useHash?: boolean; - - /** - * Background search session id - */ - searchSessionId?: string; - - /** - * Columns displayed in the table - */ - columns?: string[]; - - /** - * Used interval of the histogram - */ - interval?: string; - - /** - * Array of the used sorting [[field,direction],...] - */ - sort?: string[][]; - - /** - * id of the used saved query - */ - savedQuery?: string; - viewMode?: VIEW_MODE; - hideAggregatedPreview?: boolean; -} - -interface Params { - appBasePath: string; - useHash: boolean; -} - -export const SEARCH_SESSION_ID_QUERY_PARAM = 'searchSessionId'; - -/** - * @deprecated - */ -export class DiscoverUrlGenerator - implements UrlGeneratorsDefinition -{ - constructor(private readonly params: Params) {} - - public readonly id = DISCOVER_APP_URL_GENERATOR; - - public readonly createUrl = async ({ - useHash = this.params.useHash, - filters, - indexPatternId, - query, - refreshInterval, - savedSearchId, - timeRange, - searchSessionId, - columns, - savedQuery, - sort, - interval, - viewMode, - hideAggregatedPreview, - }: DiscoverUrlGeneratorState): Promise => { - const savedSearchPath = savedSearchId ? `view/${encodeURIComponent(savedSearchId)}` : ''; - const appState: { - query?: Query; - filters?: Filter[]; - index?: string; - columns?: string[]; - interval?: string; - sort?: string[][]; - savedQuery?: string; - viewMode?: VIEW_MODE; - hideAggregatedPreview?: boolean; - } = {}; - const queryState: QueryState = {}; - - if (query) appState.query = query; - if (filters && filters.length) - appState.filters = filters?.filter((f) => !esFilters.isFilterPinned(f)); - if (indexPatternId) appState.index = indexPatternId; - if (columns) appState.columns = columns; - if (savedQuery) appState.savedQuery = savedQuery; - if (sort) appState.sort = sort; - if (interval) appState.interval = interval; - - if (timeRange) queryState.time = timeRange; - if (filters && filters.length) - queryState.filters = filters?.filter((f) => esFilters.isFilterPinned(f)); - if (refreshInterval) queryState.refreshInterval = refreshInterval; - if (viewMode) appState.viewMode = viewMode; - if (hideAggregatedPreview) appState.hideAggregatedPreview = hideAggregatedPreview; - - let url = `${this.params.appBasePath}#/${savedSearchPath}`; - url = setStateToKbnUrl('_g', queryState, { useHash }, url); - url = setStateToKbnUrl('_a', appState, { useHash }, url); - - if (searchSessionId) { - url = `${url}&${SEARCH_SESSION_ID_QUERY_PARAM}=${searchSessionId}`; - } - - return url; - }; -} diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx index 91fb8552beed8..4635d4694ed1e 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx @@ -65,9 +65,9 @@ export class DashboardToDiscoverDrilldown }; private readonly getPath = async (config: Config, context: ActionContext): Promise => { - const { urlGenerator } = this.params.start().plugins.discover; + const { locator } = this.params.start().plugins.discover; - if (!urlGenerator) throw new Error('Discover URL generator not available.'); + if (!locator) throw new Error('Discover locator not available.'); let indexPatternId = !!config.customIndexPattern && !!config.indexPatternId ? config.indexPatternId : ''; @@ -79,7 +79,7 @@ export class DashboardToDiscoverDrilldown } } - return await urlGenerator.createUrl({ + return await locator.getUrl({ indexPatternId, }); }; From 0d2349158fd6a2d945129e57469cb79303b34c10 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 17 Feb 2022 15:14:25 +0200 Subject: [PATCH 057/104] [TSVB2Lens] Support top_hit of size 1 aggregation (#125766) * [TSVB2Lens] Support top_hit of size 1 aggregation * Add restriction to math aggregation * Support with quick function Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/trigger_action/get_series.test.ts | 36 +++++++++++++++++++ .../public/trigger_action/get_series.ts | 32 +++++++++++++++++ .../trigger_action/supported_metrics.ts | 4 +++ .../operations/definitions/last_value.tsx | 3 +- 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts index 12de3248794ab..3b01aeebb2dcf 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.test.ts @@ -325,6 +325,42 @@ describe('getSeries', () => { ]); }); + test('should return the correct formula config for a top_hit size 1 aggregation', () => { + const metric = [ + { + id: '12345', + type: 'top_hit', + field: 'day_of_week_i', + size: 1, + order_by: 'timestamp', + }, + ] as Metric[]; + const config = getSeries(metric); + expect(config).toStrictEqual([ + { + agg: 'last_value', + fieldName: 'day_of_week_i', + isFullReference: false, + params: { + sortField: 'timestamp', + }, + }, + ]); + }); + + test('should return null for a top_hit size >1 aggregation', () => { + const metric = [ + { + id: '12345', + type: 'top_hit', + field: 'day_of_week_i', + size: 2, + }, + ] as Metric[]; + const config = getSeries(metric); + expect(config).toBeNull(); + }); + test('should return the correct formula for the math aggregation with percentiles as variables', () => { const metric = [ { diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts index 021ccff7c8d71..5e7d39f3085f6 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/get_series.ts @@ -57,6 +57,15 @@ export const getSeries = (metrics: Metric[]): VisualizeEditorLayersContext['metr continue; } const currentMetric = metrics[layerMetricIdx]; + // We can only support top_hit with size 1 + if ( + (currentMetric.type === 'top_hit' && + currentMetric?.size && + Number(currentMetric?.size) !== 1) || + currentMetric?.order === 'asc' + ) { + return null; + } // should treat percentiles differently if (currentMetric.type === 'percentile') { @@ -152,6 +161,29 @@ export const getSeries = (metrics: Metric[]): VisualizeEditorLayersContext['metr metricsArray = getFormulaSeries(formula); break; } + case 'top_hit': { + const currentMetric = metrics[metricIdx]; + // We can only support top_hit with size 1 + if ( + (currentMetric?.size && Number(currentMetric?.size) !== 1) || + currentMetric?.order === 'asc' + ) { + return null; + } + const timeScale = getTimeScale(currentMetric); + metricsArray = [ + { + agg: aggregationMap.name, + isFullReference: aggregationMap.isFullReference, + fieldName: fieldName ?? 'document', + params: { + ...(timeScale && { timeScale }), + ...(currentMetric?.order_by && { sortField: currentMetric?.order_by }), + }, + }, + ]; + break; + } default: { const timeScale = getTimeScale(metrics[metricIdx]); metricsArray = [ diff --git a/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts b/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts index 74bb4e4d1dc15..354b60c31854a 100644 --- a/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts +++ b/src/plugins/vis_types/timeseries/public/trigger_action/supported_metrics.ts @@ -80,6 +80,10 @@ export const SUPPORTED_METRICS: { [key: string]: AggOptions } = { name: 'filter_ratio', isFullReference: false, }, + top_hit: { + name: 'last_value', + isFullReference: false, + }, math: { name: 'formula', isFullReference: true, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx index 1743bb057ba9b..3b31844bc4aed 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx @@ -166,6 +166,7 @@ export const lastValueOperation: OperationDefinition f.type === 'date')?.name; @@ -188,7 +189,7 @@ export const lastValueOperation: OperationDefinition Date: Thu, 17 Feb 2022 08:40:32 -0600 Subject: [PATCH 058/104] split kbn_archiver out of es_archiver (#125882) --- .../_indexpattern_with_unmapped_fields.ts | 3 ++ .../es_archiver/unmapped_fields/data.json | 45 ---------------- .../kbn_archiver/unmapped_fields.json | 51 +++++++++++++++++++ 3 files changed, 54 insertions(+), 45 deletions(-) create mode 100644 test/functional/fixtures/kbn_archiver/unmapped_fields.json diff --git a/test/functional/apps/discover/_indexpattern_with_unmapped_fields.ts b/test/functional/apps/discover/_indexpattern_with_unmapped_fields.ts index 2a1e60db541e8..c3982ba72824b 100644 --- a/test/functional/apps/discover/_indexpattern_with_unmapped_fields.ts +++ b/test/functional/apps/discover/_indexpattern_with_unmapped_fields.ts @@ -19,6 +19,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('index pattern with unmapped fields', () => { before(async () => { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/unmapped_fields'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/unmapped_fields'); await security.testUser.setRoles(['kibana_admin', 'test-index-unmapped-fields']); const fromTime = 'Jan 20, 2021 @ 00:00:00.000'; const toTime = 'Jan 25, 2021 @ 00:00:00.000'; @@ -35,6 +37,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async () => { await esArchiver.unload('test/functional/fixtures/es_archiver/unmapped_fields'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); await kibanaServer.uiSettings.unset('defaultIndex'); await kibanaServer.uiSettings.unset('discover:searchFieldsFromSource'); await kibanaServer.uiSettings.unset('timepicker:timeDefaults'); diff --git a/test/functional/fixtures/es_archiver/unmapped_fields/data.json b/test/functional/fixtures/es_archiver/unmapped_fields/data.json index 10c33280696b1..d23a5b83eb2c6 100644 --- a/test/functional/fixtures/es_archiver/unmapped_fields/data.json +++ b/test/functional/fixtures/es_archiver/unmapped_fields/data.json @@ -1,48 +1,3 @@ -{ - "type": "doc", - "value": { - "id": "search:cd43f5c2-h761-13f6-9486-733b1ac9221a", - "index": ".kibana", - "source": { - "search": { - "columns": [ - "_source" - ], - "description": "Existing Saved Search", - "hits": 4, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"index\": \"test-index-unmapped-fields\",\n \"highlightAll\": true,\n \"filter\": [],\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n }\n}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "Existing Saved Search", - "version": 1 - }, - "type": "search" - } - } -} - -{ - "type": "doc", - "value": { - "id": "index-pattern:test-index-unmapped-fields", - "index": ".kibana", - "source": { - "index-pattern": { - "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":4,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", - "timeFieldName": "timestamp", - "title": "test-index-unmapped-fields", - "fieldFormatMap": "{\"timestamp\":{\"id\":\"date\"}}" - }, - "type": "index-pattern" - }, - "type": "_doc" - } -} - { "type": "doc", "value": { diff --git a/test/functional/fixtures/kbn_archiver/unmapped_fields.json b/test/functional/fixtures/kbn_archiver/unmapped_fields.json new file mode 100644 index 0000000000000..aa1e464af5377 --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/unmapped_fields.json @@ -0,0 +1,51 @@ +{ + "attributes": { + "fieldFormatMap": "{\"timestamp\":{\"id\":\"date\"}}", + "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":4,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "timestamp", + "title": "test-index-unmapped-fields" + }, + "coreMigrationVersion": "7.17.1", + "id": "test-index-unmapped-fields", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "version": "WzEzLDJd" +} + +{ + "attributes": { + "columns": [ + "_source" + ], + "description": "Existing Saved Search", + "hits": 4, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "Existing Saved Search", + "version": 1 + }, + "coreMigrationVersion": "7.17.1", + "id": "cd43f5c2-h761-13f6-9486-733b1ac9221a", + "migrationVersion": { + "search": "7.9.3" + }, + "references": [ + { + "id": "test-index-unmapped-fields", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "version": "WzEyLDJd" +} \ No newline at end of file From f792e5d14baad0179705536fdfa77359d5d61b48 Mon Sep 17 00:00:00 2001 From: Lee Drengenberg Date: Thu, 17 Feb 2022 08:41:28 -0600 Subject: [PATCH 059/104] [Archive Migration] kbn_archive date_nanos (#125838) * kbn_archive date_nanos * kbn_archive date_nanos in context and discover * kbn_archiver more date_nanos tests * fix eslint error * fix lint error --- test/functional/apps/context/_date_nanos.ts | 3 + .../context/_date_nanos_custom_timestamp.ts | 5 ++ test/functional/apps/discover/_date_nanos.ts | 3 + .../apps/discover/_date_nanos_mixed.ts | 5 ++ .../fixtures/es_archiver/date_nanos/data.json | 44 ------------ .../es_archiver/date_nanos_custom/data.json | 19 ------ .../es_archiver/date_nanos_mixed/data.json | 48 ------------- .../fixtures/kbn_archiver/date_nanos.json | 51 ++++++++++++++ .../kbn_archiver/date_nanos_custom.json | 68 +++++++++++++++++++ .../kbn_archiver/date_nanos_mixed.json | 16 +++++ 10 files changed, 151 insertions(+), 111 deletions(-) create mode 100644 test/functional/fixtures/kbn_archiver/date_nanos.json create mode 100644 test/functional/fixtures/kbn_archiver/date_nanos_custom.json create mode 100644 test/functional/fixtures/kbn_archiver/date_nanos_mixed.json diff --git a/test/functional/apps/context/_date_nanos.ts b/test/functional/apps/context/_date_nanos.ts index 843230215492b..84793150b3edc 100644 --- a/test/functional/apps/context/_date_nanos.ts +++ b/test/functional/apps/context/_date_nanos.ts @@ -24,6 +24,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { before(async function () { await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos']); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/date_nanos'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/date_nanos'); await kibanaServer.uiSettings.replace({ defaultIndex: TEST_INDEX_PATTERN }); await kibanaServer.uiSettings.update({ 'context:defaultSize': `${TEST_DEFAULT_CONTEXT_SIZE}`, @@ -35,6 +37,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async function unloadMakelogs() { await security.testUser.restoreDefaults(); await esArchiver.unload('test/functional/fixtures/es_archiver/date_nanos'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); it('displays predessors - anchor - successors in right order ', async function () { diff --git a/test/functional/apps/context/_date_nanos_custom_timestamp.ts b/test/functional/apps/context/_date_nanos_custom_timestamp.ts index 42b0ec11a94e6..1c9417968f8ab 100644 --- a/test/functional/apps/context/_date_nanos_custom_timestamp.ts +++ b/test/functional/apps/context/_date_nanos_custom_timestamp.ts @@ -24,6 +24,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { before(async function () { await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos_custom']); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/date_nanos_custom'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/date_nanos_custom' + ); await kibanaServer.uiSettings.replace({ defaultIndex: TEST_INDEX_PATTERN }); await kibanaServer.uiSettings.update({ 'context:defaultSize': `${TEST_DEFAULT_CONTEXT_SIZE}`, @@ -46,6 +50,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async function () { await security.testUser.restoreDefaults(); await esArchiver.unload('test/functional/fixtures/es_archiver/date_nanos_custom'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); }); } diff --git a/test/functional/apps/discover/_date_nanos.ts b/test/functional/apps/discover/_date_nanos.ts index 81327d0744bfe..dcabb3dac0585 100644 --- a/test/functional/apps/discover/_date_nanos.ts +++ b/test/functional/apps/discover/_date_nanos.ts @@ -21,6 +21,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('date_nanos', function () { before(async function () { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/date_nanos'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/date_nanos'); await kibanaServer.uiSettings.replace({ defaultIndex: 'date-nanos' }); await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos']); await PageObjects.common.navigateToApp('discover'); @@ -30,6 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async function unloadMakelogs() { await security.testUser.restoreDefaults(); await esArchiver.unload('test/functional/fixtures/es_archiver/date_nanos'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); it('should show a timestamp with nanoseconds in the first result row', async function () { diff --git a/test/functional/apps/discover/_date_nanos_mixed.ts b/test/functional/apps/discover/_date_nanos_mixed.ts index 7d4104c3ac344..5cd72a67f36b1 100644 --- a/test/functional/apps/discover/_date_nanos_mixed.ts +++ b/test/functional/apps/discover/_date_nanos_mixed.ts @@ -21,6 +21,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('date_nanos_mixed', function () { before(async function () { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/date_nanos_mixed'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/date_nanos_mixed' + ); await kibanaServer.uiSettings.replace({ defaultIndex: 'timestamp-*' }); await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos_mixed']); await PageObjects.common.navigateToApp('discover'); @@ -30,6 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async () => { await security.testUser.restoreDefaults(); esArchiver.unload('test/functional/fixtures/es_archiver/date_nanos_mixed'); + await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); }); it('shows a list of records of indices with date & date_nanos fields in the right order', async function () { diff --git a/test/functional/fixtures/es_archiver/date_nanos/data.json b/test/functional/fixtures/es_archiver/date_nanos/data.json index 60feed23ee149..1638b6dd4190b 100644 --- a/test/functional/fixtures/es_archiver/date_nanos/data.json +++ b/test/functional/fixtures/es_archiver/date_nanos/data.json @@ -1,47 +1,3 @@ -{ - "type": "doc", - "value": { - "id": "index-pattern:date-nanos", - "index": ".kibana", - "source": { - "index-pattern": { - "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]", - "timeFieldName": "@timestamp", - "title": "date-nanos", - "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date_nanos\"}}" - }, - "type": "index-pattern" - } - } -} - -{ - "type": "doc", - "value": { - "id": "search:ab12e3c0-f231-11e6-9486-733b1ac9221a", - "index": ".kibana", - "source": { - "search": { - "columns": [ - "_source" - ], - "description": "A Saved Search Description", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\n \"index\": \"date-nanos\",\n \"highlightAll\": true,\n \"filter\": [],\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n }\n}" - }, - "sort": [ - "@timestamp", - "desc" - ], - "title": "A Saved Search", - "version": 1 - }, - "type": "search" - } - } -} - { "type": "doc", "value": { diff --git a/test/functional/fixtures/es_archiver/date_nanos_custom/data.json b/test/functional/fixtures/es_archiver/date_nanos_custom/data.json index 73cba70a8b93d..10b0db8beda72 100644 --- a/test/functional/fixtures/es_archiver/date_nanos_custom/data.json +++ b/test/functional/fixtures/es_archiver/date_nanos_custom/data.json @@ -1,22 +1,3 @@ -{ - "type": "doc", - "value": { - "id": "index-pattern:date_nanos_custom_timestamp", - "index": ".kibana", - "source": { - "index-pattern": { - "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"test\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"test.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"test\"}}},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date_nanos\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", - "timeFieldName": "timestamp", - "title": "date_nanos_custom_timestamp" - }, - "references": [ - ], - "type": "index-pattern", - "updated_at": "2020-01-09T21:43:20.283Z" - } - } -} - { "type": "doc", "value": { diff --git a/test/functional/fixtures/es_archiver/date_nanos_mixed/data.json b/test/functional/fixtures/es_archiver/date_nanos_mixed/data.json index abde15e2b08c4..d49a6fa2f2412 100644 --- a/test/functional/fixtures/es_archiver/date_nanos_mixed/data.json +++ b/test/functional/fixtures/es_archiver/date_nanos_mixed/data.json @@ -1,51 +1,3 @@ -{ - "type": "doc", - "value": { - "id": "index-pattern:timestamp-*", - "index": ".kibana", - "source": { - "index-pattern": { - "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\",\"date_nanos\"],\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", - "timeFieldName": "timestamp", - "title": "timestamp-*", - "fieldFormatMap": "{\"timestamp\":{\"id\":\"date_nanos\"}}" - }, - "type": "index-pattern" - }, - "type": "_doc" - } -} - -{ - "type": "doc", - "value": { - "id": "search:82116b30-d407-11e9-8004-932185690e7b", - "index": ".kibana", - "source": { - "search": { - "columns": [ - "_source" - ], - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"key\":\"number\",\"negate\":false,\"params\":{\"query\":123},\"type\":\"phrase\",\"value\":\"123\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"number\":{\"query\":123,\"type\":\"phrase\"}}}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" - }, - "sort": [ - [ - "@timestamp", - "desc" - ] - ], - "title": "New Saved Search", - "version": 1 - }, - "type": "search" - }, - "type": "_doc" - } -} - { "type": "doc", "value": { diff --git a/test/functional/fixtures/kbn_archiver/date_nanos.json b/test/functional/fixtures/kbn_archiver/date_nanos.json new file mode 100644 index 0000000000000..249f364887620 --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/date_nanos.json @@ -0,0 +1,51 @@ +{ + "attributes": { + "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date_nanos\"}}", + "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]", + "timeFieldName": "@timestamp", + "title": "date-nanos" + }, + "coreMigrationVersion": "7.17.1", + "id": "date-nanos", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "version": "WzM2LDJd" +} + +{ + "attributes": { + "columns": [ + "_source" + ], + "description": "A Saved Search Description", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "A Saved Search", + "version": 1 + }, + "coreMigrationVersion": "7.17.1", + "id": "ab12e3c0-f231-11e6-9486-733b1ac9221a", + "migrationVersion": { + "search": "7.9.3" + }, + "references": [ + { + "id": "date-nanos", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "version": "WzM3LDJd" +} \ No newline at end of file diff --git a/test/functional/fixtures/kbn_archiver/date_nanos_custom.json b/test/functional/fixtures/kbn_archiver/date_nanos_custom.json new file mode 100644 index 0000000000000..b789407a0ba88 --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/date_nanos_custom.json @@ -0,0 +1,68 @@ +{ + "attributes": { + "fieldFormatMap": "{\"@timestamp\":{\"id\":\"date_nanos\"}}", + "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]", + "timeFieldName": "@timestamp", + "title": "date-nanos" + }, + "coreMigrationVersion": "7.17.1", + "id": "date-nanos", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "version": "WzQyLDJd" +} + +{ + "attributes": { + "columns": [ + "_source" + ], + "description": "A Saved Search Description", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "A Saved Search", + "version": 1 + }, + "coreMigrationVersion": "7.17.1", + "id": "ab12e3c0-f231-11e6-9486-733b1ac9221a", + "migrationVersion": { + "search": "7.9.3" + }, + "references": [ + { + "id": "date-nanos", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "version": "WzQzLDJd" +} + +{ + "attributes": { + "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"test\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"test.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"test\"}}},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date_nanos\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "timestamp", + "title": "date_nanos_custom_timestamp" + }, + "coreMigrationVersion": "7.17.1", + "id": "date_nanos_custom_timestamp", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2020-01-09T21:43:20.283Z", + "version": "WzQ1LDJd" +} \ No newline at end of file diff --git a/test/functional/fixtures/kbn_archiver/date_nanos_mixed.json b/test/functional/fixtures/kbn_archiver/date_nanos_mixed.json new file mode 100644 index 0000000000000..6d528a382753f --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/date_nanos_mixed.json @@ -0,0 +1,16 @@ +{ + "attributes": { + "fieldFormatMap": "{\"timestamp\":{\"id\":\"date_nanos\"}}", + "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\",\"date_nanos\"],\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "timestamp", + "title": "timestamp-*" + }, + "coreMigrationVersion": "7.17.1", + "id": "timestamp-*", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "version": "WzU2LDJd" +} \ No newline at end of file From ea6be3c8d55d06876e2b80db5f793473c13e3af5 Mon Sep 17 00:00:00 2001 From: Stuart Tettemer Date: Thu, 17 Feb 2022 09:03:41 -0600 Subject: [PATCH 060/104] Update painless antlr grammar for fields API $-syntax (#125818) $('fieldname', ) was added in elasticsearch/#80518. This updated the ANTLR grammar so that the syntax check passes. painless_lexer.g4 adapted from elasticsearch/modules/lang-painless/src/main/antlr/PainlessLexer.g4 painless_parser.g4 adapted from elasticsearch/modules/lang-painless/src/main/antlr/PainlessParser.g4 Generated by running `npm run build:antlr4ts` from `packages/kbn-monaco` --- .../src/painless/antlr/painless_lexer.g4 | 1 + .../src/painless/antlr/painless_lexer.interp | 5 +- .../src/painless/antlr/painless_lexer.tokens | 290 +++---- .../src/painless/antlr/painless_lexer.ts | 811 +++++++++--------- .../src/painless/antlr/painless_parser.g4 | 2 +- .../src/painless/antlr/painless_parser.interp | 4 +- .../src/painless/antlr/painless_parser.tokens | 290 +++---- .../src/painless/antlr/painless_parser.ts | 470 +++++----- 8 files changed, 952 insertions(+), 921 deletions(-) diff --git a/packages/kbn-monaco/src/painless/antlr/painless_lexer.g4 b/packages/kbn-monaco/src/painless/antlr/painless_lexer.g4 index 56a8fada59aa5..71a495d113b76 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_lexer.g4 +++ b/packages/kbn-monaco/src/painless/antlr/painless_lexer.g4 @@ -17,6 +17,7 @@ LBRACE: '['; RBRACE: ']'; LP: '('; RP: ')'; +DOLLAR: '$'; // We switch modes after a dot to ensure there are not conflicts // between shortcuts and decimal values. Without the mode switch // shortcuts such as id.0.0 will fail because 0.0 will be interpreted diff --git a/packages/kbn-monaco/src/painless/antlr/painless_lexer.interp b/packages/kbn-monaco/src/painless/antlr/painless_lexer.interp index df5a0d5244124..ab7a7e876df8e 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_lexer.interp +++ b/packages/kbn-monaco/src/painless/antlr/painless_lexer.interp @@ -8,6 +8,7 @@ null ']' '(' ')' +'$' '.' '?.' ',' @@ -96,6 +97,7 @@ LBRACE RBRACE LP RP +DOLLAR DOT NSDOT COMMA @@ -183,6 +185,7 @@ LBRACE RBRACE LP RP +DOLLAR DOT NSDOT COMMA @@ -270,4 +273,4 @@ DEFAULT_MODE AFTER_DOT atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 87, 634, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 3, 2, 6, 2, 176, 10, 2, 13, 2, 14, 2, 177, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 186, 10, 3, 12, 3, 14, 3, 189, 11, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 196, 10, 3, 12, 3, 14, 3, 199, 11, 3, 3, 3, 3, 3, 5, 3, 203, 10, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 48, 3, 48, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 6, 73, 442, 10, 73, 13, 73, 14, 73, 443, 3, 73, 5, 73, 447, 10, 73, 3, 74, 3, 74, 3, 74, 6, 74, 452, 10, 74, 13, 74, 14, 74, 453, 3, 74, 5, 74, 457, 10, 74, 3, 75, 3, 75, 3, 75, 7, 75, 462, 10, 75, 12, 75, 14, 75, 465, 11, 75, 5, 75, 467, 10, 75, 3, 75, 5, 75, 470, 10, 75, 3, 76, 3, 76, 3, 76, 7, 76, 475, 10, 76, 12, 76, 14, 76, 478, 11, 76, 5, 76, 480, 10, 76, 3, 76, 3, 76, 6, 76, 484, 10, 76, 13, 76, 14, 76, 485, 5, 76, 488, 10, 76, 3, 76, 3, 76, 5, 76, 492, 10, 76, 3, 76, 6, 76, 495, 10, 76, 13, 76, 14, 76, 496, 5, 76, 499, 10, 76, 3, 76, 5, 76, 502, 10, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 7, 77, 510, 10, 77, 12, 77, 14, 77, 513, 11, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 7, 77, 522, 10, 77, 12, 77, 14, 77, 525, 11, 77, 3, 77, 5, 77, 528, 10, 77, 3, 78, 3, 78, 3, 78, 3, 78, 6, 78, 534, 10, 78, 13, 78, 14, 78, 535, 3, 78, 3, 78, 7, 78, 540, 10, 78, 12, 78, 14, 78, 543, 11, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 5, 82, 601, 10, 82, 3, 83, 3, 83, 3, 83, 3, 83, 3, 84, 3, 84, 7, 84, 609, 10, 84, 12, 84, 14, 84, 612, 11, 84, 3, 85, 3, 85, 3, 85, 7, 85, 617, 10, 85, 12, 85, 14, 85, 620, 11, 85, 5, 85, 622, 10, 85, 3, 85, 3, 85, 3, 86, 3, 86, 7, 86, 628, 10, 86, 12, 86, 14, 86, 631, 11, 86, 3, 86, 3, 86, 7, 187, 197, 511, 523, 535, 2, 2, 87, 4, 2, 3, 6, 2, 4, 8, 2, 5, 10, 2, 6, 12, 2, 7, 14, 2, 8, 16, 2, 9, 18, 2, 10, 20, 2, 11, 22, 2, 12, 24, 2, 13, 26, 2, 14, 28, 2, 15, 30, 2, 16, 32, 2, 17, 34, 2, 18, 36, 2, 19, 38, 2, 20, 40, 2, 21, 42, 2, 22, 44, 2, 23, 46, 2, 24, 48, 2, 25, 50, 2, 26, 52, 2, 27, 54, 2, 28, 56, 2, 29, 58, 2, 30, 60, 2, 31, 62, 2, 32, 64, 2, 33, 66, 2, 34, 68, 2, 35, 70, 2, 36, 72, 2, 37, 74, 2, 38, 76, 2, 39, 78, 2, 40, 80, 2, 41, 82, 2, 42, 84, 2, 43, 86, 2, 44, 88, 2, 45, 90, 2, 46, 92, 2, 47, 94, 2, 48, 96, 2, 49, 98, 2, 50, 100, 2, 51, 102, 2, 52, 104, 2, 53, 106, 2, 54, 108, 2, 55, 110, 2, 56, 112, 2, 57, 114, 2, 58, 116, 2, 59, 118, 2, 60, 120, 2, 61, 122, 2, 62, 124, 2, 63, 126, 2, 64, 128, 2, 65, 130, 2, 66, 132, 2, 67, 134, 2, 68, 136, 2, 69, 138, 2, 70, 140, 2, 71, 142, 2, 72, 144, 2, 73, 146, 2, 74, 148, 2, 75, 150, 2, 76, 152, 2, 77, 154, 2, 78, 156, 2, 79, 158, 2, 80, 160, 2, 81, 162, 2, 82, 164, 2, 83, 166, 2, 84, 168, 2, 85, 170, 2, 86, 172, 2, 87, 4, 2, 3, 21, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 3, 2, 50, 57, 4, 2, 78, 78, 110, 110, 4, 2, 90, 90, 122, 122, 5, 2, 50, 59, 67, 72, 99, 104, 3, 2, 51, 59, 3, 2, 50, 59, 8, 2, 70, 70, 72, 72, 78, 78, 102, 102, 104, 104, 110, 110, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 6, 2, 70, 70, 72, 72, 102, 102, 104, 104, 4, 2, 36, 36, 94, 94, 4, 2, 41, 41, 94, 94, 3, 2, 12, 12, 4, 2, 12, 12, 49, 49, 9, 2, 87, 87, 101, 101, 107, 107, 110, 111, 117, 117, 119, 119, 122, 122, 5, 2, 67, 92, 97, 97, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 2, 672, 2, 4, 3, 2, 2, 2, 2, 6, 3, 2, 2, 2, 2, 8, 3, 2, 2, 2, 2, 10, 3, 2, 2, 2, 2, 12, 3, 2, 2, 2, 2, 14, 3, 2, 2, 2, 2, 16, 3, 2, 2, 2, 2, 18, 3, 2, 2, 2, 2, 20, 3, 2, 2, 2, 2, 22, 3, 2, 2, 2, 2, 24, 3, 2, 2, 2, 2, 26, 3, 2, 2, 2, 2, 28, 3, 2, 2, 2, 2, 30, 3, 2, 2, 2, 2, 32, 3, 2, 2, 2, 2, 34, 3, 2, 2, 2, 2, 36, 3, 2, 2, 2, 2, 38, 3, 2, 2, 2, 2, 40, 3, 2, 2, 2, 2, 42, 3, 2, 2, 2, 2, 44, 3, 2, 2, 2, 2, 46, 3, 2, 2, 2, 2, 48, 3, 2, 2, 2, 2, 50, 3, 2, 2, 2, 2, 52, 3, 2, 2, 2, 2, 54, 3, 2, 2, 2, 2, 56, 3, 2, 2, 2, 2, 58, 3, 2, 2, 2, 2, 60, 3, 2, 2, 2, 2, 62, 3, 2, 2, 2, 2, 64, 3, 2, 2, 2, 2, 66, 3, 2, 2, 2, 2, 68, 3, 2, 2, 2, 2, 70, 3, 2, 2, 2, 2, 72, 3, 2, 2, 2, 2, 74, 3, 2, 2, 2, 2, 76, 3, 2, 2, 2, 2, 78, 3, 2, 2, 2, 2, 80, 3, 2, 2, 2, 2, 82, 3, 2, 2, 2, 2, 84, 3, 2, 2, 2, 2, 86, 3, 2, 2, 2, 2, 88, 3, 2, 2, 2, 2, 90, 3, 2, 2, 2, 2, 92, 3, 2, 2, 2, 2, 94, 3, 2, 2, 2, 2, 96, 3, 2, 2, 2, 2, 98, 3, 2, 2, 2, 2, 100, 3, 2, 2, 2, 2, 102, 3, 2, 2, 2, 2, 104, 3, 2, 2, 2, 2, 106, 3, 2, 2, 2, 2, 108, 3, 2, 2, 2, 2, 110, 3, 2, 2, 2, 2, 112, 3, 2, 2, 2, 2, 114, 3, 2, 2, 2, 2, 116, 3, 2, 2, 2, 2, 118, 3, 2, 2, 2, 2, 120, 3, 2, 2, 2, 2, 122, 3, 2, 2, 2, 2, 124, 3, 2, 2, 2, 2, 126, 3, 2, 2, 2, 2, 128, 3, 2, 2, 2, 2, 130, 3, 2, 2, 2, 2, 132, 3, 2, 2, 2, 2, 134, 3, 2, 2, 2, 2, 136, 3, 2, 2, 2, 2, 138, 3, 2, 2, 2, 2, 140, 3, 2, 2, 2, 2, 142, 3, 2, 2, 2, 2, 144, 3, 2, 2, 2, 2, 146, 3, 2, 2, 2, 2, 148, 3, 2, 2, 2, 2, 150, 3, 2, 2, 2, 2, 152, 3, 2, 2, 2, 2, 154, 3, 2, 2, 2, 2, 156, 3, 2, 2, 2, 2, 158, 3, 2, 2, 2, 2, 160, 3, 2, 2, 2, 2, 162, 3, 2, 2, 2, 2, 164, 3, 2, 2, 2, 2, 166, 3, 2, 2, 2, 2, 168, 3, 2, 2, 2, 3, 170, 3, 2, 2, 2, 3, 172, 3, 2, 2, 2, 4, 175, 3, 2, 2, 2, 6, 202, 3, 2, 2, 2, 8, 206, 3, 2, 2, 2, 10, 208, 3, 2, 2, 2, 12, 210, 3, 2, 2, 2, 14, 212, 3, 2, 2, 2, 16, 214, 3, 2, 2, 2, 18, 216, 3, 2, 2, 2, 20, 218, 3, 2, 2, 2, 22, 222, 3, 2, 2, 2, 24, 227, 3, 2, 2, 2, 26, 229, 3, 2, 2, 2, 28, 231, 3, 2, 2, 2, 30, 234, 3, 2, 2, 2, 32, 237, 3, 2, 2, 2, 34, 242, 3, 2, 2, 2, 36, 248, 3, 2, 2, 2, 38, 251, 3, 2, 2, 2, 40, 255, 3, 2, 2, 2, 42, 264, 3, 2, 2, 2, 44, 270, 3, 2, 2, 2, 46, 277, 3, 2, 2, 2, 48, 281, 3, 2, 2, 2, 50, 285, 3, 2, 2, 2, 52, 291, 3, 2, 2, 2, 54, 297, 3, 2, 2, 2, 56, 302, 3, 2, 2, 2, 58, 313, 3, 2, 2, 2, 60, 315, 3, 2, 2, 2, 62, 317, 3, 2, 2, 2, 64, 319, 3, 2, 2, 2, 66, 322, 3, 2, 2, 2, 68, 324, 3, 2, 2, 2, 70, 326, 3, 2, 2, 2, 72, 328, 3, 2, 2, 2, 74, 331, 3, 2, 2, 2, 76, 334, 3, 2, 2, 2, 78, 338, 3, 2, 2, 2, 80, 340, 3, 2, 2, 2, 82, 343, 3, 2, 2, 2, 84, 345, 3, 2, 2, 2, 86, 348, 3, 2, 2, 2, 88, 351, 3, 2, 2, 2, 90, 355, 3, 2, 2, 2, 92, 358, 3, 2, 2, 2, 94, 362, 3, 2, 2, 2, 96, 364, 3, 2, 2, 2, 98, 366, 3, 2, 2, 2, 100, 368, 3, 2, 2, 2, 102, 371, 3, 2, 2, 2, 104, 374, 3, 2, 2, 2, 106, 376, 3, 2, 2, 2, 108, 378, 3, 2, 2, 2, 110, 381, 3, 2, 2, 2, 112, 384, 3, 2, 2, 2, 114, 387, 3, 2, 2, 2, 116, 390, 3, 2, 2, 2, 118, 394, 3, 2, 2, 2, 120, 397, 3, 2, 2, 2, 122, 400, 3, 2, 2, 2, 124, 402, 3, 2, 2, 2, 126, 405, 3, 2, 2, 2, 128, 408, 3, 2, 2, 2, 130, 411, 3, 2, 2, 2, 132, 414, 3, 2, 2, 2, 134, 417, 3, 2, 2, 2, 136, 420, 3, 2, 2, 2, 138, 423, 3, 2, 2, 2, 140, 426, 3, 2, 2, 2, 142, 430, 3, 2, 2, 2, 144, 434, 3, 2, 2, 2, 146, 439, 3, 2, 2, 2, 148, 448, 3, 2, 2, 2, 150, 466, 3, 2, 2, 2, 152, 479, 3, 2, 2, 2, 154, 527, 3, 2, 2, 2, 156, 529, 3, 2, 2, 2, 158, 546, 3, 2, 2, 2, 160, 551, 3, 2, 2, 2, 162, 557, 3, 2, 2, 2, 164, 600, 3, 2, 2, 2, 166, 602, 3, 2, 2, 2, 168, 606, 3, 2, 2, 2, 170, 621, 3, 2, 2, 2, 172, 625, 3, 2, 2, 2, 174, 176, 9, 2, 2, 2, 175, 174, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 175, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 180, 8, 2, 2, 2, 180, 5, 3, 2, 2, 2, 181, 182, 7, 49, 2, 2, 182, 183, 7, 49, 2, 2, 183, 187, 3, 2, 2, 2, 184, 186, 11, 2, 2, 2, 185, 184, 3, 2, 2, 2, 186, 189, 3, 2, 2, 2, 187, 188, 3, 2, 2, 2, 187, 185, 3, 2, 2, 2, 188, 190, 3, 2, 2, 2, 189, 187, 3, 2, 2, 2, 190, 203, 9, 3, 2, 2, 191, 192, 7, 49, 2, 2, 192, 193, 7, 44, 2, 2, 193, 197, 3, 2, 2, 2, 194, 196, 11, 2, 2, 2, 195, 194, 3, 2, 2, 2, 196, 199, 3, 2, 2, 2, 197, 198, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 198, 200, 3, 2, 2, 2, 199, 197, 3, 2, 2, 2, 200, 201, 7, 44, 2, 2, 201, 203, 7, 49, 2, 2, 202, 181, 3, 2, 2, 2, 202, 191, 3, 2, 2, 2, 203, 204, 3, 2, 2, 2, 204, 205, 8, 3, 2, 2, 205, 7, 3, 2, 2, 2, 206, 207, 7, 125, 2, 2, 207, 9, 3, 2, 2, 2, 208, 209, 7, 127, 2, 2, 209, 11, 3, 2, 2, 2, 210, 211, 7, 93, 2, 2, 211, 13, 3, 2, 2, 2, 212, 213, 7, 95, 2, 2, 213, 15, 3, 2, 2, 2, 214, 215, 7, 42, 2, 2, 215, 17, 3, 2, 2, 2, 216, 217, 7, 43, 2, 2, 217, 19, 3, 2, 2, 2, 218, 219, 7, 48, 2, 2, 219, 220, 3, 2, 2, 2, 220, 221, 8, 10, 3, 2, 221, 21, 3, 2, 2, 2, 222, 223, 7, 65, 2, 2, 223, 224, 7, 48, 2, 2, 224, 225, 3, 2, 2, 2, 225, 226, 8, 11, 3, 2, 226, 23, 3, 2, 2, 2, 227, 228, 7, 46, 2, 2, 228, 25, 3, 2, 2, 2, 229, 230, 7, 61, 2, 2, 230, 27, 3, 2, 2, 2, 231, 232, 7, 107, 2, 2, 232, 233, 7, 104, 2, 2, 233, 29, 3, 2, 2, 2, 234, 235, 7, 107, 2, 2, 235, 236, 7, 112, 2, 2, 236, 31, 3, 2, 2, 2, 237, 238, 7, 103, 2, 2, 238, 239, 7, 110, 2, 2, 239, 240, 7, 117, 2, 2, 240, 241, 7, 103, 2, 2, 241, 33, 3, 2, 2, 2, 242, 243, 7, 121, 2, 2, 243, 244, 7, 106, 2, 2, 244, 245, 7, 107, 2, 2, 245, 246, 7, 110, 2, 2, 246, 247, 7, 103, 2, 2, 247, 35, 3, 2, 2, 2, 248, 249, 7, 102, 2, 2, 249, 250, 7, 113, 2, 2, 250, 37, 3, 2, 2, 2, 251, 252, 7, 104, 2, 2, 252, 253, 7, 113, 2, 2, 253, 254, 7, 116, 2, 2, 254, 39, 3, 2, 2, 2, 255, 256, 7, 101, 2, 2, 256, 257, 7, 113, 2, 2, 257, 258, 7, 112, 2, 2, 258, 259, 7, 118, 2, 2, 259, 260, 7, 107, 2, 2, 260, 261, 7, 112, 2, 2, 261, 262, 7, 119, 2, 2, 262, 263, 7, 103, 2, 2, 263, 41, 3, 2, 2, 2, 264, 265, 7, 100, 2, 2, 265, 266, 7, 116, 2, 2, 266, 267, 7, 103, 2, 2, 267, 268, 7, 99, 2, 2, 268, 269, 7, 109, 2, 2, 269, 43, 3, 2, 2, 2, 270, 271, 7, 116, 2, 2, 271, 272, 7, 103, 2, 2, 272, 273, 7, 118, 2, 2, 273, 274, 7, 119, 2, 2, 274, 275, 7, 116, 2, 2, 275, 276, 7, 112, 2, 2, 276, 45, 3, 2, 2, 2, 277, 278, 7, 112, 2, 2, 278, 279, 7, 103, 2, 2, 279, 280, 7, 121, 2, 2, 280, 47, 3, 2, 2, 2, 281, 282, 7, 118, 2, 2, 282, 283, 7, 116, 2, 2, 283, 284, 7, 123, 2, 2, 284, 49, 3, 2, 2, 2, 285, 286, 7, 101, 2, 2, 286, 287, 7, 99, 2, 2, 287, 288, 7, 118, 2, 2, 288, 289, 7, 101, 2, 2, 289, 290, 7, 106, 2, 2, 290, 51, 3, 2, 2, 2, 291, 292, 7, 118, 2, 2, 292, 293, 7, 106, 2, 2, 293, 294, 7, 116, 2, 2, 294, 295, 7, 113, 2, 2, 295, 296, 7, 121, 2, 2, 296, 53, 3, 2, 2, 2, 297, 298, 7, 118, 2, 2, 298, 299, 7, 106, 2, 2, 299, 300, 7, 107, 2, 2, 300, 301, 7, 117, 2, 2, 301, 55, 3, 2, 2, 2, 302, 303, 7, 107, 2, 2, 303, 304, 7, 112, 2, 2, 304, 305, 7, 117, 2, 2, 305, 306, 7, 118, 2, 2, 306, 307, 7, 99, 2, 2, 307, 308, 7, 112, 2, 2, 308, 309, 7, 101, 2, 2, 309, 310, 7, 103, 2, 2, 310, 311, 7, 113, 2, 2, 311, 312, 7, 104, 2, 2, 312, 57, 3, 2, 2, 2, 313, 314, 7, 35, 2, 2, 314, 59, 3, 2, 2, 2, 315, 316, 7, 128, 2, 2, 316, 61, 3, 2, 2, 2, 317, 318, 7, 44, 2, 2, 318, 63, 3, 2, 2, 2, 319, 320, 7, 49, 2, 2, 320, 321, 6, 32, 2, 2, 321, 65, 3, 2, 2, 2, 322, 323, 7, 39, 2, 2, 323, 67, 3, 2, 2, 2, 324, 325, 7, 45, 2, 2, 325, 69, 3, 2, 2, 2, 326, 327, 7, 47, 2, 2, 327, 71, 3, 2, 2, 2, 328, 329, 7, 62, 2, 2, 329, 330, 7, 62, 2, 2, 330, 73, 3, 2, 2, 2, 331, 332, 7, 64, 2, 2, 332, 333, 7, 64, 2, 2, 333, 75, 3, 2, 2, 2, 334, 335, 7, 64, 2, 2, 335, 336, 7, 64, 2, 2, 336, 337, 7, 64, 2, 2, 337, 77, 3, 2, 2, 2, 338, 339, 7, 62, 2, 2, 339, 79, 3, 2, 2, 2, 340, 341, 7, 62, 2, 2, 341, 342, 7, 63, 2, 2, 342, 81, 3, 2, 2, 2, 343, 344, 7, 64, 2, 2, 344, 83, 3, 2, 2, 2, 345, 346, 7, 64, 2, 2, 346, 347, 7, 63, 2, 2, 347, 85, 3, 2, 2, 2, 348, 349, 7, 63, 2, 2, 349, 350, 7, 63, 2, 2, 350, 87, 3, 2, 2, 2, 351, 352, 7, 63, 2, 2, 352, 353, 7, 63, 2, 2, 353, 354, 7, 63, 2, 2, 354, 89, 3, 2, 2, 2, 355, 356, 7, 35, 2, 2, 356, 357, 7, 63, 2, 2, 357, 91, 3, 2, 2, 2, 358, 359, 7, 35, 2, 2, 359, 360, 7, 63, 2, 2, 360, 361, 7, 63, 2, 2, 361, 93, 3, 2, 2, 2, 362, 363, 7, 40, 2, 2, 363, 95, 3, 2, 2, 2, 364, 365, 7, 96, 2, 2, 365, 97, 3, 2, 2, 2, 366, 367, 7, 126, 2, 2, 367, 99, 3, 2, 2, 2, 368, 369, 7, 40, 2, 2, 369, 370, 7, 40, 2, 2, 370, 101, 3, 2, 2, 2, 371, 372, 7, 126, 2, 2, 372, 373, 7, 126, 2, 2, 373, 103, 3, 2, 2, 2, 374, 375, 7, 65, 2, 2, 375, 105, 3, 2, 2, 2, 376, 377, 7, 60, 2, 2, 377, 107, 3, 2, 2, 2, 378, 379, 7, 65, 2, 2, 379, 380, 7, 60, 2, 2, 380, 109, 3, 2, 2, 2, 381, 382, 7, 60, 2, 2, 382, 383, 7, 60, 2, 2, 383, 111, 3, 2, 2, 2, 384, 385, 7, 47, 2, 2, 385, 386, 7, 64, 2, 2, 386, 113, 3, 2, 2, 2, 387, 388, 7, 63, 2, 2, 388, 389, 7, 128, 2, 2, 389, 115, 3, 2, 2, 2, 390, 391, 7, 63, 2, 2, 391, 392, 7, 63, 2, 2, 392, 393, 7, 128, 2, 2, 393, 117, 3, 2, 2, 2, 394, 395, 7, 45, 2, 2, 395, 396, 7, 45, 2, 2, 396, 119, 3, 2, 2, 2, 397, 398, 7, 47, 2, 2, 398, 399, 7, 47, 2, 2, 399, 121, 3, 2, 2, 2, 400, 401, 7, 63, 2, 2, 401, 123, 3, 2, 2, 2, 402, 403, 7, 45, 2, 2, 403, 404, 7, 63, 2, 2, 404, 125, 3, 2, 2, 2, 405, 406, 7, 47, 2, 2, 406, 407, 7, 63, 2, 2, 407, 127, 3, 2, 2, 2, 408, 409, 7, 44, 2, 2, 409, 410, 7, 63, 2, 2, 410, 129, 3, 2, 2, 2, 411, 412, 7, 49, 2, 2, 412, 413, 7, 63, 2, 2, 413, 131, 3, 2, 2, 2, 414, 415, 7, 39, 2, 2, 415, 416, 7, 63, 2, 2, 416, 133, 3, 2, 2, 2, 417, 418, 7, 40, 2, 2, 418, 419, 7, 63, 2, 2, 419, 135, 3, 2, 2, 2, 420, 421, 7, 96, 2, 2, 421, 422, 7, 63, 2, 2, 422, 137, 3, 2, 2, 2, 423, 424, 7, 126, 2, 2, 424, 425, 7, 63, 2, 2, 425, 139, 3, 2, 2, 2, 426, 427, 7, 62, 2, 2, 427, 428, 7, 62, 2, 2, 428, 429, 7, 63, 2, 2, 429, 141, 3, 2, 2, 2, 430, 431, 7, 64, 2, 2, 431, 432, 7, 64, 2, 2, 432, 433, 7, 63, 2, 2, 433, 143, 3, 2, 2, 2, 434, 435, 7, 64, 2, 2, 435, 436, 7, 64, 2, 2, 436, 437, 7, 64, 2, 2, 437, 438, 7, 63, 2, 2, 438, 145, 3, 2, 2, 2, 439, 441, 7, 50, 2, 2, 440, 442, 9, 4, 2, 2, 441, 440, 3, 2, 2, 2, 442, 443, 3, 2, 2, 2, 443, 441, 3, 2, 2, 2, 443, 444, 3, 2, 2, 2, 444, 446, 3, 2, 2, 2, 445, 447, 9, 5, 2, 2, 446, 445, 3, 2, 2, 2, 446, 447, 3, 2, 2, 2, 447, 147, 3, 2, 2, 2, 448, 449, 7, 50, 2, 2, 449, 451, 9, 6, 2, 2, 450, 452, 9, 7, 2, 2, 451, 450, 3, 2, 2, 2, 452, 453, 3, 2, 2, 2, 453, 451, 3, 2, 2, 2, 453, 454, 3, 2, 2, 2, 454, 456, 3, 2, 2, 2, 455, 457, 9, 5, 2, 2, 456, 455, 3, 2, 2, 2, 456, 457, 3, 2, 2, 2, 457, 149, 3, 2, 2, 2, 458, 467, 7, 50, 2, 2, 459, 463, 9, 8, 2, 2, 460, 462, 9, 9, 2, 2, 461, 460, 3, 2, 2, 2, 462, 465, 3, 2, 2, 2, 463, 461, 3, 2, 2, 2, 463, 464, 3, 2, 2, 2, 464, 467, 3, 2, 2, 2, 465, 463, 3, 2, 2, 2, 466, 458, 3, 2, 2, 2, 466, 459, 3, 2, 2, 2, 467, 469, 3, 2, 2, 2, 468, 470, 9, 10, 2, 2, 469, 468, 3, 2, 2, 2, 469, 470, 3, 2, 2, 2, 470, 151, 3, 2, 2, 2, 471, 480, 7, 50, 2, 2, 472, 476, 9, 8, 2, 2, 473, 475, 9, 9, 2, 2, 474, 473, 3, 2, 2, 2, 475, 478, 3, 2, 2, 2, 476, 474, 3, 2, 2, 2, 476, 477, 3, 2, 2, 2, 477, 480, 3, 2, 2, 2, 478, 476, 3, 2, 2, 2, 479, 471, 3, 2, 2, 2, 479, 472, 3, 2, 2, 2, 480, 487, 3, 2, 2, 2, 481, 483, 5, 20, 10, 2, 482, 484, 9, 9, 2, 2, 483, 482, 3, 2, 2, 2, 484, 485, 3, 2, 2, 2, 485, 483, 3, 2, 2, 2, 485, 486, 3, 2, 2, 2, 486, 488, 3, 2, 2, 2, 487, 481, 3, 2, 2, 2, 487, 488, 3, 2, 2, 2, 488, 498, 3, 2, 2, 2, 489, 491, 9, 11, 2, 2, 490, 492, 9, 12, 2, 2, 491, 490, 3, 2, 2, 2, 491, 492, 3, 2, 2, 2, 492, 494, 3, 2, 2, 2, 493, 495, 9, 9, 2, 2, 494, 493, 3, 2, 2, 2, 495, 496, 3, 2, 2, 2, 496, 494, 3, 2, 2, 2, 496, 497, 3, 2, 2, 2, 497, 499, 3, 2, 2, 2, 498, 489, 3, 2, 2, 2, 498, 499, 3, 2, 2, 2, 499, 501, 3, 2, 2, 2, 500, 502, 9, 13, 2, 2, 501, 500, 3, 2, 2, 2, 501, 502, 3, 2, 2, 2, 502, 153, 3, 2, 2, 2, 503, 511, 7, 36, 2, 2, 504, 505, 7, 94, 2, 2, 505, 510, 7, 36, 2, 2, 506, 507, 7, 94, 2, 2, 507, 510, 7, 94, 2, 2, 508, 510, 10, 14, 2, 2, 509, 504, 3, 2, 2, 2, 509, 506, 3, 2, 2, 2, 509, 508, 3, 2, 2, 2, 510, 513, 3, 2, 2, 2, 511, 512, 3, 2, 2, 2, 511, 509, 3, 2, 2, 2, 512, 514, 3, 2, 2, 2, 513, 511, 3, 2, 2, 2, 514, 528, 7, 36, 2, 2, 515, 523, 7, 41, 2, 2, 516, 517, 7, 94, 2, 2, 517, 522, 7, 41, 2, 2, 518, 519, 7, 94, 2, 2, 519, 522, 7, 94, 2, 2, 520, 522, 10, 15, 2, 2, 521, 516, 3, 2, 2, 2, 521, 518, 3, 2, 2, 2, 521, 520, 3, 2, 2, 2, 522, 525, 3, 2, 2, 2, 523, 524, 3, 2, 2, 2, 523, 521, 3, 2, 2, 2, 524, 526, 3, 2, 2, 2, 525, 523, 3, 2, 2, 2, 526, 528, 7, 41, 2, 2, 527, 503, 3, 2, 2, 2, 527, 515, 3, 2, 2, 2, 528, 155, 3, 2, 2, 2, 529, 533, 7, 49, 2, 2, 530, 531, 7, 94, 2, 2, 531, 534, 10, 16, 2, 2, 532, 534, 10, 17, 2, 2, 533, 530, 3, 2, 2, 2, 533, 532, 3, 2, 2, 2, 534, 535, 3, 2, 2, 2, 535, 536, 3, 2, 2, 2, 535, 533, 3, 2, 2, 2, 536, 537, 3, 2, 2, 2, 537, 541, 7, 49, 2, 2, 538, 540, 9, 18, 2, 2, 539, 538, 3, 2, 2, 2, 540, 543, 3, 2, 2, 2, 541, 539, 3, 2, 2, 2, 541, 542, 3, 2, 2, 2, 542, 544, 3, 2, 2, 2, 543, 541, 3, 2, 2, 2, 544, 545, 6, 78, 3, 2, 545, 157, 3, 2, 2, 2, 546, 547, 7, 118, 2, 2, 547, 548, 7, 116, 2, 2, 548, 549, 7, 119, 2, 2, 549, 550, 7, 103, 2, 2, 550, 159, 3, 2, 2, 2, 551, 552, 7, 104, 2, 2, 552, 553, 7, 99, 2, 2, 553, 554, 7, 110, 2, 2, 554, 555, 7, 117, 2, 2, 555, 556, 7, 103, 2, 2, 556, 161, 3, 2, 2, 2, 557, 558, 7, 112, 2, 2, 558, 559, 7, 119, 2, 2, 559, 560, 7, 110, 2, 2, 560, 561, 7, 110, 2, 2, 561, 163, 3, 2, 2, 2, 562, 563, 7, 100, 2, 2, 563, 564, 7, 113, 2, 2, 564, 565, 7, 113, 2, 2, 565, 566, 7, 110, 2, 2, 566, 567, 7, 103, 2, 2, 567, 568, 7, 99, 2, 2, 568, 601, 7, 112, 2, 2, 569, 570, 7, 100, 2, 2, 570, 571, 7, 123, 2, 2, 571, 572, 7, 118, 2, 2, 572, 601, 7, 103, 2, 2, 573, 574, 7, 117, 2, 2, 574, 575, 7, 106, 2, 2, 575, 576, 7, 113, 2, 2, 576, 577, 7, 116, 2, 2, 577, 601, 7, 118, 2, 2, 578, 579, 7, 101, 2, 2, 579, 580, 7, 106, 2, 2, 580, 581, 7, 99, 2, 2, 581, 601, 7, 116, 2, 2, 582, 583, 7, 107, 2, 2, 583, 584, 7, 112, 2, 2, 584, 601, 7, 118, 2, 2, 585, 586, 7, 110, 2, 2, 586, 587, 7, 113, 2, 2, 587, 588, 7, 112, 2, 2, 588, 601, 7, 105, 2, 2, 589, 590, 7, 104, 2, 2, 590, 591, 7, 110, 2, 2, 591, 592, 7, 113, 2, 2, 592, 593, 7, 99, 2, 2, 593, 601, 7, 118, 2, 2, 594, 595, 7, 102, 2, 2, 595, 596, 7, 113, 2, 2, 596, 597, 7, 119, 2, 2, 597, 598, 7, 100, 2, 2, 598, 599, 7, 110, 2, 2, 599, 601, 7, 103, 2, 2, 600, 562, 3, 2, 2, 2, 600, 569, 3, 2, 2, 2, 600, 573, 3, 2, 2, 2, 600, 578, 3, 2, 2, 2, 600, 582, 3, 2, 2, 2, 600, 585, 3, 2, 2, 2, 600, 589, 3, 2, 2, 2, 600, 594, 3, 2, 2, 2, 601, 165, 3, 2, 2, 2, 602, 603, 7, 102, 2, 2, 603, 604, 7, 103, 2, 2, 604, 605, 7, 104, 2, 2, 605, 167, 3, 2, 2, 2, 606, 610, 9, 19, 2, 2, 607, 609, 9, 20, 2, 2, 608, 607, 3, 2, 2, 2, 609, 612, 3, 2, 2, 2, 610, 608, 3, 2, 2, 2, 610, 611, 3, 2, 2, 2, 611, 169, 3, 2, 2, 2, 612, 610, 3, 2, 2, 2, 613, 622, 7, 50, 2, 2, 614, 618, 9, 8, 2, 2, 615, 617, 9, 9, 2, 2, 616, 615, 3, 2, 2, 2, 617, 620, 3, 2, 2, 2, 618, 616, 3, 2, 2, 2, 618, 619, 3, 2, 2, 2, 619, 622, 3, 2, 2, 2, 620, 618, 3, 2, 2, 2, 621, 613, 3, 2, 2, 2, 621, 614, 3, 2, 2, 2, 622, 623, 3, 2, 2, 2, 623, 624, 8, 85, 4, 2, 624, 171, 3, 2, 2, 2, 625, 629, 9, 19, 2, 2, 626, 628, 9, 20, 2, 2, 627, 626, 3, 2, 2, 2, 628, 631, 3, 2, 2, 2, 629, 627, 3, 2, 2, 2, 629, 630, 3, 2, 2, 2, 630, 632, 3, 2, 2, 2, 631, 629, 3, 2, 2, 2, 632, 633, 8, 86, 4, 2, 633, 173, 3, 2, 2, 2, 36, 2, 3, 177, 187, 197, 202, 443, 446, 453, 456, 463, 466, 469, 476, 479, 485, 487, 491, 496, 498, 501, 509, 511, 521, 523, 527, 533, 535, 541, 600, 610, 618, 621, 629, 5, 8, 2, 2, 4, 3, 2, 4, 2, 2] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 88, 638, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 3, 2, 6, 2, 178, 10, 2, 13, 2, 14, 2, 179, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 188, 10, 3, 12, 3, 14, 3, 191, 11, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 198, 10, 3, 12, 3, 14, 3, 201, 11, 3, 3, 3, 3, 3, 5, 3, 205, 10, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 49, 3, 49, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 6, 74, 446, 10, 74, 13, 74, 14, 74, 447, 3, 74, 5, 74, 451, 10, 74, 3, 75, 3, 75, 3, 75, 6, 75, 456, 10, 75, 13, 75, 14, 75, 457, 3, 75, 5, 75, 461, 10, 75, 3, 76, 3, 76, 3, 76, 7, 76, 466, 10, 76, 12, 76, 14, 76, 469, 11, 76, 5, 76, 471, 10, 76, 3, 76, 5, 76, 474, 10, 76, 3, 77, 3, 77, 3, 77, 7, 77, 479, 10, 77, 12, 77, 14, 77, 482, 11, 77, 5, 77, 484, 10, 77, 3, 77, 3, 77, 6, 77, 488, 10, 77, 13, 77, 14, 77, 489, 5, 77, 492, 10, 77, 3, 77, 3, 77, 5, 77, 496, 10, 77, 3, 77, 6, 77, 499, 10, 77, 13, 77, 14, 77, 500, 5, 77, 503, 10, 77, 3, 77, 5, 77, 506, 10, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 7, 78, 514, 10, 78, 12, 78, 14, 78, 517, 11, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 7, 78, 526, 10, 78, 12, 78, 14, 78, 529, 11, 78, 3, 78, 5, 78, 532, 10, 78, 3, 79, 3, 79, 3, 79, 3, 79, 6, 79, 538, 10, 79, 13, 79, 14, 79, 539, 3, 79, 3, 79, 7, 79, 544, 10, 79, 12, 79, 14, 79, 547, 11, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 5, 83, 605, 10, 83, 3, 84, 3, 84, 3, 84, 3, 84, 3, 85, 3, 85, 7, 85, 613, 10, 85, 12, 85, 14, 85, 616, 11, 85, 3, 86, 3, 86, 3, 86, 7, 86, 621, 10, 86, 12, 86, 14, 86, 624, 11, 86, 5, 86, 626, 10, 86, 3, 86, 3, 86, 3, 87, 3, 87, 7, 87, 632, 10, 87, 12, 87, 14, 87, 635, 11, 87, 3, 87, 3, 87, 7, 189, 199, 515, 527, 539, 2, 2, 88, 4, 2, 3, 6, 2, 4, 8, 2, 5, 10, 2, 6, 12, 2, 7, 14, 2, 8, 16, 2, 9, 18, 2, 10, 20, 2, 11, 22, 2, 12, 24, 2, 13, 26, 2, 14, 28, 2, 15, 30, 2, 16, 32, 2, 17, 34, 2, 18, 36, 2, 19, 38, 2, 20, 40, 2, 21, 42, 2, 22, 44, 2, 23, 46, 2, 24, 48, 2, 25, 50, 2, 26, 52, 2, 27, 54, 2, 28, 56, 2, 29, 58, 2, 30, 60, 2, 31, 62, 2, 32, 64, 2, 33, 66, 2, 34, 68, 2, 35, 70, 2, 36, 72, 2, 37, 74, 2, 38, 76, 2, 39, 78, 2, 40, 80, 2, 41, 82, 2, 42, 84, 2, 43, 86, 2, 44, 88, 2, 45, 90, 2, 46, 92, 2, 47, 94, 2, 48, 96, 2, 49, 98, 2, 50, 100, 2, 51, 102, 2, 52, 104, 2, 53, 106, 2, 54, 108, 2, 55, 110, 2, 56, 112, 2, 57, 114, 2, 58, 116, 2, 59, 118, 2, 60, 120, 2, 61, 122, 2, 62, 124, 2, 63, 126, 2, 64, 128, 2, 65, 130, 2, 66, 132, 2, 67, 134, 2, 68, 136, 2, 69, 138, 2, 70, 140, 2, 71, 142, 2, 72, 144, 2, 73, 146, 2, 74, 148, 2, 75, 150, 2, 76, 152, 2, 77, 154, 2, 78, 156, 2, 79, 158, 2, 80, 160, 2, 81, 162, 2, 82, 164, 2, 83, 166, 2, 84, 168, 2, 85, 170, 2, 86, 172, 2, 87, 174, 2, 88, 4, 2, 3, 21, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 3, 2, 50, 57, 4, 2, 78, 78, 110, 110, 4, 2, 90, 90, 122, 122, 5, 2, 50, 59, 67, 72, 99, 104, 3, 2, 51, 59, 3, 2, 50, 59, 8, 2, 70, 70, 72, 72, 78, 78, 102, 102, 104, 104, 110, 110, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 6, 2, 70, 70, 72, 72, 102, 102, 104, 104, 4, 2, 36, 36, 94, 94, 4, 2, 41, 41, 94, 94, 3, 2, 12, 12, 4, 2, 12, 12, 49, 49, 9, 2, 87, 87, 101, 101, 107, 107, 110, 111, 117, 117, 119, 119, 122, 122, 5, 2, 67, 92, 97, 97, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 2, 676, 2, 4, 3, 2, 2, 2, 2, 6, 3, 2, 2, 2, 2, 8, 3, 2, 2, 2, 2, 10, 3, 2, 2, 2, 2, 12, 3, 2, 2, 2, 2, 14, 3, 2, 2, 2, 2, 16, 3, 2, 2, 2, 2, 18, 3, 2, 2, 2, 2, 20, 3, 2, 2, 2, 2, 22, 3, 2, 2, 2, 2, 24, 3, 2, 2, 2, 2, 26, 3, 2, 2, 2, 2, 28, 3, 2, 2, 2, 2, 30, 3, 2, 2, 2, 2, 32, 3, 2, 2, 2, 2, 34, 3, 2, 2, 2, 2, 36, 3, 2, 2, 2, 2, 38, 3, 2, 2, 2, 2, 40, 3, 2, 2, 2, 2, 42, 3, 2, 2, 2, 2, 44, 3, 2, 2, 2, 2, 46, 3, 2, 2, 2, 2, 48, 3, 2, 2, 2, 2, 50, 3, 2, 2, 2, 2, 52, 3, 2, 2, 2, 2, 54, 3, 2, 2, 2, 2, 56, 3, 2, 2, 2, 2, 58, 3, 2, 2, 2, 2, 60, 3, 2, 2, 2, 2, 62, 3, 2, 2, 2, 2, 64, 3, 2, 2, 2, 2, 66, 3, 2, 2, 2, 2, 68, 3, 2, 2, 2, 2, 70, 3, 2, 2, 2, 2, 72, 3, 2, 2, 2, 2, 74, 3, 2, 2, 2, 2, 76, 3, 2, 2, 2, 2, 78, 3, 2, 2, 2, 2, 80, 3, 2, 2, 2, 2, 82, 3, 2, 2, 2, 2, 84, 3, 2, 2, 2, 2, 86, 3, 2, 2, 2, 2, 88, 3, 2, 2, 2, 2, 90, 3, 2, 2, 2, 2, 92, 3, 2, 2, 2, 2, 94, 3, 2, 2, 2, 2, 96, 3, 2, 2, 2, 2, 98, 3, 2, 2, 2, 2, 100, 3, 2, 2, 2, 2, 102, 3, 2, 2, 2, 2, 104, 3, 2, 2, 2, 2, 106, 3, 2, 2, 2, 2, 108, 3, 2, 2, 2, 2, 110, 3, 2, 2, 2, 2, 112, 3, 2, 2, 2, 2, 114, 3, 2, 2, 2, 2, 116, 3, 2, 2, 2, 2, 118, 3, 2, 2, 2, 2, 120, 3, 2, 2, 2, 2, 122, 3, 2, 2, 2, 2, 124, 3, 2, 2, 2, 2, 126, 3, 2, 2, 2, 2, 128, 3, 2, 2, 2, 2, 130, 3, 2, 2, 2, 2, 132, 3, 2, 2, 2, 2, 134, 3, 2, 2, 2, 2, 136, 3, 2, 2, 2, 2, 138, 3, 2, 2, 2, 2, 140, 3, 2, 2, 2, 2, 142, 3, 2, 2, 2, 2, 144, 3, 2, 2, 2, 2, 146, 3, 2, 2, 2, 2, 148, 3, 2, 2, 2, 2, 150, 3, 2, 2, 2, 2, 152, 3, 2, 2, 2, 2, 154, 3, 2, 2, 2, 2, 156, 3, 2, 2, 2, 2, 158, 3, 2, 2, 2, 2, 160, 3, 2, 2, 2, 2, 162, 3, 2, 2, 2, 2, 164, 3, 2, 2, 2, 2, 166, 3, 2, 2, 2, 2, 168, 3, 2, 2, 2, 2, 170, 3, 2, 2, 2, 3, 172, 3, 2, 2, 2, 3, 174, 3, 2, 2, 2, 4, 177, 3, 2, 2, 2, 6, 204, 3, 2, 2, 2, 8, 208, 3, 2, 2, 2, 10, 210, 3, 2, 2, 2, 12, 212, 3, 2, 2, 2, 14, 214, 3, 2, 2, 2, 16, 216, 3, 2, 2, 2, 18, 218, 3, 2, 2, 2, 20, 220, 3, 2, 2, 2, 22, 222, 3, 2, 2, 2, 24, 226, 3, 2, 2, 2, 26, 231, 3, 2, 2, 2, 28, 233, 3, 2, 2, 2, 30, 235, 3, 2, 2, 2, 32, 238, 3, 2, 2, 2, 34, 241, 3, 2, 2, 2, 36, 246, 3, 2, 2, 2, 38, 252, 3, 2, 2, 2, 40, 255, 3, 2, 2, 2, 42, 259, 3, 2, 2, 2, 44, 268, 3, 2, 2, 2, 46, 274, 3, 2, 2, 2, 48, 281, 3, 2, 2, 2, 50, 285, 3, 2, 2, 2, 52, 289, 3, 2, 2, 2, 54, 295, 3, 2, 2, 2, 56, 301, 3, 2, 2, 2, 58, 306, 3, 2, 2, 2, 60, 317, 3, 2, 2, 2, 62, 319, 3, 2, 2, 2, 64, 321, 3, 2, 2, 2, 66, 323, 3, 2, 2, 2, 68, 326, 3, 2, 2, 2, 70, 328, 3, 2, 2, 2, 72, 330, 3, 2, 2, 2, 74, 332, 3, 2, 2, 2, 76, 335, 3, 2, 2, 2, 78, 338, 3, 2, 2, 2, 80, 342, 3, 2, 2, 2, 82, 344, 3, 2, 2, 2, 84, 347, 3, 2, 2, 2, 86, 349, 3, 2, 2, 2, 88, 352, 3, 2, 2, 2, 90, 355, 3, 2, 2, 2, 92, 359, 3, 2, 2, 2, 94, 362, 3, 2, 2, 2, 96, 366, 3, 2, 2, 2, 98, 368, 3, 2, 2, 2, 100, 370, 3, 2, 2, 2, 102, 372, 3, 2, 2, 2, 104, 375, 3, 2, 2, 2, 106, 378, 3, 2, 2, 2, 108, 380, 3, 2, 2, 2, 110, 382, 3, 2, 2, 2, 112, 385, 3, 2, 2, 2, 114, 388, 3, 2, 2, 2, 116, 391, 3, 2, 2, 2, 118, 394, 3, 2, 2, 2, 120, 398, 3, 2, 2, 2, 122, 401, 3, 2, 2, 2, 124, 404, 3, 2, 2, 2, 126, 406, 3, 2, 2, 2, 128, 409, 3, 2, 2, 2, 130, 412, 3, 2, 2, 2, 132, 415, 3, 2, 2, 2, 134, 418, 3, 2, 2, 2, 136, 421, 3, 2, 2, 2, 138, 424, 3, 2, 2, 2, 140, 427, 3, 2, 2, 2, 142, 430, 3, 2, 2, 2, 144, 434, 3, 2, 2, 2, 146, 438, 3, 2, 2, 2, 148, 443, 3, 2, 2, 2, 150, 452, 3, 2, 2, 2, 152, 470, 3, 2, 2, 2, 154, 483, 3, 2, 2, 2, 156, 531, 3, 2, 2, 2, 158, 533, 3, 2, 2, 2, 160, 550, 3, 2, 2, 2, 162, 555, 3, 2, 2, 2, 164, 561, 3, 2, 2, 2, 166, 604, 3, 2, 2, 2, 168, 606, 3, 2, 2, 2, 170, 610, 3, 2, 2, 2, 172, 625, 3, 2, 2, 2, 174, 629, 3, 2, 2, 2, 176, 178, 9, 2, 2, 2, 177, 176, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 181, 3, 2, 2, 2, 181, 182, 8, 2, 2, 2, 182, 5, 3, 2, 2, 2, 183, 184, 7, 49, 2, 2, 184, 185, 7, 49, 2, 2, 185, 189, 3, 2, 2, 2, 186, 188, 11, 2, 2, 2, 187, 186, 3, 2, 2, 2, 188, 191, 3, 2, 2, 2, 189, 190, 3, 2, 2, 2, 189, 187, 3, 2, 2, 2, 190, 192, 3, 2, 2, 2, 191, 189, 3, 2, 2, 2, 192, 205, 9, 3, 2, 2, 193, 194, 7, 49, 2, 2, 194, 195, 7, 44, 2, 2, 195, 199, 3, 2, 2, 2, 196, 198, 11, 2, 2, 2, 197, 196, 3, 2, 2, 2, 198, 201, 3, 2, 2, 2, 199, 200, 3, 2, 2, 2, 199, 197, 3, 2, 2, 2, 200, 202, 3, 2, 2, 2, 201, 199, 3, 2, 2, 2, 202, 203, 7, 44, 2, 2, 203, 205, 7, 49, 2, 2, 204, 183, 3, 2, 2, 2, 204, 193, 3, 2, 2, 2, 205, 206, 3, 2, 2, 2, 206, 207, 8, 3, 2, 2, 207, 7, 3, 2, 2, 2, 208, 209, 7, 125, 2, 2, 209, 9, 3, 2, 2, 2, 210, 211, 7, 127, 2, 2, 211, 11, 3, 2, 2, 2, 212, 213, 7, 93, 2, 2, 213, 13, 3, 2, 2, 2, 214, 215, 7, 95, 2, 2, 215, 15, 3, 2, 2, 2, 216, 217, 7, 42, 2, 2, 217, 17, 3, 2, 2, 2, 218, 219, 7, 43, 2, 2, 219, 19, 3, 2, 2, 2, 220, 221, 7, 38, 2, 2, 221, 21, 3, 2, 2, 2, 222, 223, 7, 48, 2, 2, 223, 224, 3, 2, 2, 2, 224, 225, 8, 11, 3, 2, 225, 23, 3, 2, 2, 2, 226, 227, 7, 65, 2, 2, 227, 228, 7, 48, 2, 2, 228, 229, 3, 2, 2, 2, 229, 230, 8, 12, 3, 2, 230, 25, 3, 2, 2, 2, 231, 232, 7, 46, 2, 2, 232, 27, 3, 2, 2, 2, 233, 234, 7, 61, 2, 2, 234, 29, 3, 2, 2, 2, 235, 236, 7, 107, 2, 2, 236, 237, 7, 104, 2, 2, 237, 31, 3, 2, 2, 2, 238, 239, 7, 107, 2, 2, 239, 240, 7, 112, 2, 2, 240, 33, 3, 2, 2, 2, 241, 242, 7, 103, 2, 2, 242, 243, 7, 110, 2, 2, 243, 244, 7, 117, 2, 2, 244, 245, 7, 103, 2, 2, 245, 35, 3, 2, 2, 2, 246, 247, 7, 121, 2, 2, 247, 248, 7, 106, 2, 2, 248, 249, 7, 107, 2, 2, 249, 250, 7, 110, 2, 2, 250, 251, 7, 103, 2, 2, 251, 37, 3, 2, 2, 2, 252, 253, 7, 102, 2, 2, 253, 254, 7, 113, 2, 2, 254, 39, 3, 2, 2, 2, 255, 256, 7, 104, 2, 2, 256, 257, 7, 113, 2, 2, 257, 258, 7, 116, 2, 2, 258, 41, 3, 2, 2, 2, 259, 260, 7, 101, 2, 2, 260, 261, 7, 113, 2, 2, 261, 262, 7, 112, 2, 2, 262, 263, 7, 118, 2, 2, 263, 264, 7, 107, 2, 2, 264, 265, 7, 112, 2, 2, 265, 266, 7, 119, 2, 2, 266, 267, 7, 103, 2, 2, 267, 43, 3, 2, 2, 2, 268, 269, 7, 100, 2, 2, 269, 270, 7, 116, 2, 2, 270, 271, 7, 103, 2, 2, 271, 272, 7, 99, 2, 2, 272, 273, 7, 109, 2, 2, 273, 45, 3, 2, 2, 2, 274, 275, 7, 116, 2, 2, 275, 276, 7, 103, 2, 2, 276, 277, 7, 118, 2, 2, 277, 278, 7, 119, 2, 2, 278, 279, 7, 116, 2, 2, 279, 280, 7, 112, 2, 2, 280, 47, 3, 2, 2, 2, 281, 282, 7, 112, 2, 2, 282, 283, 7, 103, 2, 2, 283, 284, 7, 121, 2, 2, 284, 49, 3, 2, 2, 2, 285, 286, 7, 118, 2, 2, 286, 287, 7, 116, 2, 2, 287, 288, 7, 123, 2, 2, 288, 51, 3, 2, 2, 2, 289, 290, 7, 101, 2, 2, 290, 291, 7, 99, 2, 2, 291, 292, 7, 118, 2, 2, 292, 293, 7, 101, 2, 2, 293, 294, 7, 106, 2, 2, 294, 53, 3, 2, 2, 2, 295, 296, 7, 118, 2, 2, 296, 297, 7, 106, 2, 2, 297, 298, 7, 116, 2, 2, 298, 299, 7, 113, 2, 2, 299, 300, 7, 121, 2, 2, 300, 55, 3, 2, 2, 2, 301, 302, 7, 118, 2, 2, 302, 303, 7, 106, 2, 2, 303, 304, 7, 107, 2, 2, 304, 305, 7, 117, 2, 2, 305, 57, 3, 2, 2, 2, 306, 307, 7, 107, 2, 2, 307, 308, 7, 112, 2, 2, 308, 309, 7, 117, 2, 2, 309, 310, 7, 118, 2, 2, 310, 311, 7, 99, 2, 2, 311, 312, 7, 112, 2, 2, 312, 313, 7, 101, 2, 2, 313, 314, 7, 103, 2, 2, 314, 315, 7, 113, 2, 2, 315, 316, 7, 104, 2, 2, 316, 59, 3, 2, 2, 2, 317, 318, 7, 35, 2, 2, 318, 61, 3, 2, 2, 2, 319, 320, 7, 128, 2, 2, 320, 63, 3, 2, 2, 2, 321, 322, 7, 44, 2, 2, 322, 65, 3, 2, 2, 2, 323, 324, 7, 49, 2, 2, 324, 325, 6, 33, 2, 2, 325, 67, 3, 2, 2, 2, 326, 327, 7, 39, 2, 2, 327, 69, 3, 2, 2, 2, 328, 329, 7, 45, 2, 2, 329, 71, 3, 2, 2, 2, 330, 331, 7, 47, 2, 2, 331, 73, 3, 2, 2, 2, 332, 333, 7, 62, 2, 2, 333, 334, 7, 62, 2, 2, 334, 75, 3, 2, 2, 2, 335, 336, 7, 64, 2, 2, 336, 337, 7, 64, 2, 2, 337, 77, 3, 2, 2, 2, 338, 339, 7, 64, 2, 2, 339, 340, 7, 64, 2, 2, 340, 341, 7, 64, 2, 2, 341, 79, 3, 2, 2, 2, 342, 343, 7, 62, 2, 2, 343, 81, 3, 2, 2, 2, 344, 345, 7, 62, 2, 2, 345, 346, 7, 63, 2, 2, 346, 83, 3, 2, 2, 2, 347, 348, 7, 64, 2, 2, 348, 85, 3, 2, 2, 2, 349, 350, 7, 64, 2, 2, 350, 351, 7, 63, 2, 2, 351, 87, 3, 2, 2, 2, 352, 353, 7, 63, 2, 2, 353, 354, 7, 63, 2, 2, 354, 89, 3, 2, 2, 2, 355, 356, 7, 63, 2, 2, 356, 357, 7, 63, 2, 2, 357, 358, 7, 63, 2, 2, 358, 91, 3, 2, 2, 2, 359, 360, 7, 35, 2, 2, 360, 361, 7, 63, 2, 2, 361, 93, 3, 2, 2, 2, 362, 363, 7, 35, 2, 2, 363, 364, 7, 63, 2, 2, 364, 365, 7, 63, 2, 2, 365, 95, 3, 2, 2, 2, 366, 367, 7, 40, 2, 2, 367, 97, 3, 2, 2, 2, 368, 369, 7, 96, 2, 2, 369, 99, 3, 2, 2, 2, 370, 371, 7, 126, 2, 2, 371, 101, 3, 2, 2, 2, 372, 373, 7, 40, 2, 2, 373, 374, 7, 40, 2, 2, 374, 103, 3, 2, 2, 2, 375, 376, 7, 126, 2, 2, 376, 377, 7, 126, 2, 2, 377, 105, 3, 2, 2, 2, 378, 379, 7, 65, 2, 2, 379, 107, 3, 2, 2, 2, 380, 381, 7, 60, 2, 2, 381, 109, 3, 2, 2, 2, 382, 383, 7, 65, 2, 2, 383, 384, 7, 60, 2, 2, 384, 111, 3, 2, 2, 2, 385, 386, 7, 60, 2, 2, 386, 387, 7, 60, 2, 2, 387, 113, 3, 2, 2, 2, 388, 389, 7, 47, 2, 2, 389, 390, 7, 64, 2, 2, 390, 115, 3, 2, 2, 2, 391, 392, 7, 63, 2, 2, 392, 393, 7, 128, 2, 2, 393, 117, 3, 2, 2, 2, 394, 395, 7, 63, 2, 2, 395, 396, 7, 63, 2, 2, 396, 397, 7, 128, 2, 2, 397, 119, 3, 2, 2, 2, 398, 399, 7, 45, 2, 2, 399, 400, 7, 45, 2, 2, 400, 121, 3, 2, 2, 2, 401, 402, 7, 47, 2, 2, 402, 403, 7, 47, 2, 2, 403, 123, 3, 2, 2, 2, 404, 405, 7, 63, 2, 2, 405, 125, 3, 2, 2, 2, 406, 407, 7, 45, 2, 2, 407, 408, 7, 63, 2, 2, 408, 127, 3, 2, 2, 2, 409, 410, 7, 47, 2, 2, 410, 411, 7, 63, 2, 2, 411, 129, 3, 2, 2, 2, 412, 413, 7, 44, 2, 2, 413, 414, 7, 63, 2, 2, 414, 131, 3, 2, 2, 2, 415, 416, 7, 49, 2, 2, 416, 417, 7, 63, 2, 2, 417, 133, 3, 2, 2, 2, 418, 419, 7, 39, 2, 2, 419, 420, 7, 63, 2, 2, 420, 135, 3, 2, 2, 2, 421, 422, 7, 40, 2, 2, 422, 423, 7, 63, 2, 2, 423, 137, 3, 2, 2, 2, 424, 425, 7, 96, 2, 2, 425, 426, 7, 63, 2, 2, 426, 139, 3, 2, 2, 2, 427, 428, 7, 126, 2, 2, 428, 429, 7, 63, 2, 2, 429, 141, 3, 2, 2, 2, 430, 431, 7, 62, 2, 2, 431, 432, 7, 62, 2, 2, 432, 433, 7, 63, 2, 2, 433, 143, 3, 2, 2, 2, 434, 435, 7, 64, 2, 2, 435, 436, 7, 64, 2, 2, 436, 437, 7, 63, 2, 2, 437, 145, 3, 2, 2, 2, 438, 439, 7, 64, 2, 2, 439, 440, 7, 64, 2, 2, 440, 441, 7, 64, 2, 2, 441, 442, 7, 63, 2, 2, 442, 147, 3, 2, 2, 2, 443, 445, 7, 50, 2, 2, 444, 446, 9, 4, 2, 2, 445, 444, 3, 2, 2, 2, 446, 447, 3, 2, 2, 2, 447, 445, 3, 2, 2, 2, 447, 448, 3, 2, 2, 2, 448, 450, 3, 2, 2, 2, 449, 451, 9, 5, 2, 2, 450, 449, 3, 2, 2, 2, 450, 451, 3, 2, 2, 2, 451, 149, 3, 2, 2, 2, 452, 453, 7, 50, 2, 2, 453, 455, 9, 6, 2, 2, 454, 456, 9, 7, 2, 2, 455, 454, 3, 2, 2, 2, 456, 457, 3, 2, 2, 2, 457, 455, 3, 2, 2, 2, 457, 458, 3, 2, 2, 2, 458, 460, 3, 2, 2, 2, 459, 461, 9, 5, 2, 2, 460, 459, 3, 2, 2, 2, 460, 461, 3, 2, 2, 2, 461, 151, 3, 2, 2, 2, 462, 471, 7, 50, 2, 2, 463, 467, 9, 8, 2, 2, 464, 466, 9, 9, 2, 2, 465, 464, 3, 2, 2, 2, 466, 469, 3, 2, 2, 2, 467, 465, 3, 2, 2, 2, 467, 468, 3, 2, 2, 2, 468, 471, 3, 2, 2, 2, 469, 467, 3, 2, 2, 2, 470, 462, 3, 2, 2, 2, 470, 463, 3, 2, 2, 2, 471, 473, 3, 2, 2, 2, 472, 474, 9, 10, 2, 2, 473, 472, 3, 2, 2, 2, 473, 474, 3, 2, 2, 2, 474, 153, 3, 2, 2, 2, 475, 484, 7, 50, 2, 2, 476, 480, 9, 8, 2, 2, 477, 479, 9, 9, 2, 2, 478, 477, 3, 2, 2, 2, 479, 482, 3, 2, 2, 2, 480, 478, 3, 2, 2, 2, 480, 481, 3, 2, 2, 2, 481, 484, 3, 2, 2, 2, 482, 480, 3, 2, 2, 2, 483, 475, 3, 2, 2, 2, 483, 476, 3, 2, 2, 2, 484, 491, 3, 2, 2, 2, 485, 487, 5, 22, 11, 2, 486, 488, 9, 9, 2, 2, 487, 486, 3, 2, 2, 2, 488, 489, 3, 2, 2, 2, 489, 487, 3, 2, 2, 2, 489, 490, 3, 2, 2, 2, 490, 492, 3, 2, 2, 2, 491, 485, 3, 2, 2, 2, 491, 492, 3, 2, 2, 2, 492, 502, 3, 2, 2, 2, 493, 495, 9, 11, 2, 2, 494, 496, 9, 12, 2, 2, 495, 494, 3, 2, 2, 2, 495, 496, 3, 2, 2, 2, 496, 498, 3, 2, 2, 2, 497, 499, 9, 9, 2, 2, 498, 497, 3, 2, 2, 2, 499, 500, 3, 2, 2, 2, 500, 498, 3, 2, 2, 2, 500, 501, 3, 2, 2, 2, 501, 503, 3, 2, 2, 2, 502, 493, 3, 2, 2, 2, 502, 503, 3, 2, 2, 2, 503, 505, 3, 2, 2, 2, 504, 506, 9, 13, 2, 2, 505, 504, 3, 2, 2, 2, 505, 506, 3, 2, 2, 2, 506, 155, 3, 2, 2, 2, 507, 515, 7, 36, 2, 2, 508, 509, 7, 94, 2, 2, 509, 514, 7, 36, 2, 2, 510, 511, 7, 94, 2, 2, 511, 514, 7, 94, 2, 2, 512, 514, 10, 14, 2, 2, 513, 508, 3, 2, 2, 2, 513, 510, 3, 2, 2, 2, 513, 512, 3, 2, 2, 2, 514, 517, 3, 2, 2, 2, 515, 516, 3, 2, 2, 2, 515, 513, 3, 2, 2, 2, 516, 518, 3, 2, 2, 2, 517, 515, 3, 2, 2, 2, 518, 532, 7, 36, 2, 2, 519, 527, 7, 41, 2, 2, 520, 521, 7, 94, 2, 2, 521, 526, 7, 41, 2, 2, 522, 523, 7, 94, 2, 2, 523, 526, 7, 94, 2, 2, 524, 526, 10, 15, 2, 2, 525, 520, 3, 2, 2, 2, 525, 522, 3, 2, 2, 2, 525, 524, 3, 2, 2, 2, 526, 529, 3, 2, 2, 2, 527, 528, 3, 2, 2, 2, 527, 525, 3, 2, 2, 2, 528, 530, 3, 2, 2, 2, 529, 527, 3, 2, 2, 2, 530, 532, 7, 41, 2, 2, 531, 507, 3, 2, 2, 2, 531, 519, 3, 2, 2, 2, 532, 157, 3, 2, 2, 2, 533, 537, 7, 49, 2, 2, 534, 535, 7, 94, 2, 2, 535, 538, 10, 16, 2, 2, 536, 538, 10, 17, 2, 2, 537, 534, 3, 2, 2, 2, 537, 536, 3, 2, 2, 2, 538, 539, 3, 2, 2, 2, 539, 540, 3, 2, 2, 2, 539, 537, 3, 2, 2, 2, 540, 541, 3, 2, 2, 2, 541, 545, 7, 49, 2, 2, 542, 544, 9, 18, 2, 2, 543, 542, 3, 2, 2, 2, 544, 547, 3, 2, 2, 2, 545, 543, 3, 2, 2, 2, 545, 546, 3, 2, 2, 2, 546, 548, 3, 2, 2, 2, 547, 545, 3, 2, 2, 2, 548, 549, 6, 79, 3, 2, 549, 159, 3, 2, 2, 2, 550, 551, 7, 118, 2, 2, 551, 552, 7, 116, 2, 2, 552, 553, 7, 119, 2, 2, 553, 554, 7, 103, 2, 2, 554, 161, 3, 2, 2, 2, 555, 556, 7, 104, 2, 2, 556, 557, 7, 99, 2, 2, 557, 558, 7, 110, 2, 2, 558, 559, 7, 117, 2, 2, 559, 560, 7, 103, 2, 2, 560, 163, 3, 2, 2, 2, 561, 562, 7, 112, 2, 2, 562, 563, 7, 119, 2, 2, 563, 564, 7, 110, 2, 2, 564, 565, 7, 110, 2, 2, 565, 165, 3, 2, 2, 2, 566, 567, 7, 100, 2, 2, 567, 568, 7, 113, 2, 2, 568, 569, 7, 113, 2, 2, 569, 570, 7, 110, 2, 2, 570, 571, 7, 103, 2, 2, 571, 572, 7, 99, 2, 2, 572, 605, 7, 112, 2, 2, 573, 574, 7, 100, 2, 2, 574, 575, 7, 123, 2, 2, 575, 576, 7, 118, 2, 2, 576, 605, 7, 103, 2, 2, 577, 578, 7, 117, 2, 2, 578, 579, 7, 106, 2, 2, 579, 580, 7, 113, 2, 2, 580, 581, 7, 116, 2, 2, 581, 605, 7, 118, 2, 2, 582, 583, 7, 101, 2, 2, 583, 584, 7, 106, 2, 2, 584, 585, 7, 99, 2, 2, 585, 605, 7, 116, 2, 2, 586, 587, 7, 107, 2, 2, 587, 588, 7, 112, 2, 2, 588, 605, 7, 118, 2, 2, 589, 590, 7, 110, 2, 2, 590, 591, 7, 113, 2, 2, 591, 592, 7, 112, 2, 2, 592, 605, 7, 105, 2, 2, 593, 594, 7, 104, 2, 2, 594, 595, 7, 110, 2, 2, 595, 596, 7, 113, 2, 2, 596, 597, 7, 99, 2, 2, 597, 605, 7, 118, 2, 2, 598, 599, 7, 102, 2, 2, 599, 600, 7, 113, 2, 2, 600, 601, 7, 119, 2, 2, 601, 602, 7, 100, 2, 2, 602, 603, 7, 110, 2, 2, 603, 605, 7, 103, 2, 2, 604, 566, 3, 2, 2, 2, 604, 573, 3, 2, 2, 2, 604, 577, 3, 2, 2, 2, 604, 582, 3, 2, 2, 2, 604, 586, 3, 2, 2, 2, 604, 589, 3, 2, 2, 2, 604, 593, 3, 2, 2, 2, 604, 598, 3, 2, 2, 2, 605, 167, 3, 2, 2, 2, 606, 607, 7, 102, 2, 2, 607, 608, 7, 103, 2, 2, 608, 609, 7, 104, 2, 2, 609, 169, 3, 2, 2, 2, 610, 614, 9, 19, 2, 2, 611, 613, 9, 20, 2, 2, 612, 611, 3, 2, 2, 2, 613, 616, 3, 2, 2, 2, 614, 612, 3, 2, 2, 2, 614, 615, 3, 2, 2, 2, 615, 171, 3, 2, 2, 2, 616, 614, 3, 2, 2, 2, 617, 626, 7, 50, 2, 2, 618, 622, 9, 8, 2, 2, 619, 621, 9, 9, 2, 2, 620, 619, 3, 2, 2, 2, 621, 624, 3, 2, 2, 2, 622, 620, 3, 2, 2, 2, 622, 623, 3, 2, 2, 2, 623, 626, 3, 2, 2, 2, 624, 622, 3, 2, 2, 2, 625, 617, 3, 2, 2, 2, 625, 618, 3, 2, 2, 2, 626, 627, 3, 2, 2, 2, 627, 628, 8, 86, 4, 2, 628, 173, 3, 2, 2, 2, 629, 633, 9, 19, 2, 2, 630, 632, 9, 20, 2, 2, 631, 630, 3, 2, 2, 2, 632, 635, 3, 2, 2, 2, 633, 631, 3, 2, 2, 2, 633, 634, 3, 2, 2, 2, 634, 636, 3, 2, 2, 2, 635, 633, 3, 2, 2, 2, 636, 637, 8, 87, 4, 2, 637, 175, 3, 2, 2, 2, 36, 2, 3, 179, 189, 199, 204, 447, 450, 457, 460, 467, 470, 473, 480, 483, 489, 491, 495, 500, 502, 505, 513, 515, 525, 527, 531, 537, 539, 545, 604, 614, 622, 625, 633, 5, 8, 2, 2, 4, 3, 2, 4, 2, 2] \ No newline at end of file diff --git a/packages/kbn-monaco/src/painless/antlr/painless_lexer.tokens b/packages/kbn-monaco/src/painless/antlr/painless_lexer.tokens index ff62343c92ba5..3a1af2a5154d3 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_lexer.tokens +++ b/packages/kbn-monaco/src/painless/antlr/painless_lexer.tokens @@ -6,153 +6,155 @@ LBRACE=5 RBRACE=6 LP=7 RP=8 -DOT=9 -NSDOT=10 -COMMA=11 -SEMICOLON=12 -IF=13 -IN=14 -ELSE=15 -WHILE=16 -DO=17 -FOR=18 -CONTINUE=19 -BREAK=20 -RETURN=21 -NEW=22 -TRY=23 -CATCH=24 -THROW=25 -THIS=26 -INSTANCEOF=27 -BOOLNOT=28 -BWNOT=29 -MUL=30 -DIV=31 -REM=32 -ADD=33 -SUB=34 -LSH=35 -RSH=36 -USH=37 -LT=38 -LTE=39 -GT=40 -GTE=41 -EQ=42 -EQR=43 -NE=44 -NER=45 -BWAND=46 -XOR=47 -BWOR=48 -BOOLAND=49 -BOOLOR=50 -COND=51 -COLON=52 -ELVIS=53 -REF=54 -ARROW=55 -FIND=56 -MATCH=57 -INCR=58 -DECR=59 -ASSIGN=60 -AADD=61 -ASUB=62 -AMUL=63 -ADIV=64 -AREM=65 -AAND=66 -AXOR=67 -AOR=68 -ALSH=69 -ARSH=70 -AUSH=71 -OCTAL=72 -HEX=73 -INTEGER=74 -DECIMAL=75 -STRING=76 -REGEX=77 -TRUE=78 -FALSE=79 -NULL=80 -PRIMITIVE=81 -DEF=82 -ID=83 -DOTINTEGER=84 -DOTID=85 +DOLLAR=9 +DOT=10 +NSDOT=11 +COMMA=12 +SEMICOLON=13 +IF=14 +IN=15 +ELSE=16 +WHILE=17 +DO=18 +FOR=19 +CONTINUE=20 +BREAK=21 +RETURN=22 +NEW=23 +TRY=24 +CATCH=25 +THROW=26 +THIS=27 +INSTANCEOF=28 +BOOLNOT=29 +BWNOT=30 +MUL=31 +DIV=32 +REM=33 +ADD=34 +SUB=35 +LSH=36 +RSH=37 +USH=38 +LT=39 +LTE=40 +GT=41 +GTE=42 +EQ=43 +EQR=44 +NE=45 +NER=46 +BWAND=47 +XOR=48 +BWOR=49 +BOOLAND=50 +BOOLOR=51 +COND=52 +COLON=53 +ELVIS=54 +REF=55 +ARROW=56 +FIND=57 +MATCH=58 +INCR=59 +DECR=60 +ASSIGN=61 +AADD=62 +ASUB=63 +AMUL=64 +ADIV=65 +AREM=66 +AAND=67 +AXOR=68 +AOR=69 +ALSH=70 +ARSH=71 +AUSH=72 +OCTAL=73 +HEX=74 +INTEGER=75 +DECIMAL=76 +STRING=77 +REGEX=78 +TRUE=79 +FALSE=80 +NULL=81 +PRIMITIVE=82 +DEF=83 +ID=84 +DOTINTEGER=85 +DOTID=86 '{'=3 '}'=4 '['=5 ']'=6 '('=7 ')'=8 -'.'=9 -'?.'=10 -','=11 -';'=12 -'if'=13 -'in'=14 -'else'=15 -'while'=16 -'do'=17 -'for'=18 -'continue'=19 -'break'=20 -'return'=21 -'new'=22 -'try'=23 -'catch'=24 -'throw'=25 -'this'=26 -'instanceof'=27 -'!'=28 -'~'=29 -'*'=30 -'/'=31 -'%'=32 -'+'=33 -'-'=34 -'<<'=35 -'>>'=36 -'>>>'=37 -'<'=38 -'<='=39 -'>'=40 -'>='=41 -'=='=42 -'==='=43 -'!='=44 -'!=='=45 -'&'=46 -'^'=47 -'|'=48 -'&&'=49 -'||'=50 -'?'=51 -':'=52 -'?:'=53 -'::'=54 -'->'=55 -'=~'=56 -'==~'=57 -'++'=58 -'--'=59 -'='=60 -'+='=61 -'-='=62 -'*='=63 -'/='=64 -'%='=65 -'&='=66 -'^='=67 -'|='=68 -'<<='=69 -'>>='=70 -'>>>='=71 -'true'=78 -'false'=79 -'null'=80 -'def'=82 +'$'=9 +'.'=10 +'?.'=11 +','=12 +';'=13 +'if'=14 +'in'=15 +'else'=16 +'while'=17 +'do'=18 +'for'=19 +'continue'=20 +'break'=21 +'return'=22 +'new'=23 +'try'=24 +'catch'=25 +'throw'=26 +'this'=27 +'instanceof'=28 +'!'=29 +'~'=30 +'*'=31 +'/'=32 +'%'=33 +'+'=34 +'-'=35 +'<<'=36 +'>>'=37 +'>>>'=38 +'<'=39 +'<='=40 +'>'=41 +'>='=42 +'=='=43 +'==='=44 +'!='=45 +'!=='=46 +'&'=47 +'^'=48 +'|'=49 +'&&'=50 +'||'=51 +'?'=52 +':'=53 +'?:'=54 +'::'=55 +'->'=56 +'=~'=57 +'==~'=58 +'++'=59 +'--'=60 +'='=61 +'+='=62 +'-='=63 +'*='=64 +'/='=65 +'%='=66 +'&='=67 +'^='=68 +'|='=69 +'<<='=70 +'>>='=71 +'>>>='=72 +'true'=79 +'false'=80 +'null'=81 +'def'=83 diff --git a/packages/kbn-monaco/src/painless/antlr/painless_lexer.ts b/packages/kbn-monaco/src/painless/antlr/painless_lexer.ts index eb335c73d94b2..5c102850d89f7 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_lexer.ts +++ b/packages/kbn-monaco/src/painless/antlr/painless_lexer.ts @@ -25,83 +25,84 @@ export class painless_lexer extends Lexer { public static readonly RBRACE = 6; public static readonly LP = 7; public static readonly RP = 8; - public static readonly DOT = 9; - public static readonly NSDOT = 10; - public static readonly COMMA = 11; - public static readonly SEMICOLON = 12; - public static readonly IF = 13; - public static readonly IN = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly DO = 17; - public static readonly FOR = 18; - public static readonly CONTINUE = 19; - public static readonly BREAK = 20; - public static readonly RETURN = 21; - public static readonly NEW = 22; - public static readonly TRY = 23; - public static readonly CATCH = 24; - public static readonly THROW = 25; - public static readonly THIS = 26; - public static readonly INSTANCEOF = 27; - public static readonly BOOLNOT = 28; - public static readonly BWNOT = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly REM = 32; - public static readonly ADD = 33; - public static readonly SUB = 34; - public static readonly LSH = 35; - public static readonly RSH = 36; - public static readonly USH = 37; - public static readonly LT = 38; - public static readonly LTE = 39; - public static readonly GT = 40; - public static readonly GTE = 41; - public static readonly EQ = 42; - public static readonly EQR = 43; - public static readonly NE = 44; - public static readonly NER = 45; - public static readonly BWAND = 46; - public static readonly XOR = 47; - public static readonly BWOR = 48; - public static readonly BOOLAND = 49; - public static readonly BOOLOR = 50; - public static readonly COND = 51; - public static readonly COLON = 52; - public static readonly ELVIS = 53; - public static readonly REF = 54; - public static readonly ARROW = 55; - public static readonly FIND = 56; - public static readonly MATCH = 57; - public static readonly INCR = 58; - public static readonly DECR = 59; - public static readonly ASSIGN = 60; - public static readonly AADD = 61; - public static readonly ASUB = 62; - public static readonly AMUL = 63; - public static readonly ADIV = 64; - public static readonly AREM = 65; - public static readonly AAND = 66; - public static readonly AXOR = 67; - public static readonly AOR = 68; - public static readonly ALSH = 69; - public static readonly ARSH = 70; - public static readonly AUSH = 71; - public static readonly OCTAL = 72; - public static readonly HEX = 73; - public static readonly INTEGER = 74; - public static readonly DECIMAL = 75; - public static readonly STRING = 76; - public static readonly REGEX = 77; - public static readonly TRUE = 78; - public static readonly FALSE = 79; - public static readonly NULL = 80; - public static readonly PRIMITIVE = 81; - public static readonly DEF = 82; - public static readonly ID = 83; - public static readonly DOTINTEGER = 84; - public static readonly DOTID = 85; + public static readonly DOLLAR = 9; + public static readonly DOT = 10; + public static readonly NSDOT = 11; + public static readonly COMMA = 12; + public static readonly SEMICOLON = 13; + public static readonly IF = 14; + public static readonly IN = 15; + public static readonly ELSE = 16; + public static readonly WHILE = 17; + public static readonly DO = 18; + public static readonly FOR = 19; + public static readonly CONTINUE = 20; + public static readonly BREAK = 21; + public static readonly RETURN = 22; + public static readonly NEW = 23; + public static readonly TRY = 24; + public static readonly CATCH = 25; + public static readonly THROW = 26; + public static readonly THIS = 27; + public static readonly INSTANCEOF = 28; + public static readonly BOOLNOT = 29; + public static readonly BWNOT = 30; + public static readonly MUL = 31; + public static readonly DIV = 32; + public static readonly REM = 33; + public static readonly ADD = 34; + public static readonly SUB = 35; + public static readonly LSH = 36; + public static readonly RSH = 37; + public static readonly USH = 38; + public static readonly LT = 39; + public static readonly LTE = 40; + public static readonly GT = 41; + public static readonly GTE = 42; + public static readonly EQ = 43; + public static readonly EQR = 44; + public static readonly NE = 45; + public static readonly NER = 46; + public static readonly BWAND = 47; + public static readonly XOR = 48; + public static readonly BWOR = 49; + public static readonly BOOLAND = 50; + public static readonly BOOLOR = 51; + public static readonly COND = 52; + public static readonly COLON = 53; + public static readonly ELVIS = 54; + public static readonly REF = 55; + public static readonly ARROW = 56; + public static readonly FIND = 57; + public static readonly MATCH = 58; + public static readonly INCR = 59; + public static readonly DECR = 60; + public static readonly ASSIGN = 61; + public static readonly AADD = 62; + public static readonly ASUB = 63; + public static readonly AMUL = 64; + public static readonly ADIV = 65; + public static readonly AREM = 66; + public static readonly AAND = 67; + public static readonly AXOR = 68; + public static readonly AOR = 69; + public static readonly ALSH = 70; + public static readonly ARSH = 71; + public static readonly AUSH = 72; + public static readonly OCTAL = 73; + public static readonly HEX = 74; + public static readonly INTEGER = 75; + public static readonly DECIMAL = 76; + public static readonly STRING = 77; + public static readonly REGEX = 78; + public static readonly TRUE = 79; + public static readonly FALSE = 80; + public static readonly NULL = 81; + public static readonly PRIMITIVE = 82; + public static readonly DEF = 83; + public static readonly ID = 84; + public static readonly DOTINTEGER = 85; + public static readonly DOTID = 86; public static readonly AFTER_DOT = 1; // tslint:disable:no-trailing-whitespace @@ -115,41 +116,41 @@ export class painless_lexer extends Lexer { ]; public static readonly ruleNames: string[] = [ - "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP", "DOT", - "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO", "FOR", - "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", "THIS", - "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", "SUB", "LSH", - "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", "NER", "BWAND", - "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS", "REF", "ARROW", - "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", "AMUL", "ADIV", - "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", "OCTAL", "HEX", - "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", "NULL", "PRIMITIVE", - "DEF", "ID", "DOTINTEGER", "DOTID", + "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", "RP", "DOLLAR", + "DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", "DO", + "FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", + "THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", + "SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", + "NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS", + "REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", + "AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", + "OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", + "NULL", "PRIMITIVE", "DEF", "ID", "DOTINTEGER", "DOTID", ]; private static readonly _LITERAL_NAMES: Array = [ - undefined, undefined, undefined, "'{'", "'}'", "'['", "']'", "'('", "')'", - "'.'", "'?.'", "','", "';'", "'if'", "'in'", "'else'", "'while'", "'do'", - "'for'", "'continue'", "'break'", "'return'", "'new'", "'try'", "'catch'", - "'throw'", "'this'", "'instanceof'", "'!'", "'~'", "'*'", "'/'", "'%'", - "'+'", "'-'", "'<<'", "'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", "'=='", - "'==='", "'!='", "'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", - "':'", "'?:'", "'::'", "'->'", "'=~'", "'==~'", "'++'", "'--'", "'='", - "'+='", "'-='", "'*='", "'/='", "'%='", "'&='", "'^='", "'|='", "'<<='", - "'>>='", "'>>>='", undefined, undefined, undefined, undefined, undefined, - undefined, "'true'", "'false'", "'null'", undefined, "'def'", + undefined, undefined, undefined, "'{'", "'}'", "'['", "']'", "'('", "')'", + "'$'", "'.'", "'?.'", "','", "';'", "'if'", "'in'", "'else'", "'while'", + "'do'", "'for'", "'continue'", "'break'", "'return'", "'new'", "'try'", + "'catch'", "'throw'", "'this'", "'instanceof'", "'!'", "'~'", "'*'", "'/'", + "'%'", "'+'", "'-'", "'<<'", "'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", + "'=='", "'==='", "'!='", "'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", + "'?'", "':'", "'?:'", "'::'", "'->'", "'=~'", "'==~'", "'++'", "'--'", + "'='", "'+='", "'-='", "'*='", "'/='", "'%='", "'&='", "'^='", "'|='", + "'<<='", "'>>='", "'>>>='", undefined, undefined, undefined, undefined, + undefined, undefined, "'true'", "'false'", "'null'", undefined, "'def'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", - "RP", "DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", - "DO", "FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", - "THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", - "SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", - "NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS", - "REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", - "AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", - "OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", - "NULL", "PRIMITIVE", "DEF", "ID", "DOTINTEGER", "DOTID", + undefined, "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", + "RP", "DOLLAR", "DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", + "WHILE", "DO", "FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", + "THROW", "THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", + "ADD", "SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", + "NE", "NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", + "ELVIS", "REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", + "ASUB", "AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", + "AUSH", "OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", + "FALSE", "NULL", "PRIMITIVE", "DEF", "ID", "DOTINTEGER", "DOTID", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(painless_lexer._LITERAL_NAMES, painless_lexer._SYMBOLIC_NAMES, []); @@ -185,13 +186,13 @@ export class painless_lexer extends Lexer { public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { // DO NOT CHANGE - // This is a manual fix to handle slashes appropriately - case 31: + // This is a manual fix to handle slashes appropriately, DIV: 32 + case 32: return this.DIV_sempred(_localctx, predIndex); // DO NOT CHANGE - // This is a manual fix to handle regexes appropriately - case 77: + // This is a manual fix to handle regexes appropriately, REGEX: 78 + case 78: return this.REGEX_sempred(_localctx, predIndex); } return true; @@ -213,7 +214,7 @@ export class painless_lexer extends Lexer { private static readonly _serializedATNSegments: number = 2; private static readonly _serializedATNSegment0: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02W\u027A\b\x01" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02X\u027E\b\x01" + "\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06" + "\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f" + "\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04" + @@ -225,299 +226,301 @@ export class painless_lexer extends Lexer { "3\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04;\t;\x04" + "<\t<\x04=\t=\x04>\t>\x04?\t?\x04@\t@\x04A\tA\x04B\tB\x04C\tC\x04D\tD\x04" + "E\tE\x04F\tF\x04G\tG\x04H\tH\x04I\tI\x04J\tJ\x04K\tK\x04L\tL\x04M\tM\x04" + - "N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04U\tU\x04V\tV\x03" + - "\x02\x06\x02\xB0\n\x02\r\x02\x0E\x02\xB1\x03\x02\x03\x02\x03\x03\x03\x03" + - "\x03\x03\x03\x03\x07\x03\xBA\n\x03\f\x03\x0E\x03\xBD\v\x03\x03\x03\x03" + - "\x03\x03\x03\x03\x03\x03\x03\x07\x03\xC4\n\x03\f\x03\x0E\x03\xC7\v\x03" + - "\x03\x03\x03\x03\x05\x03\xCB\n\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03" + - "\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03\t\x03\t\x03" + - "\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\r\x03" + - "\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03\x10\x03" + - "\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03" + - "\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03" + - "\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x15\x03\x15\x03" + - "\x15\x03\x15\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03" + - "\x16\x03\x16\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03" + - "\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03" + - "\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03" + - "\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03" + - "\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03 \x03" + - " \x03 \x03!\x03!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03$\x03%\x03%\x03%\x03" + - "&\x03&\x03&\x03&\x03\'\x03\'\x03(\x03(\x03(\x03)\x03)\x03*\x03*\x03*\x03" + - "+\x03+\x03+\x03,\x03,\x03,\x03,\x03-\x03-\x03-\x03.\x03.\x03.\x03.\x03" + - "/\x03/\x030\x030\x031\x031\x032\x032\x032\x033\x033\x033\x034\x034\x03" + - "5\x035\x036\x036\x036\x037\x037\x037\x038\x038\x038\x039\x039\x039\x03" + - ":\x03:\x03:\x03:\x03;\x03;\x03;\x03<\x03<\x03<\x03=\x03=\x03>\x03>\x03" + - ">\x03?\x03?\x03?\x03@\x03@\x03@\x03A\x03A\x03A\x03B\x03B\x03B\x03C\x03" + - "C\x03C\x03D\x03D\x03D\x03E\x03E\x03E\x03F\x03F\x03F\x03F\x03G\x03G\x03" + - "G\x03G\x03H\x03H\x03H\x03H\x03H\x03I\x03I\x06I\u01BA\nI\rI\x0EI\u01BB" + - "\x03I\x05I\u01BF\nI\x03J\x03J\x03J\x06J\u01C4\nJ\rJ\x0EJ\u01C5\x03J\x05" + - "J\u01C9\nJ\x03K\x03K\x03K\x07K\u01CE\nK\fK\x0EK\u01D1\vK\x05K\u01D3\n" + - "K\x03K\x05K\u01D6\nK\x03L\x03L\x03L\x07L\u01DB\nL\fL\x0EL\u01DE\vL\x05" + - "L\u01E0\nL\x03L\x03L\x06L\u01E4\nL\rL\x0EL\u01E5\x05L\u01E8\nL\x03L\x03" + - "L\x05L\u01EC\nL\x03L\x06L\u01EF\nL\rL\x0EL\u01F0\x05L\u01F3\nL\x03L\x05" + - "L\u01F6\nL\x03M\x03M\x03M\x03M\x03M\x03M\x07M\u01FE\nM\fM\x0EM\u0201\v" + - "M\x03M\x03M\x03M\x03M\x03M\x03M\x03M\x07M\u020A\nM\fM\x0EM\u020D\vM\x03" + - "M\x05M\u0210\nM\x03N\x03N\x03N\x03N\x06N\u0216\nN\rN\x0EN\u0217\x03N\x03" + - "N\x07N\u021C\nN\fN\x0EN\u021F\vN\x03N\x03N\x03O\x03O\x03O\x03O\x03O\x03" + - "P\x03P\x03P\x03P\x03P\x03P\x03Q\x03Q\x03Q\x03Q\x03Q\x03R\x03R\x03R\x03" + - "R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03" + - "R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03R\x03" + - "R\x03R\x03R\x03R\x03R\x03R\x03R\x05R\u0259\nR\x03S\x03S\x03S\x03S\x03" + - "T\x03T\x07T\u0261\nT\fT\x0ET\u0264\vT\x03U\x03U\x03U\x07U\u0269\nU\fU" + - "\x0EU\u026C\vU\x05U\u026E\nU\x03U\x03U\x03V\x03V\x07V\u0274\nV\fV\x0E" + - "V\u0277\vV\x03V\x03V\x07\xBB\xC5\u01FF\u020B\u0217\x02\x02W\x04\x02\x03" + - "\x06\x02\x04\b\x02\x05\n\x02\x06\f\x02\x07\x0E\x02\b\x10\x02\t\x12\x02" + - "\n\x14\x02\v\x16\x02\f\x18\x02\r\x1A\x02\x0E\x1C\x02\x0F\x1E\x02\x10 " + - "\x02\x11\"\x02\x12$\x02\x13&\x02\x14(\x02\x15*\x02\x16,\x02\x17.\x02\x18" + - "0\x02\x192\x02\x1A4\x02\x1B6\x02\x1C8\x02\x1D:\x02\x1E<\x02\x1F>\x02 " + - "@\x02!B\x02\"D\x02#F\x02$H\x02%J\x02&L\x02\'N\x02(P\x02)R\x02*T\x02+V" + - "\x02,X\x02-Z\x02.\\\x02/^\x020`\x021b\x022d\x023f\x024h\x025j\x026l\x02" + - "7n\x028p\x029r\x02:t\x02;v\x02|\x02?~\x02@\x80\x02A\x82\x02" + - "B\x84\x02C\x86\x02D\x88\x02E\x8A\x02F\x8C\x02G\x8E\x02H\x90\x02I\x92\x02" + - "J\x94\x02K\x96\x02L\x98\x02M\x9A\x02N\x9C\x02O\x9E\x02P\xA0\x02Q\xA2\x02" + - "R\xA4\x02S\xA6\x02T\xA8\x02U\xAA\x02V\xAC\x02W\x04\x02\x03\x15\x05\x02" + - "\v\f\x0F\x0F\"\"\x04\x02\f\f\x0F\x0F\x03\x0229\x04\x02NNnn\x04\x02ZZz" + - "z\x05\x022;CHch\x03\x023;\x03\x022;\b\x02FFHHNNffhhnn\x04\x02GGgg\x04" + - "\x02--//\x06\x02FFHHffhh\x04\x02$$^^\x04\x02))^^\x03\x02\f\f\x04\x02\f" + - "\f11\t\x02WWeekknouuwwzz\x05\x02C\\aac|\x06\x022;C\\aac|\x02\u02A0\x02" + - "\x04\x03\x02\x02\x02\x02\x06\x03\x02\x02\x02\x02\b\x03\x02\x02\x02\x02" + - "\n\x03\x02\x02\x02\x02\f\x03\x02\x02\x02\x02\x0E\x03\x02\x02\x02\x02\x10" + - "\x03\x02\x02\x02\x02\x12\x03\x02\x02\x02\x02\x14\x03\x02\x02\x02\x02\x16" + - "\x03\x02\x02\x02\x02\x18\x03\x02\x02\x02\x02\x1A\x03\x02\x02\x02\x02\x1C" + - "\x03\x02\x02\x02\x02\x1E\x03\x02\x02\x02\x02 \x03\x02\x02\x02\x02\"\x03" + - "\x02\x02\x02\x02$\x03\x02\x02\x02\x02&\x03\x02\x02\x02\x02(\x03\x02\x02" + - "\x02\x02*\x03\x02\x02\x02\x02,\x03\x02\x02\x02\x02.\x03\x02\x02\x02\x02" + - "0\x03\x02\x02\x02\x022\x03\x02\x02\x02\x024\x03\x02\x02\x02\x026\x03\x02" + - "\x02\x02\x028\x03\x02\x02\x02\x02:\x03\x02\x02\x02\x02<\x03\x02\x02\x02" + - "\x02>\x03\x02\x02\x02\x02@\x03\x02\x02\x02\x02B\x03\x02\x02\x02\x02D\x03" + - "\x02\x02\x02\x02F\x03\x02\x02\x02\x02H\x03\x02\x02\x02\x02J\x03\x02\x02" + - "\x02\x02L\x03\x02\x02\x02\x02N\x03\x02\x02\x02\x02P\x03\x02\x02\x02\x02" + - "R\x03\x02\x02\x02\x02T\x03\x02\x02\x02\x02V\x03\x02\x02\x02\x02X\x03\x02" + - "\x02\x02\x02Z\x03\x02\x02\x02\x02\\\x03\x02\x02\x02\x02^\x03\x02\x02\x02" + - "\x02`\x03\x02\x02\x02\x02b\x03\x02\x02\x02\x02d\x03\x02\x02\x02\x02f\x03" + - "\x02\x02\x02\x02h\x03\x02\x02\x02\x02j\x03\x02\x02\x02\x02l\x03\x02\x02" + - "\x02\x02n\x03\x02\x02\x02\x02p\x03\x02\x02\x02\x02r\x03\x02\x02\x02\x02" + - "t\x03\x02\x02\x02\x02v\x03\x02\x02\x02\x02x\x03\x02\x02\x02\x02z\x03\x02" + - "\x02\x02\x02|\x03\x02\x02\x02\x02~\x03\x02\x02\x02\x02\x80\x03\x02\x02" + - "\x02\x02\x82\x03\x02\x02\x02\x02\x84\x03\x02\x02\x02\x02\x86\x03\x02\x02" + - "\x02\x02\x88\x03\x02\x02\x02\x02\x8A\x03\x02\x02\x02\x02\x8C\x03\x02\x02" + - "\x02\x02\x8E\x03\x02\x02\x02\x02\x90\x03\x02\x02\x02\x02\x92\x03\x02\x02" + - "\x02\x02\x94\x03\x02\x02\x02\x02\x96\x03\x02\x02\x02\x02\x98\x03\x02\x02" + - "\x02\x02\x9A\x03\x02\x02\x02\x02\x9C\x03\x02\x02\x02\x02\x9E\x03\x02\x02" + - "\x02\x02\xA0\x03\x02\x02\x02\x02\xA2\x03\x02\x02\x02\x02\xA4\x03\x02\x02" + - "\x02\x02\xA6\x03\x02\x02\x02\x02\xA8\x03\x02\x02\x02\x03\xAA\x03\x02\x02" + - "\x02\x03\xAC\x03\x02\x02\x02\x04\xAF\x03\x02\x02\x02\x06\xCA\x03\x02\x02" + - "\x02\b\xCE\x03\x02\x02\x02\n\xD0\x03\x02\x02\x02\f\xD2\x03\x02\x02\x02" + - "\x0E\xD4\x03\x02\x02\x02\x10\xD6\x03\x02\x02\x02\x12\xD8\x03\x02\x02\x02" + - "\x14\xDA\x03\x02\x02\x02\x16\xDE\x03\x02\x02\x02\x18\xE3\x03\x02\x02\x02" + - "\x1A\xE5\x03\x02\x02\x02\x1C\xE7\x03\x02\x02\x02\x1E\xEA\x03\x02\x02\x02" + - " \xED\x03\x02\x02\x02\"\xF2\x03\x02\x02\x02$\xF8\x03\x02\x02\x02&\xFB" + - "\x03\x02\x02\x02(\xFF\x03\x02\x02\x02*\u0108\x03\x02\x02\x02,\u010E\x03" + - "\x02\x02\x02.\u0115\x03\x02\x02\x020\u0119\x03\x02\x02\x022\u011D\x03" + - "\x02\x02\x024\u0123\x03\x02\x02\x026\u0129\x03\x02\x02\x028\u012E\x03" + - "\x02\x02\x02:\u0139\x03\x02\x02\x02<\u013B\x03\x02\x02\x02>\u013D\x03" + - "\x02\x02\x02@\u013F\x03\x02\x02\x02B\u0142\x03\x02\x02\x02D\u0144\x03" + - "\x02\x02\x02F\u0146\x03\x02\x02\x02H\u0148\x03\x02\x02\x02J\u014B\x03" + - "\x02\x02\x02L\u014E\x03\x02\x02\x02N\u0152\x03\x02\x02\x02P\u0154\x03" + - "\x02\x02\x02R\u0157\x03\x02\x02\x02T\u0159\x03\x02\x02\x02V\u015C\x03" + - "\x02\x02\x02X\u015F\x03\x02\x02\x02Z\u0163\x03\x02\x02\x02\\\u0166\x03" + - "\x02\x02\x02^\u016A\x03\x02\x02\x02`\u016C\x03\x02\x02\x02b\u016E\x03" + - "\x02\x02\x02d\u0170\x03\x02\x02\x02f\u0173\x03\x02\x02\x02h\u0176\x03" + - "\x02\x02\x02j\u0178\x03\x02\x02\x02l\u017A\x03\x02\x02\x02n\u017D\x03" + - "\x02\x02\x02p\u0180\x03\x02\x02\x02r\u0183\x03\x02\x02\x02t\u0186\x03" + - "\x02\x02\x02v\u018A\x03\x02\x02\x02x\u018D\x03\x02\x02\x02z\u0190\x03" + - "\x02\x02\x02|\u0192\x03\x02\x02\x02~\u0195\x03\x02\x02\x02\x80\u0198\x03" + - "\x02\x02\x02\x82\u019B\x03\x02\x02\x02\x84\u019E\x03\x02\x02\x02\x86\u01A1" + - "\x03\x02\x02\x02\x88\u01A4\x03\x02\x02\x02\x8A\u01A7\x03\x02\x02\x02\x8C" + - "\u01AA\x03\x02\x02\x02\x8E\u01AE\x03\x02\x02\x02\x90\u01B2\x03\x02\x02" + - "\x02\x92\u01B7\x03\x02\x02\x02\x94\u01C0\x03\x02\x02\x02\x96\u01D2\x03" + - "\x02\x02\x02\x98\u01DF\x03\x02\x02\x02\x9A\u020F\x03\x02\x02\x02\x9C\u0211" + - "\x03\x02\x02\x02\x9E\u0222\x03\x02\x02\x02\xA0\u0227\x03\x02\x02\x02\xA2" + - "\u022D\x03\x02\x02\x02\xA4\u0258\x03\x02\x02\x02\xA6\u025A\x03\x02\x02" + - "\x02\xA8\u025E\x03\x02\x02\x02\xAA\u026D\x03\x02\x02\x02\xAC\u0271\x03" + - "\x02\x02\x02\xAE\xB0\t\x02\x02\x02\xAF\xAE\x03\x02\x02\x02\xB0\xB1\x03" + - "\x02\x02\x02\xB1\xAF\x03\x02\x02\x02\xB1\xB2\x03\x02\x02\x02\xB2\xB3\x03" + - "\x02\x02\x02\xB3\xB4\b\x02\x02\x02\xB4\x05\x03\x02\x02\x02\xB5\xB6\x07" + - "1\x02\x02\xB6\xB7\x071\x02\x02\xB7\xBB\x03\x02\x02\x02\xB8\xBA\v\x02\x02" + - "\x02\xB9\xB8\x03\x02\x02\x02\xBA\xBD\x03\x02\x02\x02\xBB\xBC\x03\x02\x02" + - "\x02\xBB\xB9\x03\x02\x02\x02\xBC\xBE\x03\x02\x02\x02\xBD\xBB\x03\x02\x02" + - "\x02\xBE\xCB\t\x03\x02\x02\xBF\xC0\x071\x02\x02\xC0\xC1\x07,\x02\x02\xC1" + - "\xC5\x03\x02\x02\x02\xC2\xC4\v\x02\x02\x02\xC3\xC2\x03\x02\x02\x02\xC4" + - "\xC7\x03\x02\x02\x02\xC5\xC6\x03\x02\x02\x02\xC5\xC3\x03\x02\x02\x02\xC6" + - "\xC8\x03\x02\x02\x02\xC7\xC5\x03\x02\x02\x02\xC8\xC9\x07,\x02\x02\xC9" + - "\xCB\x071\x02\x02\xCA\xB5\x03\x02\x02\x02\xCA\xBF\x03\x02\x02\x02\xCB" + - "\xCC\x03\x02\x02\x02\xCC\xCD\b\x03\x02\x02\xCD\x07\x03\x02\x02\x02\xCE" + - "\xCF\x07}\x02\x02\xCF\t\x03\x02\x02\x02\xD0\xD1\x07\x7F\x02\x02\xD1\v" + - "\x03\x02\x02\x02\xD2\xD3\x07]\x02\x02\xD3\r\x03\x02\x02\x02\xD4\xD5\x07" + - "_\x02\x02\xD5\x0F\x03\x02\x02\x02\xD6\xD7\x07*\x02\x02\xD7\x11\x03\x02" + - "\x02\x02\xD8\xD9\x07+\x02\x02\xD9\x13\x03\x02\x02\x02\xDA\xDB\x070\x02" + - "\x02\xDB\xDC\x03\x02\x02\x02\xDC\xDD\b\n\x03\x02\xDD\x15\x03\x02\x02\x02" + - "\xDE\xDF\x07A\x02\x02\xDF\xE0\x070\x02\x02\xE0\xE1\x03\x02\x02\x02\xE1" + - "\xE2\b\v\x03\x02\xE2\x17\x03\x02\x02\x02\xE3\xE4\x07.\x02\x02\xE4\x19" + - "\x03\x02\x02\x02\xE5\xE6\x07=\x02\x02\xE6\x1B\x03\x02\x02\x02\xE7\xE8" + - "\x07k\x02\x02\xE8\xE9\x07h\x02\x02\xE9\x1D\x03\x02\x02\x02\xEA\xEB\x07" + - "k\x02\x02\xEB\xEC\x07p\x02\x02\xEC\x1F\x03\x02\x02\x02\xED\xEE\x07g\x02" + - "\x02\xEE\xEF\x07n\x02\x02\xEF\xF0\x07u\x02\x02\xF0\xF1\x07g\x02\x02\xF1" + - "!\x03\x02\x02\x02\xF2\xF3\x07y\x02\x02\xF3\xF4\x07j\x02\x02\xF4\xF5\x07" + - "k\x02\x02\xF5\xF6\x07n\x02\x02\xF6\xF7\x07g\x02\x02\xF7#\x03\x02\x02\x02" + - "\xF8\xF9\x07f\x02\x02\xF9\xFA\x07q\x02\x02\xFA%\x03\x02\x02\x02\xFB\xFC" + - "\x07h\x02\x02\xFC\xFD\x07q\x02\x02\xFD\xFE\x07t\x02\x02\xFE\'\x03\x02" + - "\x02\x02\xFF\u0100\x07e\x02\x02\u0100\u0101\x07q\x02\x02\u0101\u0102\x07" + - "p\x02\x02\u0102\u0103\x07v\x02\x02\u0103\u0104\x07k\x02\x02\u0104\u0105" + - "\x07p\x02\x02\u0105\u0106\x07w\x02\x02\u0106\u0107\x07g\x02\x02\u0107" + - ")\x03\x02\x02\x02\u0108\u0109\x07d\x02\x02\u0109\u010A\x07t\x02\x02\u010A" + - "\u010B\x07g\x02\x02\u010B\u010C\x07c\x02\x02\u010C\u010D\x07m\x02\x02" + - "\u010D+\x03\x02\x02\x02\u010E\u010F\x07t\x02\x02\u010F\u0110\x07g\x02" + - "\x02\u0110\u0111\x07v\x02\x02\u0111\u0112\x07w\x02\x02\u0112\u0113\x07" + - "t\x02\x02\u0113\u0114\x07p\x02\x02\u0114-\x03\x02\x02\x02\u0115\u0116" + - "\x07p\x02\x02\u0116\u0117\x07g\x02\x02\u0117\u0118\x07y\x02\x02\u0118" + - "/\x03\x02\x02\x02\u0119\u011A\x07v\x02\x02\u011A\u011B\x07t\x02\x02\u011B" + - "\u011C\x07{\x02\x02\u011C1\x03\x02\x02\x02\u011D\u011E\x07e\x02\x02\u011E" + - "\u011F\x07c\x02\x02\u011F\u0120\x07v\x02\x02\u0120\u0121\x07e\x02\x02" + - "\u0121\u0122\x07j\x02\x02\u01223\x03\x02\x02\x02\u0123\u0124\x07v\x02" + - "\x02\u0124\u0125\x07j\x02\x02\u0125\u0126\x07t\x02\x02\u0126\u0127\x07" + - "q\x02\x02\u0127\u0128\x07y\x02\x02\u01285\x03\x02\x02\x02\u0129\u012A" + - "\x07v\x02\x02\u012A\u012B\x07j\x02\x02\u012B\u012C\x07k\x02\x02\u012C" + - "\u012D\x07u\x02\x02\u012D7\x03\x02\x02\x02\u012E\u012F\x07k\x02\x02\u012F" + - "\u0130\x07p\x02\x02\u0130\u0131\x07u\x02\x02\u0131\u0132\x07v\x02\x02" + - "\u0132\u0133\x07c\x02\x02\u0133\u0134\x07p\x02\x02\u0134\u0135\x07e\x02" + - "\x02\u0135\u0136\x07g\x02\x02\u0136\u0137\x07q\x02\x02\u0137\u0138\x07" + - "h\x02\x02\u01389\x03\x02\x02\x02\u0139\u013A\x07#\x02\x02\u013A;\x03\x02" + - "\x02\x02\u013B\u013C\x07\x80\x02\x02\u013C=\x03\x02\x02\x02\u013D\u013E" + - "\x07,\x02\x02\u013E?\x03\x02\x02\x02\u013F\u0140\x071\x02\x02\u0140\u0141" + - "\x06 \x02\x02\u0141A\x03\x02\x02\x02\u0142\u0143\x07\'\x02\x02\u0143C" + - "\x03\x02\x02\x02\u0144\u0145\x07-\x02\x02\u0145E\x03\x02\x02\x02\u0146" + - "\u0147\x07/\x02\x02\u0147G\x03\x02\x02\x02\u0148\u0149\x07>\x02\x02\u0149" + - "\u014A\x07>\x02\x02\u014AI\x03\x02\x02\x02\u014B\u014C\x07@\x02\x02\u014C" + - "\u014D\x07@\x02\x02\u014DK\x03\x02\x02\x02\u014E\u014F\x07@\x02\x02\u014F" + - "\u0150\x07@\x02\x02\u0150\u0151\x07@\x02\x02\u0151M\x03\x02\x02\x02\u0152" + - "\u0153\x07>\x02\x02\u0153O\x03\x02\x02\x02\u0154\u0155\x07>\x02\x02\u0155" + - "\u0156\x07?\x02\x02\u0156Q\x03\x02\x02\x02\u0157\u0158\x07@\x02\x02\u0158" + - "S\x03\x02\x02\x02\u0159\u015A\x07@\x02\x02\u015A\u015B\x07?\x02\x02\u015B" + - "U\x03\x02\x02\x02\u015C\u015D\x07?\x02\x02\u015D\u015E\x07?\x02\x02\u015E" + - "W\x03\x02\x02\x02\u015F\u0160\x07?\x02\x02\u0160\u0161\x07?\x02\x02\u0161" + - "\u0162\x07?\x02\x02\u0162Y\x03\x02\x02\x02\u0163\u0164\x07#\x02\x02\u0164" + - "\u0165\x07?\x02\x02\u0165[\x03\x02\x02\x02\u0166\u0167\x07#\x02\x02\u0167" + - "\u0168\x07?\x02\x02\u0168\u0169\x07?\x02\x02\u0169]\x03\x02\x02\x02\u016A" + - "\u016B\x07(\x02\x02\u016B_\x03\x02\x02\x02\u016C\u016D\x07`\x02\x02\u016D" + - "a\x03\x02\x02\x02\u016E\u016F\x07~\x02\x02\u016Fc\x03\x02\x02\x02\u0170" + - "\u0171\x07(\x02\x02\u0171\u0172\x07(\x02\x02\u0172e\x03\x02\x02\x02\u0173" + - "\u0174\x07~\x02\x02\u0174\u0175\x07~\x02\x02\u0175g\x03\x02\x02\x02\u0176" + - "\u0177\x07A\x02\x02\u0177i\x03\x02\x02\x02\u0178\u0179\x07<\x02\x02\u0179" + - "k\x03\x02\x02\x02\u017A\u017B\x07A\x02\x02\u017B\u017C\x07<\x02\x02\u017C" + - "m\x03\x02\x02\x02\u017D\u017E\x07<\x02\x02\u017E\u017F\x07<\x02\x02\u017F" + - "o\x03\x02\x02\x02\u0180\u0181\x07/\x02\x02\u0181\u0182\x07@\x02\x02\u0182" + - "q\x03\x02\x02\x02\u0183\u0184\x07?\x02\x02\u0184\u0185\x07\x80\x02\x02" + - "\u0185s\x03\x02\x02\x02\u0186\u0187\x07?\x02\x02\u0187\u0188\x07?\x02" + - "\x02\u0188\u0189\x07\x80\x02\x02\u0189u\x03\x02\x02\x02\u018A\u018B\x07" + - "-\x02\x02\u018B\u018C\x07-\x02\x02\u018Cw\x03\x02\x02\x02\u018D\u018E" + - "\x07/\x02\x02\u018E\u018F\x07/\x02\x02\u018Fy\x03\x02\x02\x02\u0190\u0191" + - "\x07?\x02\x02\u0191{\x03\x02\x02\x02\u0192\u0193\x07-\x02\x02\u0193\u0194" + - "\x07?\x02\x02\u0194}\x03\x02\x02\x02\u0195\u0196\x07/\x02\x02\u0196\u0197" + - "\x07?\x02\x02\u0197\x7F\x03\x02\x02\x02\u0198\u0199\x07,\x02\x02\u0199" + - "\u019A\x07?\x02\x02\u019A\x81\x03\x02\x02\x02\u019B\u019C\x071\x02\x02" + - "\u019C\u019D\x07?\x02\x02\u019D\x83\x03\x02\x02\x02\u019E\u019F\x07\'" + - "\x02\x02\u019F\u01A0\x07?\x02\x02\u01A0\x85\x03\x02\x02\x02\u01A1\u01A2" + - "\x07(\x02\x02\u01A2\u01A3\x07?\x02\x02\u01A3\x87\x03\x02\x02\x02\u01A4" + - "\u01A5\x07`\x02\x02\u01A5\u01A6\x07?\x02\x02\u01A6\x89\x03\x02\x02\x02" + - "\u01A7\u01A8\x07~\x02\x02\u01A8\u01A9\x07?\x02\x02\u01A9\x8B\x03\x02\x02" + - "\x02\u01AA\u01AB\x07>\x02\x02\u01AB\u01AC\x07>\x02\x02\u01AC\u01AD\x07" + - "?\x02\x02\u01AD\x8D\x03\x02\x02\x02\u01AE\u01AF\x07@\x02\x02\u01AF\u01B0" + - "\x07@\x02\x02\u01B0\u01B1\x07?\x02\x02\u01B1\x8F\x03\x02\x02\x02\u01B2" + - "\u01B3\x07@\x02\x02\u01B3\u01B4\x07@\x02\x02\u01B4\u01B5\x07@\x02\x02" + - "\u01B5\u01B6\x07?\x02\x02\u01B6\x91\x03\x02\x02\x02\u01B7\u01B9\x072\x02" + - "\x02\u01B8\u01BA\t\x04\x02\x02\u01B9\u01B8\x03\x02\x02\x02\u01BA\u01BB" + - "\x03\x02\x02\x02\u01BB\u01B9\x03\x02\x02\x02\u01BB\u01BC\x03\x02\x02\x02" + - "\u01BC\u01BE\x03\x02\x02\x02\u01BD\u01BF\t\x05\x02\x02\u01BE\u01BD\x03" + - "\x02\x02\x02\u01BE\u01BF\x03\x02\x02\x02\u01BF\x93\x03\x02\x02\x02\u01C0" + - "\u01C1\x072\x02\x02\u01C1\u01C3\t\x06\x02\x02\u01C2\u01C4\t\x07\x02\x02" + - "\u01C3\u01C2\x03\x02\x02\x02\u01C4\u01C5\x03\x02\x02\x02\u01C5\u01C3\x03" + - "\x02\x02\x02\u01C5\u01C6\x03\x02\x02\x02\u01C6\u01C8\x03\x02\x02\x02\u01C7" + - "\u01C9\t\x05\x02\x02\u01C8\u01C7\x03\x02\x02\x02\u01C8\u01C9\x03\x02\x02" + - "\x02\u01C9\x95\x03\x02\x02\x02\u01CA\u01D3\x072\x02\x02\u01CB\u01CF\t" + - "\b\x02\x02\u01CC\u01CE\t\t\x02\x02\u01CD\u01CC\x03\x02\x02\x02\u01CE\u01D1" + - "\x03\x02\x02\x02\u01CF\u01CD\x03\x02\x02\x02\u01CF\u01D0\x03\x02\x02\x02" + - "\u01D0\u01D3\x03\x02\x02\x02\u01D1\u01CF\x03\x02\x02\x02\u01D2\u01CA\x03" + - "\x02\x02\x02\u01D2\u01CB\x03\x02\x02\x02\u01D3\u01D5\x03\x02\x02\x02\u01D4" + - "\u01D6\t\n\x02\x02\u01D5\u01D4\x03\x02\x02\x02\u01D5\u01D6\x03\x02\x02" + - "\x02\u01D6\x97\x03\x02\x02\x02\u01D7\u01E0\x072\x02\x02\u01D8\u01DC\t" + - "\b\x02\x02\u01D9\u01DB\t\t\x02\x02\u01DA\u01D9\x03\x02\x02\x02\u01DB\u01DE" + - "\x03\x02\x02\x02\u01DC\u01DA\x03\x02\x02\x02\u01DC\u01DD\x03\x02\x02\x02" + - "\u01DD\u01E0\x03\x02\x02\x02\u01DE\u01DC\x03\x02\x02\x02\u01DF\u01D7\x03" + - "\x02\x02\x02\u01DF\u01D8\x03\x02\x02\x02\u01E0\u01E7\x03\x02\x02\x02\u01E1" + - "\u01E3\x05\x14\n\x02\u01E2\u01E4\t\t\x02\x02\u01E3\u01E2\x03\x02\x02\x02" + - "\u01E4\u01E5\x03\x02\x02\x02\u01E5\u01E3\x03\x02\x02\x02\u01E5\u01E6\x03" + - "\x02\x02\x02\u01E6\u01E8\x03\x02\x02\x02\u01E7\u01E1\x03\x02\x02\x02\u01E7" + - "\u01E8\x03\x02\x02\x02\u01E8\u01F2\x03\x02\x02\x02\u01E9\u01EB\t\v\x02" + - "\x02\u01EA\u01EC\t\f\x02\x02\u01EB\u01EA\x03\x02\x02\x02\u01EB\u01EC\x03" + - "\x02\x02\x02\u01EC\u01EE\x03\x02\x02\x02\u01ED\u01EF\t\t\x02\x02\u01EE" + - "\u01ED\x03\x02\x02\x02\u01EF\u01F0\x03\x02\x02\x02\u01F0\u01EE\x03\x02" + - "\x02\x02\u01F0\u01F1\x03\x02\x02\x02\u01F1\u01F3\x03\x02\x02\x02\u01F2" + - "\u01E9\x03\x02\x02\x02\u01F2\u01F3\x03\x02\x02\x02\u01F3\u01F5\x03\x02" + - "\x02\x02\u01F4\u01F6\t\r\x02\x02\u01F5\u01F4\x03\x02\x02\x02\u01F5\u01F6" + - "\x03\x02\x02\x02\u01F6\x99\x03\x02\x02\x02\u01F7\u01FF\x07$\x02\x02\u01F8" + - "\u01F9\x07^\x02\x02\u01F9\u01FE\x07$\x02\x02\u01FA\u01FB\x07^\x02\x02" + - "\u01FB\u01FE\x07^\x02\x02\u01FC\u01FE\n\x0E\x02\x02\u01FD\u01F8\x03\x02" + - "\x02\x02\u01FD\u01FA\x03\x02\x02\x02\u01FD\u01FC\x03\x02\x02\x02\u01FE" + - "\u0201\x03\x02\x02\x02\u01FF\u0200\x03\x02\x02\x02\u01FF\u01FD\x03\x02" + - "\x02\x02\u0200\u0202\x03\x02\x02\x02\u0201\u01FF\x03\x02\x02\x02\u0202" + - "\u0210\x07$\x02\x02\u0203\u020B\x07)\x02\x02\u0204\u0205\x07^\x02\x02" + - "\u0205\u020A\x07)\x02\x02\u0206\u0207\x07^\x02\x02\u0207\u020A\x07^\x02" + - "\x02\u0208\u020A\n\x0F\x02\x02\u0209\u0204\x03\x02\x02\x02\u0209\u0206" + - "\x03\x02\x02\x02\u0209\u0208\x03\x02\x02\x02\u020A\u020D\x03\x02\x02\x02" + - "\u020B\u020C\x03\x02\x02\x02\u020B\u0209\x03\x02\x02\x02\u020C"; + "N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04U\tU\x04V\tV\x04" + + "W\tW\x03\x02\x06\x02\xB2\n\x02\r\x02\x0E\x02\xB3\x03\x02\x03\x02\x03\x03" + + "\x03\x03\x03\x03\x03\x03\x07\x03\xBC\n\x03\f\x03\x0E\x03\xBF\v\x03\x03" + + "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03\xC6\n\x03\f\x03\x0E\x03\xC9" + + "\v\x03\x03\x03\x03\x03\x05\x03\xCD\n\x03\x03\x03\x03\x03\x03\x04\x03\x04" + + "\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03\t\x03" + + "\t\x03\n\x03\n\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\f\x03\f\x03\f\x03" + + "\r\x03\r\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03\x10\x03\x10" + + "\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12" + + "\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x14\x03\x14" + + "\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15" + + "\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x17\x03\x17\x03\x17" + + "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x19" + + "\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A" + + "\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C" + + "\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D" + + "\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03 " + + "\x03 \x03!\x03!\x03!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03%\x03%\x03%\x03" + + "&\x03&\x03&\x03\'\x03\'\x03\'\x03\'\x03(\x03(\x03)\x03)\x03)\x03*\x03" + + "*\x03+\x03+\x03+\x03,\x03,\x03,\x03-\x03-\x03-\x03-\x03.\x03.\x03.\x03" + + "/\x03/\x03/\x03/\x030\x030\x031\x031\x032\x032\x033\x033\x033\x034\x03" + + "4\x034\x035\x035\x036\x036\x037\x037\x037\x038\x038\x038\x039\x039\x03" + + "9\x03:\x03:\x03:\x03;\x03;\x03;\x03;\x03<\x03<\x03<\x03=\x03=\x03=\x03" + + ">\x03>\x03?\x03?\x03?\x03@\x03@\x03@\x03A\x03A\x03A\x03B\x03B\x03B\x03" + + "C\x03C\x03C\x03D\x03D\x03D\x03E\x03E\x03E\x03F\x03F\x03F\x03G\x03G\x03" + + "G\x03G\x03H\x03H\x03H\x03H\x03I\x03I\x03I\x03I\x03I\x03J\x03J\x06J\u01BE" + + "\nJ\rJ\x0EJ\u01BF\x03J\x05J\u01C3\nJ\x03K\x03K\x03K\x06K\u01C8\nK\rK\x0E" + + "K\u01C9\x03K\x05K\u01CD\nK\x03L\x03L\x03L\x07L\u01D2\nL\fL\x0EL\u01D5" + + "\vL\x05L\u01D7\nL\x03L\x05L\u01DA\nL\x03M\x03M\x03M\x07M\u01DF\nM\fM\x0E" + + "M\u01E2\vM\x05M\u01E4\nM\x03M\x03M\x06M\u01E8\nM\rM\x0EM\u01E9\x05M\u01EC" + + "\nM\x03M\x03M\x05M\u01F0\nM\x03M\x06M\u01F3\nM\rM\x0EM\u01F4\x05M\u01F7" + + "\nM\x03M\x05M\u01FA\nM\x03N\x03N\x03N\x03N\x03N\x03N\x07N\u0202\nN\fN" + + "\x0EN\u0205\vN\x03N\x03N\x03N\x03N\x03N\x03N\x03N\x07N\u020E\nN\fN\x0E" + + "N\u0211\vN\x03N\x05N\u0214\nN\x03O\x03O\x03O\x03O\x06O\u021A\nO\rO\x0E" + + "O\u021B\x03O\x03O\x07O\u0220\nO\fO\x0EO\u0223\vO\x03O\x03O\x03P\x03P\x03" + + "P\x03P\x03P\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03R\x03R\x03R\x03R\x03R\x03" + + "S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03" + + "S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03" + + "S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x03S\x05S\u025D\nS\x03T\x03" + + "T\x03T\x03T\x03U\x03U\x07U\u0265\nU\fU\x0EU\u0268\vU\x03V\x03V\x03V\x07" + + "V\u026D\nV\fV\x0EV\u0270\vV\x05V\u0272\nV\x03V\x03V\x03W\x03W\x07W\u0278" + + "\nW\fW\x0EW\u027B\vW\x03W\x03W\x07\xBD\xC7\u0203\u020F\u021B\x02\x02X" + + "\x04\x02\x03\x06\x02\x04\b\x02\x05\n\x02\x06\f\x02\x07\x0E\x02\b\x10\x02" + + "\t\x12\x02\n\x14\x02\v\x16\x02\f\x18\x02\r\x1A\x02\x0E\x1C\x02\x0F\x1E" + + "\x02\x10 \x02\x11\"\x02\x12$\x02\x13&\x02\x14(\x02\x15*\x02\x16,\x02\x17" + + ".\x02\x180\x02\x192\x02\x1A4\x02\x1B6\x02\x1C8\x02\x1D:\x02\x1E<\x02\x1F" + + ">\x02 @\x02!B\x02\"D\x02#F\x02$H\x02%J\x02&L\x02\'N\x02(P\x02)R\x02*T" + + "\x02+V\x02,X\x02-Z\x02.\\\x02/^\x020`\x021b\x022d\x023f\x024h\x025j\x02" + + "6l\x027n\x028p\x029r\x02:t\x02;v\x02|\x02?~\x02@\x80\x02" + + "A\x82\x02B\x84\x02C\x86\x02D\x88\x02E\x8A\x02F\x8C\x02G\x8E\x02H\x90\x02" + + "I\x92\x02J\x94\x02K\x96\x02L\x98\x02M\x9A\x02N\x9C\x02O\x9E\x02P\xA0\x02" + + "Q\xA2\x02R\xA4\x02S\xA6\x02T\xA8\x02U\xAA\x02V\xAC\x02W\xAE\x02X\x04\x02" + + "\x03\x15\x05\x02\v\f\x0F\x0F\"\"\x04\x02\f\f\x0F\x0F\x03\x0229\x04\x02" + + "NNnn\x04\x02ZZzz\x05\x022;CHch\x03\x023;\x03\x022;\b\x02FFHHNNffhhnn\x04" + + "\x02GGgg\x04\x02--//\x06\x02FFHHffhh\x04\x02$$^^\x04\x02))^^\x03\x02\f" + + "\f\x04\x02\f\f11\t\x02WWeekknouuwwzz\x05\x02C\\aac|\x06\x022;C\\aac|\x02" + + "\u02A4\x02\x04\x03\x02\x02\x02\x02\x06\x03\x02\x02\x02\x02\b\x03\x02\x02" + + "\x02\x02\n\x03\x02\x02\x02\x02\f\x03\x02\x02\x02\x02\x0E\x03\x02\x02\x02" + + "\x02\x10\x03\x02\x02\x02\x02\x12\x03\x02\x02\x02\x02\x14\x03\x02\x02\x02" + + "\x02\x16\x03\x02\x02\x02\x02\x18\x03\x02\x02\x02\x02\x1A\x03\x02\x02\x02" + + "\x02\x1C\x03\x02\x02\x02\x02\x1E\x03\x02\x02\x02\x02 \x03\x02\x02\x02" + + "\x02\"\x03\x02\x02\x02\x02$\x03\x02\x02\x02\x02&\x03\x02\x02\x02\x02(" + + "\x03\x02\x02\x02\x02*\x03\x02\x02\x02\x02,\x03\x02\x02\x02\x02.\x03\x02" + + "\x02\x02\x020\x03\x02\x02\x02\x022\x03\x02\x02\x02\x024\x03\x02\x02\x02" + + "\x026\x03\x02\x02\x02\x028\x03\x02\x02\x02\x02:\x03\x02\x02\x02\x02<\x03" + + "\x02\x02\x02\x02>\x03\x02\x02\x02\x02@\x03\x02\x02\x02\x02B\x03\x02\x02" + + "\x02\x02D\x03\x02\x02\x02\x02F\x03\x02\x02\x02\x02H\x03\x02\x02\x02\x02" + + "J\x03\x02\x02\x02\x02L\x03\x02\x02\x02\x02N\x03\x02\x02\x02\x02P\x03\x02" + + "\x02\x02\x02R\x03\x02\x02\x02\x02T\x03\x02\x02\x02\x02V\x03\x02\x02\x02" + + "\x02X\x03\x02\x02\x02\x02Z\x03\x02\x02\x02\x02\\\x03\x02\x02\x02\x02^" + + "\x03\x02\x02\x02\x02`\x03\x02\x02\x02\x02b\x03\x02\x02\x02\x02d\x03\x02" + + "\x02\x02\x02f\x03\x02\x02\x02\x02h\x03\x02\x02\x02\x02j\x03\x02\x02\x02" + + "\x02l\x03\x02\x02\x02\x02n\x03\x02\x02\x02\x02p\x03\x02\x02\x02\x02r\x03" + + "\x02\x02\x02\x02t\x03\x02\x02\x02\x02v\x03\x02\x02\x02\x02x\x03\x02\x02" + + "\x02\x02z\x03\x02\x02\x02\x02|\x03\x02\x02\x02\x02~\x03\x02\x02\x02\x02" + + "\x80\x03\x02\x02\x02\x02\x82\x03\x02\x02\x02\x02\x84\x03\x02\x02\x02\x02" + + "\x86\x03\x02\x02\x02\x02\x88\x03\x02\x02\x02\x02\x8A\x03\x02\x02\x02\x02" + + "\x8C\x03\x02\x02\x02\x02\x8E\x03\x02\x02\x02\x02\x90\x03\x02\x02\x02\x02" + + "\x92\x03\x02\x02\x02\x02\x94\x03\x02\x02\x02\x02\x96\x03\x02\x02\x02\x02" + + "\x98\x03\x02\x02\x02\x02\x9A\x03\x02\x02\x02\x02\x9C\x03\x02\x02\x02\x02" + + "\x9E\x03\x02\x02\x02\x02\xA0\x03\x02\x02\x02\x02\xA2\x03\x02\x02\x02\x02" + + "\xA4\x03\x02\x02\x02\x02\xA6\x03\x02\x02\x02\x02\xA8\x03\x02\x02\x02\x02" + + "\xAA\x03\x02\x02\x02\x03\xAC\x03\x02\x02\x02\x03\xAE\x03\x02\x02\x02\x04" + + "\xB1\x03\x02\x02\x02\x06\xCC\x03\x02\x02\x02\b\xD0\x03\x02\x02\x02\n\xD2" + + "\x03\x02\x02\x02\f\xD4\x03\x02\x02\x02\x0E\xD6\x03\x02\x02\x02\x10\xD8" + + "\x03\x02\x02\x02\x12\xDA\x03\x02\x02\x02\x14\xDC\x03\x02\x02\x02\x16\xDE" + + "\x03\x02\x02\x02\x18\xE2\x03\x02\x02\x02\x1A\xE7\x03\x02\x02\x02\x1C\xE9" + + "\x03\x02\x02\x02\x1E\xEB\x03\x02\x02\x02 \xEE\x03\x02\x02\x02\"\xF1\x03" + + "\x02\x02\x02$\xF6\x03\x02\x02\x02&\xFC\x03\x02\x02\x02(\xFF\x03\x02\x02" + + "\x02*\u0103\x03\x02\x02\x02,\u010C\x03\x02\x02\x02.\u0112\x03\x02\x02" + + "\x020\u0119\x03\x02\x02\x022\u011D\x03\x02\x02\x024\u0121\x03\x02\x02" + + "\x026\u0127\x03\x02\x02\x028\u012D\x03\x02\x02\x02:\u0132\x03\x02\x02" + + "\x02<\u013D\x03\x02\x02\x02>\u013F\x03\x02\x02\x02@\u0141\x03\x02\x02" + + "\x02B\u0143\x03\x02\x02\x02D\u0146\x03\x02\x02\x02F\u0148\x03\x02\x02" + + "\x02H\u014A\x03\x02\x02\x02J\u014C\x03\x02\x02\x02L\u014F\x03\x02\x02" + + "\x02N\u0152\x03\x02\x02\x02P\u0156\x03\x02\x02\x02R\u0158\x03\x02\x02" + + "\x02T\u015B\x03\x02\x02\x02V\u015D\x03\x02\x02\x02X\u0160\x03\x02\x02" + + "\x02Z\u0163\x03\x02\x02\x02\\\u0167\x03\x02\x02\x02^\u016A\x03\x02\x02" + + "\x02`\u016E\x03\x02\x02\x02b\u0170\x03\x02\x02\x02d\u0172\x03\x02\x02" + + "\x02f\u0174\x03\x02\x02\x02h\u0177\x03\x02\x02\x02j\u017A\x03\x02\x02" + + "\x02l\u017C\x03\x02\x02\x02n\u017E\x03\x02\x02\x02p\u0181\x03\x02\x02" + + "\x02r\u0184\x03\x02\x02\x02t\u0187\x03\x02\x02\x02v\u018A\x03\x02\x02" + + "\x02x\u018E\x03\x02\x02\x02z\u0191\x03\x02\x02\x02|\u0194\x03\x02\x02" + + "\x02~\u0196\x03\x02\x02\x02\x80\u0199\x03\x02\x02\x02\x82\u019C\x03\x02" + + "\x02\x02\x84\u019F\x03\x02\x02\x02\x86\u01A2\x03\x02\x02\x02\x88\u01A5" + + "\x03\x02\x02\x02\x8A\u01A8\x03\x02\x02\x02\x8C\u01AB\x03\x02\x02\x02\x8E" + + "\u01AE\x03\x02\x02\x02\x90\u01B2\x03\x02\x02\x02\x92\u01B6\x03\x02\x02" + + "\x02\x94\u01BB\x03\x02\x02\x02\x96\u01C4\x03\x02\x02\x02\x98\u01D6\x03" + + "\x02\x02\x02\x9A\u01E3\x03\x02\x02\x02\x9C\u0213\x03\x02\x02\x02\x9E\u0215" + + "\x03\x02\x02\x02\xA0\u0226\x03\x02\x02\x02\xA2\u022B\x03\x02\x02\x02\xA4" + + "\u0231\x03\x02\x02\x02\xA6\u025C\x03\x02\x02\x02\xA8\u025E\x03\x02\x02" + + "\x02\xAA\u0262\x03\x02\x02\x02\xAC\u0271\x03\x02\x02\x02\xAE\u0275\x03" + + "\x02\x02\x02\xB0\xB2\t\x02\x02\x02\xB1\xB0\x03\x02\x02\x02\xB2\xB3\x03" + + "\x02\x02\x02\xB3\xB1\x03\x02\x02\x02\xB3\xB4\x03\x02\x02\x02\xB4\xB5\x03" + + "\x02\x02\x02\xB5\xB6\b\x02\x02\x02\xB6\x05\x03\x02\x02\x02\xB7\xB8\x07" + + "1\x02\x02\xB8\xB9\x071\x02\x02\xB9\xBD\x03\x02\x02\x02\xBA\xBC\v\x02\x02" + + "\x02\xBB\xBA\x03\x02\x02\x02\xBC\xBF\x03\x02\x02\x02\xBD\xBE\x03\x02\x02" + + "\x02\xBD\xBB\x03\x02\x02\x02\xBE\xC0\x03\x02\x02\x02\xBF\xBD\x03\x02\x02" + + "\x02\xC0\xCD\t\x03\x02\x02\xC1\xC2\x071\x02\x02\xC2\xC3\x07,\x02\x02\xC3" + + "\xC7\x03\x02\x02\x02\xC4\xC6\v\x02\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6" + + "\xC9\x03\x02\x02\x02\xC7\xC8\x03\x02\x02\x02\xC7\xC5\x03\x02\x02\x02\xC8" + + "\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02\x02\x02\xCA\xCB\x07,\x02\x02\xCB" + + "\xCD\x071\x02\x02\xCC\xB7\x03\x02\x02\x02\xCC\xC1\x03\x02\x02\x02\xCD" + + "\xCE\x03\x02\x02\x02\xCE\xCF\b\x03\x02\x02\xCF\x07\x03\x02\x02\x02\xD0" + + "\xD1\x07}\x02\x02\xD1\t\x03\x02\x02\x02\xD2\xD3\x07\x7F\x02\x02\xD3\v" + + "\x03\x02\x02\x02\xD4\xD5\x07]\x02\x02\xD5\r\x03\x02\x02\x02\xD6\xD7\x07" + + "_\x02\x02\xD7\x0F\x03\x02\x02\x02\xD8\xD9\x07*\x02\x02\xD9\x11\x03\x02" + + "\x02\x02\xDA\xDB\x07+\x02\x02\xDB\x13\x03\x02\x02\x02\xDC\xDD\x07&\x02" + + "\x02\xDD\x15\x03\x02\x02\x02\xDE\xDF\x070\x02\x02\xDF\xE0\x03\x02\x02" + + "\x02\xE0\xE1\b\v\x03\x02\xE1\x17\x03\x02\x02\x02\xE2\xE3\x07A\x02\x02" + + "\xE3\xE4\x070\x02\x02\xE4\xE5\x03\x02\x02\x02\xE5\xE6\b\f\x03\x02\xE6" + + "\x19\x03\x02\x02\x02\xE7\xE8\x07.\x02\x02\xE8\x1B\x03\x02\x02\x02\xE9" + + "\xEA\x07=\x02\x02\xEA\x1D\x03\x02\x02\x02\xEB\xEC\x07k\x02\x02\xEC\xED" + + "\x07h\x02\x02\xED\x1F\x03\x02\x02\x02\xEE\xEF\x07k\x02\x02\xEF\xF0\x07" + + "p\x02\x02\xF0!\x03\x02\x02\x02\xF1\xF2\x07g\x02\x02\xF2\xF3\x07n\x02\x02" + + "\xF3\xF4\x07u\x02\x02\xF4\xF5\x07g\x02\x02\xF5#\x03\x02\x02\x02\xF6\xF7" + + "\x07y\x02\x02\xF7\xF8\x07j\x02\x02\xF8\xF9\x07k\x02\x02\xF9\xFA\x07n\x02" + + "\x02\xFA\xFB\x07g\x02\x02\xFB%\x03\x02\x02\x02\xFC\xFD\x07f\x02\x02\xFD" + + "\xFE\x07q\x02\x02\xFE\'\x03\x02\x02\x02\xFF\u0100\x07h\x02\x02\u0100\u0101" + + "\x07q\x02\x02\u0101\u0102\x07t\x02\x02\u0102)\x03\x02\x02\x02\u0103\u0104" + + "\x07e\x02\x02\u0104\u0105\x07q\x02\x02\u0105\u0106\x07p\x02\x02\u0106" + + "\u0107\x07v\x02\x02\u0107\u0108\x07k\x02\x02\u0108\u0109\x07p\x02\x02" + + "\u0109\u010A\x07w\x02\x02\u010A\u010B\x07g\x02\x02\u010B+\x03\x02\x02" + + "\x02\u010C\u010D\x07d\x02\x02\u010D\u010E\x07t\x02\x02\u010E\u010F\x07" + + "g\x02\x02\u010F\u0110\x07c\x02\x02\u0110\u0111\x07m\x02\x02\u0111-\x03" + + "\x02\x02\x02\u0112\u0113\x07t\x02\x02\u0113\u0114\x07g\x02\x02\u0114\u0115" + + "\x07v\x02\x02\u0115\u0116\x07w\x02\x02\u0116\u0117\x07t\x02\x02\u0117" + + "\u0118\x07p\x02\x02\u0118/\x03\x02\x02\x02\u0119\u011A\x07p\x02\x02\u011A" + + "\u011B\x07g\x02\x02\u011B\u011C\x07y\x02\x02\u011C1\x03\x02\x02\x02\u011D" + + "\u011E\x07v\x02\x02\u011E\u011F\x07t\x02\x02\u011F\u0120\x07{\x02\x02" + + "\u01203\x03\x02\x02\x02\u0121\u0122\x07e\x02\x02\u0122\u0123\x07c\x02" + + "\x02\u0123\u0124\x07v\x02\x02\u0124\u0125\x07e\x02\x02\u0125\u0126\x07" + + "j\x02\x02\u01265\x03\x02\x02\x02\u0127\u0128\x07v\x02\x02\u0128\u0129" + + "\x07j\x02\x02\u0129\u012A\x07t\x02\x02\u012A\u012B\x07q\x02\x02\u012B" + + "\u012C\x07y\x02\x02\u012C7\x03\x02\x02\x02\u012D\u012E\x07v\x02\x02\u012E" + + "\u012F\x07j\x02\x02\u012F\u0130\x07k\x02\x02\u0130\u0131\x07u\x02\x02" + + "\u01319\x03\x02\x02\x02\u0132\u0133\x07k\x02\x02\u0133\u0134\x07p\x02" + + "\x02\u0134\u0135\x07u\x02\x02\u0135\u0136\x07v\x02\x02\u0136\u0137\x07" + + "c\x02\x02\u0137\u0138\x07p\x02\x02\u0138\u0139\x07e\x02\x02\u0139\u013A" + + "\x07g\x02\x02\u013A\u013B\x07q\x02\x02\u013B\u013C\x07h\x02\x02\u013C" + + ";\x03\x02\x02\x02\u013D\u013E\x07#\x02\x02\u013E=\x03\x02\x02\x02\u013F" + + "\u0140\x07\x80\x02\x02\u0140?\x03\x02\x02\x02\u0141\u0142\x07,\x02\x02" + + "\u0142A\x03\x02\x02\x02\u0143\u0144\x071\x02\x02\u0144\u0145\x06!\x02" + + "\x02\u0145C\x03\x02\x02\x02\u0146\u0147\x07\'\x02\x02\u0147E\x03\x02\x02" + + "\x02\u0148\u0149\x07-\x02\x02\u0149G\x03\x02\x02\x02\u014A\u014B\x07/" + + "\x02\x02\u014BI\x03\x02\x02\x02\u014C\u014D\x07>\x02\x02\u014D\u014E\x07" + + ">\x02\x02\u014EK\x03\x02\x02\x02\u014F\u0150\x07@\x02\x02\u0150\u0151" + + "\x07@\x02\x02\u0151M\x03\x02\x02\x02\u0152\u0153\x07@\x02\x02\u0153\u0154" + + "\x07@\x02\x02\u0154\u0155\x07@\x02\x02\u0155O\x03\x02\x02\x02\u0156\u0157" + + "\x07>\x02\x02\u0157Q\x03\x02\x02\x02\u0158\u0159\x07>\x02\x02\u0159\u015A" + + "\x07?\x02\x02\u015AS\x03\x02\x02\x02\u015B\u015C\x07@\x02\x02\u015CU\x03" + + "\x02\x02\x02\u015D\u015E\x07@\x02\x02\u015E\u015F\x07?\x02\x02\u015FW" + + "\x03\x02\x02\x02\u0160\u0161\x07?\x02\x02\u0161\u0162\x07?\x02\x02\u0162" + + "Y\x03\x02\x02\x02\u0163\u0164\x07?\x02\x02\u0164\u0165\x07?\x02\x02\u0165" + + "\u0166\x07?\x02\x02\u0166[\x03\x02\x02\x02\u0167\u0168\x07#\x02\x02\u0168" + + "\u0169\x07?\x02\x02\u0169]\x03\x02\x02\x02\u016A\u016B\x07#\x02\x02\u016B" + + "\u016C\x07?\x02\x02\u016C\u016D\x07?\x02\x02\u016D_\x03\x02\x02\x02\u016E" + + "\u016F\x07(\x02\x02\u016Fa\x03\x02\x02\x02\u0170\u0171\x07`\x02\x02\u0171" + + "c\x03\x02\x02\x02\u0172\u0173\x07~\x02\x02\u0173e\x03\x02\x02\x02\u0174" + + "\u0175\x07(\x02\x02\u0175\u0176\x07(\x02\x02\u0176g\x03\x02\x02\x02\u0177" + + "\u0178\x07~\x02\x02\u0178\u0179\x07~\x02\x02\u0179i\x03\x02\x02\x02\u017A" + + "\u017B\x07A\x02\x02\u017Bk\x03\x02\x02\x02\u017C\u017D\x07<\x02\x02\u017D" + + "m\x03\x02\x02\x02\u017E\u017F\x07A\x02\x02\u017F\u0180\x07<\x02\x02\u0180" + + "o\x03\x02\x02\x02\u0181\u0182\x07<\x02\x02\u0182\u0183\x07<\x02\x02\u0183" + + "q\x03\x02\x02\x02\u0184\u0185\x07/\x02\x02\u0185\u0186\x07@\x02\x02\u0186" + + "s\x03\x02\x02\x02\u0187\u0188\x07?\x02\x02\u0188\u0189\x07\x80\x02\x02" + + "\u0189u\x03\x02\x02\x02\u018A\u018B\x07?\x02\x02\u018B\u018C\x07?\x02" + + "\x02\u018C\u018D\x07\x80\x02\x02\u018Dw\x03\x02\x02\x02\u018E\u018F\x07" + + "-\x02\x02\u018F\u0190\x07-\x02\x02\u0190y\x03\x02\x02\x02\u0191\u0192" + + "\x07/\x02\x02\u0192\u0193\x07/\x02\x02\u0193{\x03\x02\x02\x02\u0194\u0195" + + "\x07?\x02\x02\u0195}\x03\x02\x02\x02\u0196\u0197\x07-\x02\x02\u0197\u0198" + + "\x07?\x02\x02\u0198\x7F\x03\x02\x02\x02\u0199\u019A\x07/\x02\x02\u019A" + + "\u019B\x07?\x02\x02\u019B\x81\x03\x02\x02\x02\u019C\u019D\x07,\x02\x02" + + "\u019D\u019E\x07?\x02\x02\u019E\x83\x03\x02\x02\x02\u019F\u01A0\x071\x02" + + "\x02\u01A0\u01A1\x07?\x02\x02\u01A1\x85\x03\x02\x02\x02\u01A2\u01A3\x07" + + "\'\x02\x02\u01A3\u01A4\x07?\x02\x02\u01A4\x87\x03\x02\x02\x02\u01A5\u01A6" + + "\x07(\x02\x02\u01A6\u01A7\x07?\x02\x02\u01A7\x89\x03\x02\x02\x02\u01A8" + + "\u01A9\x07`\x02\x02\u01A9\u01AA\x07?\x02\x02\u01AA\x8B\x03\x02\x02\x02" + + "\u01AB\u01AC\x07~\x02\x02\u01AC\u01AD\x07?\x02\x02\u01AD\x8D\x03\x02\x02" + + "\x02\u01AE\u01AF\x07>\x02\x02\u01AF\u01B0\x07>\x02\x02\u01B0\u01B1\x07" + + "?\x02\x02\u01B1\x8F\x03\x02\x02\x02\u01B2\u01B3\x07@\x02\x02\u01B3\u01B4" + + "\x07@\x02\x02\u01B4\u01B5\x07?\x02\x02\u01B5\x91\x03\x02\x02\x02\u01B6" + + "\u01B7\x07@\x02\x02\u01B7\u01B8\x07@\x02\x02\u01B8\u01B9\x07@\x02\x02" + + "\u01B9\u01BA\x07?\x02\x02\u01BA\x93\x03\x02\x02\x02\u01BB\u01BD\x072\x02" + + "\x02\u01BC\u01BE\t\x04\x02\x02\u01BD\u01BC\x03\x02\x02\x02\u01BE\u01BF" + + "\x03\x02\x02\x02\u01BF\u01BD\x03\x02\x02\x02\u01BF\u01C0\x03\x02\x02\x02" + + "\u01C0\u01C2\x03\x02\x02\x02\u01C1\u01C3\t\x05\x02\x02\u01C2\u01C1\x03" + + "\x02\x02\x02\u01C2\u01C3\x03\x02\x02\x02\u01C3\x95\x03\x02\x02\x02\u01C4" + + "\u01C5\x072\x02\x02\u01C5\u01C7\t\x06\x02\x02\u01C6\u01C8\t\x07\x02\x02" + + "\u01C7\u01C6\x03\x02\x02\x02\u01C8\u01C9\x03\x02\x02\x02\u01C9\u01C7\x03" + + "\x02\x02\x02\u01C9\u01CA\x03\x02\x02\x02\u01CA\u01CC\x03\x02\x02\x02\u01CB" + + "\u01CD\t\x05\x02\x02\u01CC\u01CB\x03\x02\x02\x02\u01CC\u01CD\x03\x02\x02" + + "\x02\u01CD\x97\x03\x02\x02\x02\u01CE\u01D7\x072\x02\x02\u01CF\u01D3\t" + + "\b\x02\x02\u01D0\u01D2\t\t\x02\x02\u01D1\u01D0\x03\x02\x02\x02\u01D2\u01D5" + + "\x03\x02\x02\x02\u01D3\u01D1\x03\x02\x02\x02\u01D3\u01D4\x03\x02\x02\x02" + + "\u01D4\u01D7\x03\x02\x02\x02\u01D5\u01D3\x03\x02\x02\x02\u01D6\u01CE\x03" + + "\x02\x02\x02\u01D6\u01CF\x03\x02\x02\x02\u01D7\u01D9\x03\x02\x02\x02\u01D8" + + "\u01DA\t\n\x02\x02\u01D9\u01D8\x03\x02\x02\x02\u01D9\u01DA\x03\x02\x02" + + "\x02\u01DA\x99\x03\x02\x02\x02\u01DB\u01E4\x072\x02\x02\u01DC\u01E0\t" + + "\b\x02\x02\u01DD\u01DF\t\t\x02\x02\u01DE\u01DD\x03\x02\x02\x02\u01DF\u01E2" + + "\x03\x02\x02\x02\u01E0\u01DE\x03\x02\x02\x02\u01E0\u01E1\x03\x02\x02\x02" + + "\u01E1\u01E4\x03\x02\x02\x02\u01E2\u01E0\x03\x02\x02\x02\u01E3\u01DB\x03" + + "\x02\x02\x02\u01E3\u01DC\x03\x02\x02\x02\u01E4\u01EB\x03\x02\x02\x02\u01E5" + + "\u01E7\x05\x16\v\x02\u01E6\u01E8\t\t\x02\x02\u01E7\u01E6\x03\x02\x02\x02" + + "\u01E8\u01E9\x03\x02\x02\x02\u01E9\u01E7\x03\x02\x02\x02\u01E9\u01EA\x03" + + "\x02\x02\x02\u01EA\u01EC\x03\x02\x02\x02\u01EB\u01E5\x03\x02\x02\x02\u01EB" + + "\u01EC\x03\x02\x02\x02\u01EC\u01F6\x03\x02\x02\x02\u01ED\u01EF\t\v\x02" + + "\x02\u01EE\u01F0\t\f\x02\x02\u01EF\u01EE\x03\x02\x02\x02\u01EF\u01F0\x03" + + "\x02\x02\x02\u01F0\u01F2\x03\x02\x02\x02\u01F1\u01F3\t\t\x02\x02\u01F2" + + "\u01F1\x03\x02\x02\x02\u01F3\u01F4\x03\x02\x02\x02\u01F4\u01F2\x03\x02" + + "\x02\x02\u01F4\u01F5\x03\x02\x02\x02\u01F5\u01F7\x03\x02\x02\x02\u01F6" + + "\u01ED\x03\x02\x02\x02\u01F6\u01F7\x03\x02\x02\x02\u01F7\u01F9\x03\x02" + + "\x02\x02\u01F8\u01FA\t\r\x02\x02\u01F9\u01F8\x03\x02\x02\x02\u01F9\u01FA" + + "\x03\x02\x02\x02\u01FA\x9B\x03\x02\x02\x02\u01FB\u0203\x07$\x02\x02\u01FC" + + "\u01FD\x07^\x02\x02\u01FD\u0202\x07$\x02\x02\u01FE\u01FF\x07^\x02\x02" + + "\u01FF\u0202\x07^\x02\x02\u0200\u0202\n\x0E\x02\x02\u0201\u01FC\x03\x02" + + "\x02\x02\u0201\u01FE\x03\x02\x02\x02\u0201\u0200\x03\x02\x02\x02\u0202" + + "\u0205\x03\x02\x02\x02\u0203\u0204\x03\x02\x02\x02\u0203\u0201\x03\x02" + + "\x02\x02\u0204\u0206\x03\x02\x02\x02\u0205\u0203\x03\x02\x02\x02\u0206" + + "\u0214\x07$\x02\x02\u0207\u020F\x07)\x02\x02\u0208\u0209\x07^\x02\x02" + + "\u0209\u020E\x07)\x02\x02\u020A\u020B\x07^\x02\x02\u020B\u020E\x07^\x02" + + "\x02\u020C\u020E\n\x0F\x02\x02\u020D\u0208"; private static readonly _serializedATNSegment1: string = - "\u020E\x03\x02\x02\x02\u020D\u020B\x03\x02\x02\x02\u020E\u0210\x07)\x02" + - "\x02\u020F\u01F7\x03\x02\x02\x02\u020F\u0203\x03\x02\x02\x02\u0210\x9B" + - "\x03\x02\x02\x02\u0211\u0215\x071\x02\x02\u0212\u0213\x07^\x02\x02\u0213" + - "\u0216\n\x10\x02\x02\u0214\u0216\n\x11\x02\x02\u0215\u0212\x03\x02\x02" + - "\x02\u0215\u0214\x03\x02\x02\x02\u0216\u0217\x03\x02\x02\x02\u0217\u0218" + - "\x03\x02\x02\x02\u0217\u0215\x03\x02\x02\x02\u0218\u0219\x03\x02\x02\x02" + - "\u0219\u021D\x071\x02\x02\u021A\u021C\t\x12\x02\x02\u021B\u021A\x03\x02" + - "\x02\x02\u021C\u021F\x03\x02\x02\x02\u021D\u021B\x03\x02\x02\x02\u021D" + - "\u021E\x03\x02\x02\x02\u021E\u0220\x03\x02\x02\x02\u021F\u021D\x03\x02" + - "\x02\x02\u0220\u0221\x06N\x03\x02\u0221\x9D\x03\x02\x02\x02\u0222\u0223" + - "\x07v\x02\x02\u0223\u0224\x07t\x02\x02\u0224\u0225\x07w\x02\x02\u0225" + - "\u0226\x07g\x02\x02\u0226\x9F\x03\x02\x02\x02\u0227\u0228\x07h\x02\x02" + - "\u0228\u0229\x07c\x02\x02\u0229\u022A\x07n\x02\x02\u022A\u022B\x07u\x02" + - "\x02\u022B\u022C\x07g\x02\x02\u022C\xA1\x03\x02\x02\x02\u022D\u022E\x07" + - "p\x02\x02\u022E\u022F\x07w\x02\x02\u022F\u0230\x07n\x02\x02\u0230\u0231" + - "\x07n\x02\x02\u0231\xA3\x03\x02\x02\x02\u0232\u0233\x07d\x02\x02\u0233" + - "\u0234\x07q\x02\x02\u0234\u0235\x07q\x02\x02\u0235\u0236\x07n\x02\x02" + - "\u0236\u0237\x07g\x02\x02\u0237\u0238\x07c\x02\x02\u0238\u0259\x07p\x02" + - "\x02\u0239\u023A\x07d\x02\x02\u023A\u023B\x07{\x02\x02\u023B\u023C\x07" + - "v\x02\x02\u023C\u0259\x07g\x02\x02\u023D\u023E\x07u\x02\x02\u023E\u023F" + - "\x07j\x02\x02\u023F\u0240\x07q\x02\x02\u0240\u0241\x07t\x02\x02\u0241" + - "\u0259\x07v\x02\x02\u0242\u0243\x07e\x02\x02\u0243\u0244\x07j\x02\x02" + - "\u0244\u0245\x07c\x02\x02\u0245\u0259\x07t\x02\x02\u0246\u0247\x07k\x02" + - "\x02\u0247\u0248\x07p\x02\x02\u0248\u0259\x07v\x02\x02\u0249\u024A\x07" + - "n\x02\x02\u024A\u024B\x07q\x02\x02\u024B\u024C\x07p\x02\x02\u024C\u0259" + - "\x07i\x02\x02\u024D\u024E\x07h\x02\x02\u024E\u024F\x07n\x02\x02\u024F" + - "\u0250\x07q\x02\x02\u0250\u0251\x07c\x02\x02\u0251\u0259\x07v\x02\x02" + - "\u0252\u0253\x07f\x02\x02\u0253\u0254\x07q\x02\x02\u0254\u0255\x07w\x02" + - "\x02\u0255\u0256\x07d\x02\x02\u0256\u0257\x07n\x02\x02\u0257\u0259\x07" + - "g\x02\x02\u0258\u0232\x03\x02\x02\x02\u0258\u0239\x03\x02\x02\x02\u0258" + - "\u023D\x03\x02\x02\x02\u0258\u0242\x03\x02\x02\x02\u0258\u0246\x03\x02" + - "\x02\x02\u0258\u0249\x03\x02\x02\x02\u0258\u024D\x03\x02\x02\x02\u0258" + - "\u0252\x03\x02\x02\x02\u0259\xA5\x03\x02\x02\x02\u025A\u025B\x07f\x02" + - "\x02\u025B\u025C\x07g\x02\x02\u025C\u025D\x07h\x02\x02\u025D\xA7\x03\x02" + - "\x02\x02\u025E\u0262\t\x13\x02\x02\u025F\u0261\t\x14\x02\x02\u0260\u025F" + - "\x03\x02\x02\x02\u0261\u0264\x03\x02\x02\x02\u0262\u0260\x03\x02\x02\x02" + - "\u0262\u0263\x03\x02\x02\x02\u0263\xA9\x03\x02\x02\x02\u0264\u0262\x03" + - "\x02\x02\x02\u0265\u026E\x072\x02\x02\u0266\u026A\t\b\x02\x02\u0267\u0269" + - "\t\t\x02\x02\u0268\u0267\x03\x02\x02\x02\u0269\u026C\x03\x02\x02\x02\u026A" + - "\u0268\x03\x02\x02\x02\u026A\u026B\x03\x02\x02\x02\u026B\u026E\x03\x02" + - "\x02\x02\u026C\u026A\x03\x02\x02\x02\u026D\u0265\x03\x02\x02\x02\u026D" + - "\u0266\x03\x02\x02\x02\u026E\u026F\x03\x02\x02\x02\u026F\u0270\bU\x04" + - "\x02\u0270\xAB\x03\x02\x02\x02\u0271\u0275\t\x13\x02\x02\u0272\u0274\t" + - "\x14\x02\x02\u0273\u0272\x03\x02\x02\x02\u0274\u0277\x03\x02\x02\x02\u0275" + - "\u0273\x03\x02\x02\x02\u0275\u0276\x03\x02\x02\x02\u0276\u0278\x03\x02" + - "\x02\x02\u0277\u0275\x03\x02\x02\x02\u0278\u0279\bV\x04\x02\u0279\xAD" + - "\x03\x02\x02\x02$\x02\x03\xB1\xBB\xC5\xCA\u01BB\u01BE\u01C5\u01C8\u01CF" + - "\u01D2\u01D5\u01DC\u01DF\u01E5\u01E7\u01EB\u01F0\u01F2\u01F5\u01FD\u01FF" + - "\u0209\u020B\u020F\u0215\u0217\u021D\u0258\u0262\u026A\u026D\u0275\x05" + - "\b\x02\x02\x04\x03\x02\x04\x02\x02"; + "\x03\x02\x02\x02\u020D\u020A\x03\x02\x02\x02\u020D\u020C\x03\x02\x02\x02" + + "\u020E\u0211\x03\x02\x02\x02\u020F\u0210\x03\x02\x02\x02\u020F\u020D\x03" + + "\x02\x02\x02\u0210\u0212\x03\x02\x02\x02\u0211\u020F\x03\x02\x02\x02\u0212" + + "\u0214\x07)\x02\x02\u0213\u01FB\x03\x02\x02\x02\u0213\u0207\x03\x02\x02" + + "\x02\u0214\x9D\x03\x02\x02\x02\u0215\u0219\x071\x02\x02\u0216\u0217\x07" + + "^\x02\x02\u0217\u021A\n\x10\x02\x02\u0218\u021A\n\x11\x02\x02\u0219\u0216" + + "\x03\x02\x02\x02\u0219\u0218\x03\x02\x02\x02\u021A\u021B\x03\x02\x02\x02" + + "\u021B\u021C\x03\x02\x02\x02\u021B\u0219\x03\x02\x02\x02\u021C\u021D\x03" + + "\x02\x02\x02\u021D\u0221\x071\x02\x02\u021E\u0220\t\x12\x02\x02\u021F" + + "\u021E\x03\x02\x02\x02\u0220\u0223\x03\x02\x02\x02\u0221\u021F\x03\x02" + + "\x02\x02\u0221\u0222\x03\x02\x02\x02\u0222\u0224\x03\x02\x02\x02\u0223" + + "\u0221\x03\x02\x02\x02\u0224\u0225\x06O\x03\x02\u0225\x9F\x03\x02\x02" + + "\x02\u0226\u0227\x07v\x02\x02\u0227\u0228\x07t\x02\x02\u0228\u0229\x07" + + "w\x02\x02\u0229\u022A\x07g\x02\x02\u022A\xA1\x03\x02\x02\x02\u022B\u022C" + + "\x07h\x02\x02\u022C\u022D\x07c\x02\x02\u022D\u022E\x07n\x02\x02\u022E" + + "\u022F\x07u\x02\x02\u022F\u0230\x07g\x02\x02\u0230\xA3\x03\x02\x02\x02" + + "\u0231\u0232\x07p\x02\x02\u0232\u0233\x07w\x02\x02\u0233\u0234\x07n\x02" + + "\x02\u0234\u0235\x07n\x02\x02\u0235\xA5\x03\x02\x02\x02\u0236\u0237\x07" + + "d\x02\x02\u0237\u0238\x07q\x02\x02\u0238\u0239\x07q\x02\x02\u0239\u023A" + + "\x07n\x02\x02\u023A\u023B\x07g\x02\x02\u023B\u023C\x07c\x02\x02\u023C" + + "\u025D\x07p\x02\x02\u023D\u023E\x07d\x02\x02\u023E\u023F\x07{\x02\x02" + + "\u023F\u0240\x07v\x02\x02\u0240\u025D\x07g\x02\x02\u0241\u0242\x07u\x02" + + "\x02\u0242\u0243\x07j\x02\x02\u0243\u0244\x07q\x02\x02\u0244\u0245\x07" + + "t\x02\x02\u0245\u025D\x07v\x02\x02\u0246\u0247\x07e\x02\x02\u0247\u0248" + + "\x07j\x02\x02\u0248\u0249\x07c\x02\x02\u0249\u025D\x07t\x02\x02\u024A" + + "\u024B\x07k\x02\x02\u024B\u024C\x07p\x02\x02\u024C\u025D\x07v\x02\x02" + + "\u024D\u024E\x07n\x02\x02\u024E\u024F\x07q\x02\x02\u024F\u0250\x07p\x02" + + "\x02\u0250\u025D\x07i\x02\x02\u0251\u0252\x07h\x02\x02\u0252\u0253\x07" + + "n\x02\x02\u0253\u0254\x07q\x02\x02\u0254\u0255\x07c\x02\x02\u0255\u025D" + + "\x07v\x02\x02\u0256\u0257\x07f\x02\x02\u0257\u0258\x07q\x02\x02\u0258" + + "\u0259\x07w\x02\x02\u0259\u025A\x07d\x02\x02\u025A\u025B\x07n\x02\x02" + + "\u025B\u025D\x07g\x02\x02\u025C\u0236\x03\x02\x02\x02\u025C\u023D\x03" + + "\x02\x02\x02\u025C\u0241\x03\x02\x02\x02\u025C\u0246\x03\x02\x02\x02\u025C" + + "\u024A\x03\x02\x02\x02\u025C\u024D\x03\x02\x02\x02\u025C\u0251\x03\x02" + + "\x02\x02\u025C\u0256\x03\x02\x02\x02\u025D\xA7\x03\x02\x02\x02\u025E\u025F" + + "\x07f\x02\x02\u025F\u0260\x07g\x02\x02\u0260\u0261\x07h\x02\x02\u0261" + + "\xA9\x03\x02\x02\x02\u0262\u0266\t\x13\x02\x02\u0263\u0265\t\x14\x02\x02" + + "\u0264\u0263\x03\x02\x02\x02\u0265\u0268\x03\x02\x02\x02\u0266\u0264\x03" + + "\x02\x02\x02\u0266\u0267\x03\x02\x02\x02\u0267\xAB\x03\x02\x02\x02\u0268" + + "\u0266\x03\x02\x02\x02\u0269\u0272\x072\x02\x02\u026A\u026E\t\b\x02\x02" + + "\u026B\u026D\t\t\x02\x02\u026C\u026B\x03\x02\x02\x02\u026D\u0270\x03\x02" + + "\x02\x02\u026E\u026C\x03\x02\x02\x02\u026E\u026F\x03\x02\x02\x02\u026F" + + "\u0272\x03\x02\x02\x02\u0270\u026E\x03\x02\x02\x02\u0271\u0269\x03\x02" + + "\x02\x02\u0271\u026A\x03\x02\x02\x02\u0272\u0273\x03\x02\x02\x02\u0273" + + "\u0274\bV\x04\x02\u0274\xAD\x03\x02\x02\x02\u0275\u0279\t\x13\x02\x02" + + "\u0276\u0278\t\x14\x02\x02\u0277\u0276\x03\x02\x02\x02\u0278\u027B\x03" + + "\x02\x02\x02\u0279\u0277\x03\x02\x02\x02\u0279\u027A\x03\x02\x02\x02\u027A" + + "\u027C\x03\x02\x02\x02\u027B\u0279\x03\x02\x02\x02\u027C\u027D\bW\x04" + + "\x02\u027D\xAF\x03\x02\x02\x02$\x02\x03\xB3\xBD\xC7\xCC\u01BF\u01C2\u01C9" + + "\u01CC\u01D3\u01D6\u01D9\u01E0\u01E3\u01E9\u01EB\u01EF\u01F4\u01F6\u01F9" + + "\u0201\u0203\u020D\u020F\u0213\u0219\u021B\u0221\u025C\u0266\u026E\u0271" + + "\u0279\x05\b\x02\x02\x04\x03\x02\x04\x02\x02"; public static readonly _serializedATN: string = Utils.join( [ painless_lexer._serializedATNSegment0, diff --git a/packages/kbn-monaco/src/painless/antlr/painless_parser.g4 b/packages/kbn-monaco/src/painless/antlr/painless_parser.g4 index 58a9285c57a00..127b47617b1eb 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_parser.g4 +++ b/packages/kbn-monaco/src/painless/antlr/painless_parser.g4 @@ -155,7 +155,7 @@ primary | listinitializer # listinit | mapinitializer # mapinit | ID # variable - | ID arguments # calllocal + | (ID | DOLLAR) arguments # calllocal | NEW type arguments # newobject ; diff --git a/packages/kbn-monaco/src/painless/antlr/painless_parser.interp b/packages/kbn-monaco/src/painless/antlr/painless_parser.interp index 4c0a7a4399e4e..de912e1ced298 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_parser.interp +++ b/packages/kbn-monaco/src/painless/antlr/painless_parser.interp @@ -8,6 +8,7 @@ null ']' '(' ')' +'$' '.' '?.' ',' @@ -96,6 +97,7 @@ LBRACE RBRACE LP RP +DOLLAR DOT NSDOT COMMA @@ -217,4 +219,4 @@ funcref atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 87, 574, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 7, 2, 82, 10, 2, 12, 2, 14, 2, 85, 11, 2, 3, 2, 7, 2, 88, 10, 2, 12, 2, 14, 2, 91, 11, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 7, 4, 107, 10, 4, 12, 4, 14, 4, 110, 11, 4, 5, 4, 112, 10, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 120, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 130, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 138, 10, 6, 3, 6, 3, 6, 3, 6, 5, 6, 143, 10, 6, 3, 6, 3, 6, 5, 6, 147, 10, 6, 3, 6, 3, 6, 5, 6, 151, 10, 6, 3, 6, 3, 6, 3, 6, 5, 6, 156, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 6, 6, 178, 10, 6, 13, 6, 14, 6, 179, 5, 6, 182, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 196, 10, 7, 3, 7, 3, 7, 3, 7, 5, 7, 201, 10, 7, 3, 8, 3, 8, 5, 8, 205, 10, 8, 3, 9, 3, 9, 7, 9, 209, 10, 9, 12, 9, 14, 9, 212, 11, 9, 3, 9, 5, 9, 215, 10, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 223, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 7, 13, 231, 10, 13, 12, 13, 14, 13, 234, 11, 13, 3, 14, 3, 14, 3, 14, 7, 14, 239, 10, 14, 12, 14, 14, 14, 242, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 7, 15, 249, 10, 15, 12, 15, 14, 15, 252, 11, 15, 5, 15, 254, 10, 15, 3, 16, 3, 16, 3, 16, 5, 16, 259, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 310, 10, 18, 12, 18, 14, 18, 313, 11, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 5, 19, 326, 10, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 333, 10, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 342, 10, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 354, 10, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 6, 24, 361, 10, 24, 13, 24, 14, 24, 362, 3, 24, 3, 24, 3, 24, 6, 24, 368, 10, 24, 13, 24, 14, 24, 369, 3, 24, 3, 24, 3, 24, 7, 24, 375, 10, 24, 12, 24, 14, 24, 378, 11, 24, 3, 24, 3, 24, 7, 24, 382, 10, 24, 12, 24, 14, 24, 385, 11, 24, 5, 24, 387, 10, 24, 3, 25, 3, 25, 7, 25, 391, 10, 25, 12, 25, 14, 25, 394, 11, 25, 3, 25, 5, 25, 397, 10, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 418, 10, 26, 3, 27, 3, 27, 3, 27, 5, 27, 423, 10, 27, 3, 28, 3, 28, 5, 28, 427, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 6, 32, 446, 10, 32, 13, 32, 14, 32, 447, 3, 32, 3, 32, 7, 32, 452, 10, 32, 12, 32, 14, 32, 455, 11, 32, 5, 32, 457, 10, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 7, 32, 467, 10, 32, 12, 32, 14, 32, 470, 11, 32, 5, 32, 472, 10, 32, 3, 32, 3, 32, 7, 32, 476, 10, 32, 12, 32, 14, 32, 479, 11, 32, 5, 32, 481, 10, 32, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 487, 10, 33, 12, 33, 14, 33, 490, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 496, 10, 33, 3, 34, 3, 34, 3, 34, 3, 34, 7, 34, 502, 10, 34, 12, 34, 14, 34, 505, 11, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 5, 34, 512, 10, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 7, 36, 522, 10, 36, 12, 36, 14, 36, 525, 11, 36, 5, 36, 527, 10, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 5, 37, 534, 10, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 541, 10, 38, 12, 38, 14, 38, 544, 11, 38, 5, 38, 546, 10, 38, 3, 38, 5, 38, 549, 10, 38, 3, 38, 3, 38, 3, 38, 5, 38, 554, 10, 38, 3, 39, 5, 39, 557, 10, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 5, 40, 572, 10, 40, 3, 40, 2, 2, 3, 34, 41, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 2, 16, 3, 3, 14, 14, 3, 2, 32, 34, 3, 2, 35, 36, 3, 2, 58, 59, 3, 2, 37, 39, 3, 2, 40, 43, 3, 2, 44, 47, 3, 2, 62, 73, 3, 2, 60, 61, 3, 2, 30, 31, 3, 2, 83, 84, 3, 2, 74, 77, 3, 2, 11, 12, 3, 2, 86, 87, 2, 633, 2, 83, 3, 2, 2, 2, 4, 94, 3, 2, 2, 2, 6, 99, 3, 2, 2, 2, 8, 119, 3, 2, 2, 2, 10, 181, 3, 2, 2, 2, 12, 200, 3, 2, 2, 2, 14, 204, 3, 2, 2, 2, 16, 206, 3, 2, 2, 2, 18, 218, 3, 2, 2, 2, 20, 222, 3, 2, 2, 2, 22, 224, 3, 2, 2, 2, 24, 226, 3, 2, 2, 2, 26, 235, 3, 2, 2, 2, 28, 253, 3, 2, 2, 2, 30, 255, 3, 2, 2, 2, 32, 260, 3, 2, 2, 2, 34, 267, 3, 2, 2, 2, 36, 325, 3, 2, 2, 2, 38, 332, 3, 2, 2, 2, 40, 341, 3, 2, 2, 2, 42, 353, 3, 2, 2, 2, 44, 355, 3, 2, 2, 2, 46, 386, 3, 2, 2, 2, 48, 396, 3, 2, 2, 2, 50, 417, 3, 2, 2, 2, 52, 422, 3, 2, 2, 2, 54, 426, 3, 2, 2, 2, 56, 428, 3, 2, 2, 2, 58, 432, 3, 2, 2, 2, 60, 435, 3, 2, 2, 2, 62, 480, 3, 2, 2, 2, 64, 495, 3, 2, 2, 2, 66, 511, 3, 2, 2, 2, 68, 513, 3, 2, 2, 2, 70, 517, 3, 2, 2, 2, 72, 533, 3, 2, 2, 2, 74, 548, 3, 2, 2, 2, 76, 556, 3, 2, 2, 2, 78, 571, 3, 2, 2, 2, 80, 82, 5, 4, 3, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 89, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 88, 5, 8, 5, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 92, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 93, 7, 2, 2, 3, 93, 3, 3, 2, 2, 2, 94, 95, 5, 26, 14, 2, 95, 96, 7, 85, 2, 2, 96, 97, 5, 6, 4, 2, 97, 98, 5, 16, 9, 2, 98, 5, 3, 2, 2, 2, 99, 111, 7, 9, 2, 2, 100, 101, 5, 26, 14, 2, 101, 108, 7, 85, 2, 2, 102, 103, 7, 13, 2, 2, 103, 104, 5, 26, 14, 2, 104, 105, 7, 85, 2, 2, 105, 107, 3, 2, 2, 2, 106, 102, 3, 2, 2, 2, 107, 110, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 108, 109, 3, 2, 2, 2, 109, 112, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 111, 100, 3, 2, 2, 2, 111, 112, 3, 2, 2, 2, 112, 113, 3, 2, 2, 2, 113, 114, 7, 10, 2, 2, 114, 7, 3, 2, 2, 2, 115, 120, 5, 10, 6, 2, 116, 117, 5, 12, 7, 2, 117, 118, 9, 2, 2, 2, 118, 120, 3, 2, 2, 2, 119, 115, 3, 2, 2, 2, 119, 116, 3, 2, 2, 2, 120, 9, 3, 2, 2, 2, 121, 122, 7, 15, 2, 2, 122, 123, 7, 9, 2, 2, 123, 124, 5, 36, 19, 2, 124, 125, 7, 10, 2, 2, 125, 129, 5, 14, 8, 2, 126, 127, 7, 17, 2, 2, 127, 130, 5, 14, 8, 2, 128, 130, 6, 6, 2, 2, 129, 126, 3, 2, 2, 2, 129, 128, 3, 2, 2, 2, 130, 182, 3, 2, 2, 2, 131, 132, 7, 18, 2, 2, 132, 133, 7, 9, 2, 2, 133, 134, 5, 36, 19, 2, 134, 137, 7, 10, 2, 2, 135, 138, 5, 14, 8, 2, 136, 138, 5, 18, 10, 2, 137, 135, 3, 2, 2, 2, 137, 136, 3, 2, 2, 2, 138, 182, 3, 2, 2, 2, 139, 140, 7, 20, 2, 2, 140, 142, 7, 9, 2, 2, 141, 143, 5, 20, 11, 2, 142, 141, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 144, 146, 7, 14, 2, 2, 145, 147, 5, 36, 19, 2, 146, 145, 3, 2, 2, 2, 146, 147, 3, 2, 2, 2, 147, 148, 3, 2, 2, 2, 148, 150, 7, 14, 2, 2, 149, 151, 5, 22, 12, 2, 150, 149, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 3, 2, 2, 2, 152, 155, 7, 10, 2, 2, 153, 156, 5, 14, 8, 2, 154, 156, 5, 18, 10, 2, 155, 153, 3, 2, 2, 2, 155, 154, 3, 2, 2, 2, 156, 182, 3, 2, 2, 2, 157, 158, 7, 20, 2, 2, 158, 159, 7, 9, 2, 2, 159, 160, 5, 26, 14, 2, 160, 161, 7, 85, 2, 2, 161, 162, 7, 54, 2, 2, 162, 163, 5, 36, 19, 2, 163, 164, 7, 10, 2, 2, 164, 165, 5, 14, 8, 2, 165, 182, 3, 2, 2, 2, 166, 167, 7, 20, 2, 2, 167, 168, 7, 9, 2, 2, 168, 169, 7, 85, 2, 2, 169, 170, 7, 16, 2, 2, 170, 171, 5, 36, 19, 2, 171, 172, 7, 10, 2, 2, 172, 173, 5, 14, 8, 2, 173, 182, 3, 2, 2, 2, 174, 175, 7, 25, 2, 2, 175, 177, 5, 16, 9, 2, 176, 178, 5, 32, 17, 2, 177, 176, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 182, 3, 2, 2, 2, 181, 121, 3, 2, 2, 2, 181, 131, 3, 2, 2, 2, 181, 139, 3, 2, 2, 2, 181, 157, 3, 2, 2, 2, 181, 166, 3, 2, 2, 2, 181, 174, 3, 2, 2, 2, 182, 11, 3, 2, 2, 2, 183, 184, 7, 19, 2, 2, 184, 185, 5, 16, 9, 2, 185, 186, 7, 18, 2, 2, 186, 187, 7, 9, 2, 2, 187, 188, 5, 36, 19, 2, 188, 189, 7, 10, 2, 2, 189, 201, 3, 2, 2, 2, 190, 201, 5, 24, 13, 2, 191, 201, 7, 21, 2, 2, 192, 201, 7, 22, 2, 2, 193, 195, 7, 23, 2, 2, 194, 196, 5, 36, 19, 2, 195, 194, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 201, 3, 2, 2, 2, 197, 198, 7, 27, 2, 2, 198, 201, 5, 36, 19, 2, 199, 201, 5, 36, 19, 2, 200, 183, 3, 2, 2, 2, 200, 190, 3, 2, 2, 2, 200, 191, 3, 2, 2, 2, 200, 192, 3, 2, 2, 2, 200, 193, 3, 2, 2, 2, 200, 197, 3, 2, 2, 2, 200, 199, 3, 2, 2, 2, 201, 13, 3, 2, 2, 2, 202, 205, 5, 16, 9, 2, 203, 205, 5, 8, 5, 2, 204, 202, 3, 2, 2, 2, 204, 203, 3, 2, 2, 2, 205, 15, 3, 2, 2, 2, 206, 210, 7, 5, 2, 2, 207, 209, 5, 8, 5, 2, 208, 207, 3, 2, 2, 2, 209, 212, 3, 2, 2, 2, 210, 208, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 214, 3, 2, 2, 2, 212, 210, 3, 2, 2, 2, 213, 215, 5, 12, 7, 2, 214, 213, 3, 2, 2, 2, 214, 215, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 217, 7, 6, 2, 2, 217, 17, 3, 2, 2, 2, 218, 219, 7, 14, 2, 2, 219, 19, 3, 2, 2, 2, 220, 223, 5, 24, 13, 2, 221, 223, 5, 36, 19, 2, 222, 220, 3, 2, 2, 2, 222, 221, 3, 2, 2, 2, 223, 21, 3, 2, 2, 2, 224, 225, 5, 36, 19, 2, 225, 23, 3, 2, 2, 2, 226, 227, 5, 26, 14, 2, 227, 232, 5, 30, 16, 2, 228, 229, 7, 13, 2, 2, 229, 231, 5, 30, 16, 2, 230, 228, 3, 2, 2, 2, 231, 234, 3, 2, 2, 2, 232, 230, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 25, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 235, 240, 5, 28, 15, 2, 236, 237, 7, 7, 2, 2, 237, 239, 7, 8, 2, 2, 238, 236, 3, 2, 2, 2, 239, 242, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 27, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 243, 254, 7, 84, 2, 2, 244, 254, 7, 83, 2, 2, 245, 250, 7, 85, 2, 2, 246, 247, 7, 11, 2, 2, 247, 249, 7, 87, 2, 2, 248, 246, 3, 2, 2, 2, 249, 252, 3, 2, 2, 2, 250, 248, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 254, 3, 2, 2, 2, 252, 250, 3, 2, 2, 2, 253, 243, 3, 2, 2, 2, 253, 244, 3, 2, 2, 2, 253, 245, 3, 2, 2, 2, 254, 29, 3, 2, 2, 2, 255, 258, 7, 85, 2, 2, 256, 257, 7, 62, 2, 2, 257, 259, 5, 36, 19, 2, 258, 256, 3, 2, 2, 2, 258, 259, 3, 2, 2, 2, 259, 31, 3, 2, 2, 2, 260, 261, 7, 26, 2, 2, 261, 262, 7, 9, 2, 2, 262, 263, 5, 28, 15, 2, 263, 264, 7, 85, 2, 2, 264, 265, 7, 10, 2, 2, 265, 266, 5, 16, 9, 2, 266, 33, 3, 2, 2, 2, 267, 268, 8, 18, 1, 2, 268, 269, 5, 38, 20, 2, 269, 311, 3, 2, 2, 2, 270, 271, 12, 15, 2, 2, 271, 272, 9, 3, 2, 2, 272, 310, 5, 34, 18, 16, 273, 274, 12, 14, 2, 2, 274, 275, 9, 4, 2, 2, 275, 310, 5, 34, 18, 15, 276, 277, 12, 13, 2, 2, 277, 278, 9, 5, 2, 2, 278, 310, 5, 34, 18, 14, 279, 280, 12, 12, 2, 2, 280, 281, 9, 6, 2, 2, 281, 310, 5, 34, 18, 13, 282, 283, 12, 11, 2, 2, 283, 284, 9, 7, 2, 2, 284, 310, 5, 34, 18, 12, 285, 286, 12, 9, 2, 2, 286, 287, 9, 8, 2, 2, 287, 310, 5, 34, 18, 10, 288, 289, 12, 8, 2, 2, 289, 290, 7, 48, 2, 2, 290, 310, 5, 34, 18, 9, 291, 292, 12, 7, 2, 2, 292, 293, 7, 49, 2, 2, 293, 310, 5, 34, 18, 8, 294, 295, 12, 6, 2, 2, 295, 296, 7, 50, 2, 2, 296, 310, 5, 34, 18, 7, 297, 298, 12, 5, 2, 2, 298, 299, 7, 51, 2, 2, 299, 310, 5, 34, 18, 6, 300, 301, 12, 4, 2, 2, 301, 302, 7, 52, 2, 2, 302, 310, 5, 34, 18, 5, 303, 304, 12, 3, 2, 2, 304, 305, 7, 55, 2, 2, 305, 310, 5, 34, 18, 3, 306, 307, 12, 10, 2, 2, 307, 308, 7, 29, 2, 2, 308, 310, 5, 26, 14, 2, 309, 270, 3, 2, 2, 2, 309, 273, 3, 2, 2, 2, 309, 276, 3, 2, 2, 2, 309, 279, 3, 2, 2, 2, 309, 282, 3, 2, 2, 2, 309, 285, 3, 2, 2, 2, 309, 288, 3, 2, 2, 2, 309, 291, 3, 2, 2, 2, 309, 294, 3, 2, 2, 2, 309, 297, 3, 2, 2, 2, 309, 300, 3, 2, 2, 2, 309, 303, 3, 2, 2, 2, 309, 306, 3, 2, 2, 2, 310, 313, 3, 2, 2, 2, 311, 309, 3, 2, 2, 2, 311, 312, 3, 2, 2, 2, 312, 35, 3, 2, 2, 2, 313, 311, 3, 2, 2, 2, 314, 326, 5, 34, 18, 2, 315, 316, 5, 34, 18, 2, 316, 317, 7, 53, 2, 2, 317, 318, 5, 36, 19, 2, 318, 319, 7, 54, 2, 2, 319, 320, 5, 36, 19, 2, 320, 326, 3, 2, 2, 2, 321, 322, 5, 34, 18, 2, 322, 323, 9, 9, 2, 2, 323, 324, 5, 36, 19, 2, 324, 326, 3, 2, 2, 2, 325, 314, 3, 2, 2, 2, 325, 315, 3, 2, 2, 2, 325, 321, 3, 2, 2, 2, 326, 37, 3, 2, 2, 2, 327, 328, 9, 10, 2, 2, 328, 333, 5, 48, 25, 2, 329, 330, 9, 4, 2, 2, 330, 333, 5, 38, 20, 2, 331, 333, 5, 40, 21, 2, 332, 327, 3, 2, 2, 2, 332, 329, 3, 2, 2, 2, 332, 331, 3, 2, 2, 2, 333, 39, 3, 2, 2, 2, 334, 342, 5, 48, 25, 2, 335, 336, 5, 48, 25, 2, 336, 337, 9, 10, 2, 2, 337, 342, 3, 2, 2, 2, 338, 339, 9, 11, 2, 2, 339, 342, 5, 38, 20, 2, 340, 342, 5, 42, 22, 2, 341, 334, 3, 2, 2, 2, 341, 335, 3, 2, 2, 2, 341, 338, 3, 2, 2, 2, 341, 340, 3, 2, 2, 2, 342, 41, 3, 2, 2, 2, 343, 344, 7, 9, 2, 2, 344, 345, 5, 44, 23, 2, 345, 346, 7, 10, 2, 2, 346, 347, 5, 38, 20, 2, 347, 354, 3, 2, 2, 2, 348, 349, 7, 9, 2, 2, 349, 350, 5, 46, 24, 2, 350, 351, 7, 10, 2, 2, 351, 352, 5, 40, 21, 2, 352, 354, 3, 2, 2, 2, 353, 343, 3, 2, 2, 2, 353, 348, 3, 2, 2, 2, 354, 43, 3, 2, 2, 2, 355, 356, 9, 12, 2, 2, 356, 45, 3, 2, 2, 2, 357, 360, 7, 84, 2, 2, 358, 359, 7, 7, 2, 2, 359, 361, 7, 8, 2, 2, 360, 358, 3, 2, 2, 2, 361, 362, 3, 2, 2, 2, 362, 360, 3, 2, 2, 2, 362, 363, 3, 2, 2, 2, 363, 387, 3, 2, 2, 2, 364, 367, 7, 83, 2, 2, 365, 366, 7, 7, 2, 2, 366, 368, 7, 8, 2, 2, 367, 365, 3, 2, 2, 2, 368, 369, 3, 2, 2, 2, 369, 367, 3, 2, 2, 2, 369, 370, 3, 2, 2, 2, 370, 387, 3, 2, 2, 2, 371, 376, 7, 85, 2, 2, 372, 373, 7, 11, 2, 2, 373, 375, 7, 87, 2, 2, 374, 372, 3, 2, 2, 2, 375, 378, 3, 2, 2, 2, 376, 374, 3, 2, 2, 2, 376, 377, 3, 2, 2, 2, 377, 383, 3, 2, 2, 2, 378, 376, 3, 2, 2, 2, 379, 380, 7, 7, 2, 2, 380, 382, 7, 8, 2, 2, 381, 379, 3, 2, 2, 2, 382, 385, 3, 2, 2, 2, 383, 381, 3, 2, 2, 2, 383, 384, 3, 2, 2, 2, 384, 387, 3, 2, 2, 2, 385, 383, 3, 2, 2, 2, 386, 357, 3, 2, 2, 2, 386, 364, 3, 2, 2, 2, 386, 371, 3, 2, 2, 2, 387, 47, 3, 2, 2, 2, 388, 392, 5, 50, 26, 2, 389, 391, 5, 52, 27, 2, 390, 389, 3, 2, 2, 2, 391, 394, 3, 2, 2, 2, 392, 390, 3, 2, 2, 2, 392, 393, 3, 2, 2, 2, 393, 397, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 395, 397, 5, 62, 32, 2, 396, 388, 3, 2, 2, 2, 396, 395, 3, 2, 2, 2, 397, 49, 3, 2, 2, 2, 398, 399, 7, 9, 2, 2, 399, 400, 5, 36, 19, 2, 400, 401, 7, 10, 2, 2, 401, 418, 3, 2, 2, 2, 402, 418, 9, 13, 2, 2, 403, 418, 7, 80, 2, 2, 404, 418, 7, 81, 2, 2, 405, 418, 7, 82, 2, 2, 406, 418, 7, 78, 2, 2, 407, 418, 7, 79, 2, 2, 408, 418, 5, 64, 33, 2, 409, 418, 5, 66, 34, 2, 410, 418, 7, 85, 2, 2, 411, 412, 7, 85, 2, 2, 412, 418, 5, 70, 36, 2, 413, 414, 7, 24, 2, 2, 414, 415, 5, 28, 15, 2, 415, 416, 5, 70, 36, 2, 416, 418, 3, 2, 2, 2, 417, 398, 3, 2, 2, 2, 417, 402, 3, 2, 2, 2, 417, 403, 3, 2, 2, 2, 417, 404, 3, 2, 2, 2, 417, 405, 3, 2, 2, 2, 417, 406, 3, 2, 2, 2, 417, 407, 3, 2, 2, 2, 417, 408, 3, 2, 2, 2, 417, 409, 3, 2, 2, 2, 417, 410, 3, 2, 2, 2, 417, 411, 3, 2, 2, 2, 417, 413, 3, 2, 2, 2, 418, 51, 3, 2, 2, 2, 419, 423, 5, 56, 29, 2, 420, 423, 5, 58, 30, 2, 421, 423, 5, 60, 31, 2, 422, 419, 3, 2, 2, 2, 422, 420, 3, 2, 2, 2, 422, 421, 3, 2, 2, 2, 423, 53, 3, 2, 2, 2, 424, 427, 5, 56, 29, 2, 425, 427, 5, 58, 30, 2, 426, 424, 3, 2, 2, 2, 426, 425, 3, 2, 2, 2, 427, 55, 3, 2, 2, 2, 428, 429, 9, 14, 2, 2, 429, 430, 7, 87, 2, 2, 430, 431, 5, 70, 36, 2, 431, 57, 3, 2, 2, 2, 432, 433, 9, 14, 2, 2, 433, 434, 9, 15, 2, 2, 434, 59, 3, 2, 2, 2, 435, 436, 7, 7, 2, 2, 436, 437, 5, 36, 19, 2, 437, 438, 7, 8, 2, 2, 438, 61, 3, 2, 2, 2, 439, 440, 7, 24, 2, 2, 440, 445, 5, 28, 15, 2, 441, 442, 7, 7, 2, 2, 442, 443, 5, 36, 19, 2, 443, 444, 7, 8, 2, 2, 444, 446, 3, 2, 2, 2, 445, 441, 3, 2, 2, 2, 446, 447, 3, 2, 2, 2, 447, 445, 3, 2, 2, 2, 447, 448, 3, 2, 2, 2, 448, 456, 3, 2, 2, 2, 449, 453, 5, 54, 28, 2, 450, 452, 5, 52, 27, 2, 451, 450, 3, 2, 2, 2, 452, 455, 3, 2, 2, 2, 453, 451, 3, 2, 2, 2, 453, 454, 3, 2, 2, 2, 454, 457, 3, 2, 2, 2, 455, 453, 3, 2, 2, 2, 456, 449, 3, 2, 2, 2, 456, 457, 3, 2, 2, 2, 457, 481, 3, 2, 2, 2, 458, 459, 7, 24, 2, 2, 459, 460, 5, 28, 15, 2, 460, 461, 7, 7, 2, 2, 461, 462, 7, 8, 2, 2, 462, 471, 7, 5, 2, 2, 463, 468, 5, 36, 19, 2, 464, 465, 7, 13, 2, 2, 465, 467, 5, 36, 19, 2, 466, 464, 3, 2, 2, 2, 467, 470, 3, 2, 2, 2, 468, 466, 3, 2, 2, 2, 468, 469, 3, 2, 2, 2, 469, 472, 3, 2, 2, 2, 470, 468, 3, 2, 2, 2, 471, 463, 3, 2, 2, 2, 471, 472, 3, 2, 2, 2, 472, 473, 3, 2, 2, 2, 473, 477, 7, 6, 2, 2, 474, 476, 5, 52, 27, 2, 475, 474, 3, 2, 2, 2, 476, 479, 3, 2, 2, 2, 477, 475, 3, 2, 2, 2, 477, 478, 3, 2, 2, 2, 478, 481, 3, 2, 2, 2, 479, 477, 3, 2, 2, 2, 480, 439, 3, 2, 2, 2, 480, 458, 3, 2, 2, 2, 481, 63, 3, 2, 2, 2, 482, 483, 7, 7, 2, 2, 483, 488, 5, 36, 19, 2, 484, 485, 7, 13, 2, 2, 485, 487, 5, 36, 19, 2, 486, 484, 3, 2, 2, 2, 487, 490, 3, 2, 2, 2, 488, 486, 3, 2, 2, 2, 488, 489, 3, 2, 2, 2, 489, 491, 3, 2, 2, 2, 490, 488, 3, 2, 2, 2, 491, 492, 7, 8, 2, 2, 492, 496, 3, 2, 2, 2, 493, 494, 7, 7, 2, 2, 494, 496, 7, 8, 2, 2, 495, 482, 3, 2, 2, 2, 495, 493, 3, 2, 2, 2, 496, 65, 3, 2, 2, 2, 497, 498, 7, 7, 2, 2, 498, 503, 5, 68, 35, 2, 499, 500, 7, 13, 2, 2, 500, 502, 5, 68, 35, 2, 501, 499, 3, 2, 2, 2, 502, 505, 3, 2, 2, 2, 503, 501, 3, 2, 2, 2, 503, 504, 3, 2, 2, 2, 504, 506, 3, 2, 2, 2, 505, 503, 3, 2, 2, 2, 506, 507, 7, 8, 2, 2, 507, 512, 3, 2, 2, 2, 508, 509, 7, 7, 2, 2, 509, 510, 7, 54, 2, 2, 510, 512, 7, 8, 2, 2, 511, 497, 3, 2, 2, 2, 511, 508, 3, 2, 2, 2, 512, 67, 3, 2, 2, 2, 513, 514, 5, 36, 19, 2, 514, 515, 7, 54, 2, 2, 515, 516, 5, 36, 19, 2, 516, 69, 3, 2, 2, 2, 517, 526, 7, 9, 2, 2, 518, 523, 5, 72, 37, 2, 519, 520, 7, 13, 2, 2, 520, 522, 5, 72, 37, 2, 521, 519, 3, 2, 2, 2, 522, 525, 3, 2, 2, 2, 523, 521, 3, 2, 2, 2, 523, 524, 3, 2, 2, 2, 524, 527, 3, 2, 2, 2, 525, 523, 3, 2, 2, 2, 526, 518, 3, 2, 2, 2, 526, 527, 3, 2, 2, 2, 527, 528, 3, 2, 2, 2, 528, 529, 7, 10, 2, 2, 529, 71, 3, 2, 2, 2, 530, 534, 5, 36, 19, 2, 531, 534, 5, 74, 38, 2, 532, 534, 5, 78, 40, 2, 533, 530, 3, 2, 2, 2, 533, 531, 3, 2, 2, 2, 533, 532, 3, 2, 2, 2, 534, 73, 3, 2, 2, 2, 535, 549, 5, 76, 39, 2, 536, 545, 7, 9, 2, 2, 537, 542, 5, 76, 39, 2, 538, 539, 7, 13, 2, 2, 539, 541, 5, 76, 39, 2, 540, 538, 3, 2, 2, 2, 541, 544, 3, 2, 2, 2, 542, 540, 3, 2, 2, 2, 542, 543, 3, 2, 2, 2, 543, 546, 3, 2, 2, 2, 544, 542, 3, 2, 2, 2, 545, 537, 3, 2, 2, 2, 545, 546, 3, 2, 2, 2, 546, 547, 3, 2, 2, 2, 547, 549, 7, 10, 2, 2, 548, 535, 3, 2, 2, 2, 548, 536, 3, 2, 2, 2, 549, 550, 3, 2, 2, 2, 550, 553, 7, 57, 2, 2, 551, 554, 5, 16, 9, 2, 552, 554, 5, 36, 19, 2, 553, 551, 3, 2, 2, 2, 553, 552, 3, 2, 2, 2, 554, 75, 3, 2, 2, 2, 555, 557, 5, 26, 14, 2, 556, 555, 3, 2, 2, 2, 556, 557, 3, 2, 2, 2, 557, 558, 3, 2, 2, 2, 558, 559, 7, 85, 2, 2, 559, 77, 3, 2, 2, 2, 560, 561, 5, 26, 14, 2, 561, 562, 7, 56, 2, 2, 562, 563, 7, 85, 2, 2, 563, 572, 3, 2, 2, 2, 564, 565, 5, 26, 14, 2, 565, 566, 7, 56, 2, 2, 566, 567, 7, 24, 2, 2, 567, 572, 3, 2, 2, 2, 568, 569, 7, 28, 2, 2, 569, 570, 7, 56, 2, 2, 570, 572, 7, 85, 2, 2, 571, 560, 3, 2, 2, 2, 571, 564, 3, 2, 2, 2, 571, 568, 3, 2, 2, 2, 572, 79, 3, 2, 2, 2, 62, 83, 89, 108, 111, 119, 129, 137, 142, 146, 150, 155, 179, 181, 195, 200, 204, 210, 214, 222, 232, 240, 250, 253, 258, 309, 311, 325, 332, 341, 353, 362, 369, 376, 383, 386, 392, 396, 417, 422, 426, 447, 453, 456, 468, 471, 477, 480, 488, 495, 503, 511, 523, 526, 533, 542, 545, 548, 553, 556, 571] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 88, 574, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 7, 2, 82, 10, 2, 12, 2, 14, 2, 85, 11, 2, 3, 2, 7, 2, 88, 10, 2, 12, 2, 14, 2, 91, 11, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 7, 4, 107, 10, 4, 12, 4, 14, 4, 110, 11, 4, 5, 4, 112, 10, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 120, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 130, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 138, 10, 6, 3, 6, 3, 6, 3, 6, 5, 6, 143, 10, 6, 3, 6, 3, 6, 5, 6, 147, 10, 6, 3, 6, 3, 6, 5, 6, 151, 10, 6, 3, 6, 3, 6, 3, 6, 5, 6, 156, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 6, 6, 178, 10, 6, 13, 6, 14, 6, 179, 5, 6, 182, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 196, 10, 7, 3, 7, 3, 7, 3, 7, 5, 7, 201, 10, 7, 3, 8, 3, 8, 5, 8, 205, 10, 8, 3, 9, 3, 9, 7, 9, 209, 10, 9, 12, 9, 14, 9, 212, 11, 9, 3, 9, 5, 9, 215, 10, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 223, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 7, 13, 231, 10, 13, 12, 13, 14, 13, 234, 11, 13, 3, 14, 3, 14, 3, 14, 7, 14, 239, 10, 14, 12, 14, 14, 14, 242, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 7, 15, 249, 10, 15, 12, 15, 14, 15, 252, 11, 15, 5, 15, 254, 10, 15, 3, 16, 3, 16, 3, 16, 5, 16, 259, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 310, 10, 18, 12, 18, 14, 18, 313, 11, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 5, 19, 326, 10, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 333, 10, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 342, 10, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 354, 10, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 6, 24, 361, 10, 24, 13, 24, 14, 24, 362, 3, 24, 3, 24, 3, 24, 6, 24, 368, 10, 24, 13, 24, 14, 24, 369, 3, 24, 3, 24, 3, 24, 7, 24, 375, 10, 24, 12, 24, 14, 24, 378, 11, 24, 3, 24, 3, 24, 7, 24, 382, 10, 24, 12, 24, 14, 24, 385, 11, 24, 5, 24, 387, 10, 24, 3, 25, 3, 25, 7, 25, 391, 10, 25, 12, 25, 14, 25, 394, 11, 25, 3, 25, 5, 25, 397, 10, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 418, 10, 26, 3, 27, 3, 27, 3, 27, 5, 27, 423, 10, 27, 3, 28, 3, 28, 5, 28, 427, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 6, 32, 446, 10, 32, 13, 32, 14, 32, 447, 3, 32, 3, 32, 7, 32, 452, 10, 32, 12, 32, 14, 32, 455, 11, 32, 5, 32, 457, 10, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 7, 32, 467, 10, 32, 12, 32, 14, 32, 470, 11, 32, 5, 32, 472, 10, 32, 3, 32, 3, 32, 7, 32, 476, 10, 32, 12, 32, 14, 32, 479, 11, 32, 5, 32, 481, 10, 32, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 487, 10, 33, 12, 33, 14, 33, 490, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 496, 10, 33, 3, 34, 3, 34, 3, 34, 3, 34, 7, 34, 502, 10, 34, 12, 34, 14, 34, 505, 11, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 5, 34, 512, 10, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 7, 36, 522, 10, 36, 12, 36, 14, 36, 525, 11, 36, 5, 36, 527, 10, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 5, 37, 534, 10, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 541, 10, 38, 12, 38, 14, 38, 544, 11, 38, 5, 38, 546, 10, 38, 3, 38, 5, 38, 549, 10, 38, 3, 38, 3, 38, 3, 38, 5, 38, 554, 10, 38, 3, 39, 5, 39, 557, 10, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 5, 40, 572, 10, 40, 3, 40, 2, 2, 3, 34, 41, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 2, 17, 3, 3, 15, 15, 3, 2, 33, 35, 3, 2, 36, 37, 3, 2, 59, 60, 3, 2, 38, 40, 3, 2, 41, 44, 3, 2, 45, 48, 3, 2, 63, 74, 3, 2, 61, 62, 3, 2, 31, 32, 3, 2, 84, 85, 3, 2, 75, 78, 4, 2, 11, 11, 86, 86, 3, 2, 12, 13, 3, 2, 87, 88, 2, 633, 2, 83, 3, 2, 2, 2, 4, 94, 3, 2, 2, 2, 6, 99, 3, 2, 2, 2, 8, 119, 3, 2, 2, 2, 10, 181, 3, 2, 2, 2, 12, 200, 3, 2, 2, 2, 14, 204, 3, 2, 2, 2, 16, 206, 3, 2, 2, 2, 18, 218, 3, 2, 2, 2, 20, 222, 3, 2, 2, 2, 22, 224, 3, 2, 2, 2, 24, 226, 3, 2, 2, 2, 26, 235, 3, 2, 2, 2, 28, 253, 3, 2, 2, 2, 30, 255, 3, 2, 2, 2, 32, 260, 3, 2, 2, 2, 34, 267, 3, 2, 2, 2, 36, 325, 3, 2, 2, 2, 38, 332, 3, 2, 2, 2, 40, 341, 3, 2, 2, 2, 42, 353, 3, 2, 2, 2, 44, 355, 3, 2, 2, 2, 46, 386, 3, 2, 2, 2, 48, 396, 3, 2, 2, 2, 50, 417, 3, 2, 2, 2, 52, 422, 3, 2, 2, 2, 54, 426, 3, 2, 2, 2, 56, 428, 3, 2, 2, 2, 58, 432, 3, 2, 2, 2, 60, 435, 3, 2, 2, 2, 62, 480, 3, 2, 2, 2, 64, 495, 3, 2, 2, 2, 66, 511, 3, 2, 2, 2, 68, 513, 3, 2, 2, 2, 70, 517, 3, 2, 2, 2, 72, 533, 3, 2, 2, 2, 74, 548, 3, 2, 2, 2, 76, 556, 3, 2, 2, 2, 78, 571, 3, 2, 2, 2, 80, 82, 5, 4, 3, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 89, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 88, 5, 8, 5, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 92, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 93, 7, 2, 2, 3, 93, 3, 3, 2, 2, 2, 94, 95, 5, 26, 14, 2, 95, 96, 7, 86, 2, 2, 96, 97, 5, 6, 4, 2, 97, 98, 5, 16, 9, 2, 98, 5, 3, 2, 2, 2, 99, 111, 7, 9, 2, 2, 100, 101, 5, 26, 14, 2, 101, 108, 7, 86, 2, 2, 102, 103, 7, 14, 2, 2, 103, 104, 5, 26, 14, 2, 104, 105, 7, 86, 2, 2, 105, 107, 3, 2, 2, 2, 106, 102, 3, 2, 2, 2, 107, 110, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 108, 109, 3, 2, 2, 2, 109, 112, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 111, 100, 3, 2, 2, 2, 111, 112, 3, 2, 2, 2, 112, 113, 3, 2, 2, 2, 113, 114, 7, 10, 2, 2, 114, 7, 3, 2, 2, 2, 115, 120, 5, 10, 6, 2, 116, 117, 5, 12, 7, 2, 117, 118, 9, 2, 2, 2, 118, 120, 3, 2, 2, 2, 119, 115, 3, 2, 2, 2, 119, 116, 3, 2, 2, 2, 120, 9, 3, 2, 2, 2, 121, 122, 7, 16, 2, 2, 122, 123, 7, 9, 2, 2, 123, 124, 5, 36, 19, 2, 124, 125, 7, 10, 2, 2, 125, 129, 5, 14, 8, 2, 126, 127, 7, 18, 2, 2, 127, 130, 5, 14, 8, 2, 128, 130, 6, 6, 2, 2, 129, 126, 3, 2, 2, 2, 129, 128, 3, 2, 2, 2, 130, 182, 3, 2, 2, 2, 131, 132, 7, 19, 2, 2, 132, 133, 7, 9, 2, 2, 133, 134, 5, 36, 19, 2, 134, 137, 7, 10, 2, 2, 135, 138, 5, 14, 8, 2, 136, 138, 5, 18, 10, 2, 137, 135, 3, 2, 2, 2, 137, 136, 3, 2, 2, 2, 138, 182, 3, 2, 2, 2, 139, 140, 7, 21, 2, 2, 140, 142, 7, 9, 2, 2, 141, 143, 5, 20, 11, 2, 142, 141, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 144, 146, 7, 15, 2, 2, 145, 147, 5, 36, 19, 2, 146, 145, 3, 2, 2, 2, 146, 147, 3, 2, 2, 2, 147, 148, 3, 2, 2, 2, 148, 150, 7, 15, 2, 2, 149, 151, 5, 22, 12, 2, 150, 149, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 3, 2, 2, 2, 152, 155, 7, 10, 2, 2, 153, 156, 5, 14, 8, 2, 154, 156, 5, 18, 10, 2, 155, 153, 3, 2, 2, 2, 155, 154, 3, 2, 2, 2, 156, 182, 3, 2, 2, 2, 157, 158, 7, 21, 2, 2, 158, 159, 7, 9, 2, 2, 159, 160, 5, 26, 14, 2, 160, 161, 7, 86, 2, 2, 161, 162, 7, 55, 2, 2, 162, 163, 5, 36, 19, 2, 163, 164, 7, 10, 2, 2, 164, 165, 5, 14, 8, 2, 165, 182, 3, 2, 2, 2, 166, 167, 7, 21, 2, 2, 167, 168, 7, 9, 2, 2, 168, 169, 7, 86, 2, 2, 169, 170, 7, 17, 2, 2, 170, 171, 5, 36, 19, 2, 171, 172, 7, 10, 2, 2, 172, 173, 5, 14, 8, 2, 173, 182, 3, 2, 2, 2, 174, 175, 7, 26, 2, 2, 175, 177, 5, 16, 9, 2, 176, 178, 5, 32, 17, 2, 177, 176, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 182, 3, 2, 2, 2, 181, 121, 3, 2, 2, 2, 181, 131, 3, 2, 2, 2, 181, 139, 3, 2, 2, 2, 181, 157, 3, 2, 2, 2, 181, 166, 3, 2, 2, 2, 181, 174, 3, 2, 2, 2, 182, 11, 3, 2, 2, 2, 183, 184, 7, 20, 2, 2, 184, 185, 5, 16, 9, 2, 185, 186, 7, 19, 2, 2, 186, 187, 7, 9, 2, 2, 187, 188, 5, 36, 19, 2, 188, 189, 7, 10, 2, 2, 189, 201, 3, 2, 2, 2, 190, 201, 5, 24, 13, 2, 191, 201, 7, 22, 2, 2, 192, 201, 7, 23, 2, 2, 193, 195, 7, 24, 2, 2, 194, 196, 5, 36, 19, 2, 195, 194, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 201, 3, 2, 2, 2, 197, 198, 7, 28, 2, 2, 198, 201, 5, 36, 19, 2, 199, 201, 5, 36, 19, 2, 200, 183, 3, 2, 2, 2, 200, 190, 3, 2, 2, 2, 200, 191, 3, 2, 2, 2, 200, 192, 3, 2, 2, 2, 200, 193, 3, 2, 2, 2, 200, 197, 3, 2, 2, 2, 200, 199, 3, 2, 2, 2, 201, 13, 3, 2, 2, 2, 202, 205, 5, 16, 9, 2, 203, 205, 5, 8, 5, 2, 204, 202, 3, 2, 2, 2, 204, 203, 3, 2, 2, 2, 205, 15, 3, 2, 2, 2, 206, 210, 7, 5, 2, 2, 207, 209, 5, 8, 5, 2, 208, 207, 3, 2, 2, 2, 209, 212, 3, 2, 2, 2, 210, 208, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 214, 3, 2, 2, 2, 212, 210, 3, 2, 2, 2, 213, 215, 5, 12, 7, 2, 214, 213, 3, 2, 2, 2, 214, 215, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 217, 7, 6, 2, 2, 217, 17, 3, 2, 2, 2, 218, 219, 7, 15, 2, 2, 219, 19, 3, 2, 2, 2, 220, 223, 5, 24, 13, 2, 221, 223, 5, 36, 19, 2, 222, 220, 3, 2, 2, 2, 222, 221, 3, 2, 2, 2, 223, 21, 3, 2, 2, 2, 224, 225, 5, 36, 19, 2, 225, 23, 3, 2, 2, 2, 226, 227, 5, 26, 14, 2, 227, 232, 5, 30, 16, 2, 228, 229, 7, 14, 2, 2, 229, 231, 5, 30, 16, 2, 230, 228, 3, 2, 2, 2, 231, 234, 3, 2, 2, 2, 232, 230, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 25, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 235, 240, 5, 28, 15, 2, 236, 237, 7, 7, 2, 2, 237, 239, 7, 8, 2, 2, 238, 236, 3, 2, 2, 2, 239, 242, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 27, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 243, 254, 7, 85, 2, 2, 244, 254, 7, 84, 2, 2, 245, 250, 7, 86, 2, 2, 246, 247, 7, 12, 2, 2, 247, 249, 7, 88, 2, 2, 248, 246, 3, 2, 2, 2, 249, 252, 3, 2, 2, 2, 250, 248, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 254, 3, 2, 2, 2, 252, 250, 3, 2, 2, 2, 253, 243, 3, 2, 2, 2, 253, 244, 3, 2, 2, 2, 253, 245, 3, 2, 2, 2, 254, 29, 3, 2, 2, 2, 255, 258, 7, 86, 2, 2, 256, 257, 7, 63, 2, 2, 257, 259, 5, 36, 19, 2, 258, 256, 3, 2, 2, 2, 258, 259, 3, 2, 2, 2, 259, 31, 3, 2, 2, 2, 260, 261, 7, 27, 2, 2, 261, 262, 7, 9, 2, 2, 262, 263, 5, 28, 15, 2, 263, 264, 7, 86, 2, 2, 264, 265, 7, 10, 2, 2, 265, 266, 5, 16, 9, 2, 266, 33, 3, 2, 2, 2, 267, 268, 8, 18, 1, 2, 268, 269, 5, 38, 20, 2, 269, 311, 3, 2, 2, 2, 270, 271, 12, 15, 2, 2, 271, 272, 9, 3, 2, 2, 272, 310, 5, 34, 18, 16, 273, 274, 12, 14, 2, 2, 274, 275, 9, 4, 2, 2, 275, 310, 5, 34, 18, 15, 276, 277, 12, 13, 2, 2, 277, 278, 9, 5, 2, 2, 278, 310, 5, 34, 18, 14, 279, 280, 12, 12, 2, 2, 280, 281, 9, 6, 2, 2, 281, 310, 5, 34, 18, 13, 282, 283, 12, 11, 2, 2, 283, 284, 9, 7, 2, 2, 284, 310, 5, 34, 18, 12, 285, 286, 12, 9, 2, 2, 286, 287, 9, 8, 2, 2, 287, 310, 5, 34, 18, 10, 288, 289, 12, 8, 2, 2, 289, 290, 7, 49, 2, 2, 290, 310, 5, 34, 18, 9, 291, 292, 12, 7, 2, 2, 292, 293, 7, 50, 2, 2, 293, 310, 5, 34, 18, 8, 294, 295, 12, 6, 2, 2, 295, 296, 7, 51, 2, 2, 296, 310, 5, 34, 18, 7, 297, 298, 12, 5, 2, 2, 298, 299, 7, 52, 2, 2, 299, 310, 5, 34, 18, 6, 300, 301, 12, 4, 2, 2, 301, 302, 7, 53, 2, 2, 302, 310, 5, 34, 18, 5, 303, 304, 12, 3, 2, 2, 304, 305, 7, 56, 2, 2, 305, 310, 5, 34, 18, 3, 306, 307, 12, 10, 2, 2, 307, 308, 7, 30, 2, 2, 308, 310, 5, 26, 14, 2, 309, 270, 3, 2, 2, 2, 309, 273, 3, 2, 2, 2, 309, 276, 3, 2, 2, 2, 309, 279, 3, 2, 2, 2, 309, 282, 3, 2, 2, 2, 309, 285, 3, 2, 2, 2, 309, 288, 3, 2, 2, 2, 309, 291, 3, 2, 2, 2, 309, 294, 3, 2, 2, 2, 309, 297, 3, 2, 2, 2, 309, 300, 3, 2, 2, 2, 309, 303, 3, 2, 2, 2, 309, 306, 3, 2, 2, 2, 310, 313, 3, 2, 2, 2, 311, 309, 3, 2, 2, 2, 311, 312, 3, 2, 2, 2, 312, 35, 3, 2, 2, 2, 313, 311, 3, 2, 2, 2, 314, 326, 5, 34, 18, 2, 315, 316, 5, 34, 18, 2, 316, 317, 7, 54, 2, 2, 317, 318, 5, 36, 19, 2, 318, 319, 7, 55, 2, 2, 319, 320, 5, 36, 19, 2, 320, 326, 3, 2, 2, 2, 321, 322, 5, 34, 18, 2, 322, 323, 9, 9, 2, 2, 323, 324, 5, 36, 19, 2, 324, 326, 3, 2, 2, 2, 325, 314, 3, 2, 2, 2, 325, 315, 3, 2, 2, 2, 325, 321, 3, 2, 2, 2, 326, 37, 3, 2, 2, 2, 327, 328, 9, 10, 2, 2, 328, 333, 5, 48, 25, 2, 329, 330, 9, 4, 2, 2, 330, 333, 5, 38, 20, 2, 331, 333, 5, 40, 21, 2, 332, 327, 3, 2, 2, 2, 332, 329, 3, 2, 2, 2, 332, 331, 3, 2, 2, 2, 333, 39, 3, 2, 2, 2, 334, 342, 5, 48, 25, 2, 335, 336, 5, 48, 25, 2, 336, 337, 9, 10, 2, 2, 337, 342, 3, 2, 2, 2, 338, 339, 9, 11, 2, 2, 339, 342, 5, 38, 20, 2, 340, 342, 5, 42, 22, 2, 341, 334, 3, 2, 2, 2, 341, 335, 3, 2, 2, 2, 341, 338, 3, 2, 2, 2, 341, 340, 3, 2, 2, 2, 342, 41, 3, 2, 2, 2, 343, 344, 7, 9, 2, 2, 344, 345, 5, 44, 23, 2, 345, 346, 7, 10, 2, 2, 346, 347, 5, 38, 20, 2, 347, 354, 3, 2, 2, 2, 348, 349, 7, 9, 2, 2, 349, 350, 5, 46, 24, 2, 350, 351, 7, 10, 2, 2, 351, 352, 5, 40, 21, 2, 352, 354, 3, 2, 2, 2, 353, 343, 3, 2, 2, 2, 353, 348, 3, 2, 2, 2, 354, 43, 3, 2, 2, 2, 355, 356, 9, 12, 2, 2, 356, 45, 3, 2, 2, 2, 357, 360, 7, 85, 2, 2, 358, 359, 7, 7, 2, 2, 359, 361, 7, 8, 2, 2, 360, 358, 3, 2, 2, 2, 361, 362, 3, 2, 2, 2, 362, 360, 3, 2, 2, 2, 362, 363, 3, 2, 2, 2, 363, 387, 3, 2, 2, 2, 364, 367, 7, 84, 2, 2, 365, 366, 7, 7, 2, 2, 366, 368, 7, 8, 2, 2, 367, 365, 3, 2, 2, 2, 368, 369, 3, 2, 2, 2, 369, 367, 3, 2, 2, 2, 369, 370, 3, 2, 2, 2, 370, 387, 3, 2, 2, 2, 371, 376, 7, 86, 2, 2, 372, 373, 7, 12, 2, 2, 373, 375, 7, 88, 2, 2, 374, 372, 3, 2, 2, 2, 375, 378, 3, 2, 2, 2, 376, 374, 3, 2, 2, 2, 376, 377, 3, 2, 2, 2, 377, 383, 3, 2, 2, 2, 378, 376, 3, 2, 2, 2, 379, 380, 7, 7, 2, 2, 380, 382, 7, 8, 2, 2, 381, 379, 3, 2, 2, 2, 382, 385, 3, 2, 2, 2, 383, 381, 3, 2, 2, 2, 383, 384, 3, 2, 2, 2, 384, 387, 3, 2, 2, 2, 385, 383, 3, 2, 2, 2, 386, 357, 3, 2, 2, 2, 386, 364, 3, 2, 2, 2, 386, 371, 3, 2, 2, 2, 387, 47, 3, 2, 2, 2, 388, 392, 5, 50, 26, 2, 389, 391, 5, 52, 27, 2, 390, 389, 3, 2, 2, 2, 391, 394, 3, 2, 2, 2, 392, 390, 3, 2, 2, 2, 392, 393, 3, 2, 2, 2, 393, 397, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 395, 397, 5, 62, 32, 2, 396, 388, 3, 2, 2, 2, 396, 395, 3, 2, 2, 2, 397, 49, 3, 2, 2, 2, 398, 399, 7, 9, 2, 2, 399, 400, 5, 36, 19, 2, 400, 401, 7, 10, 2, 2, 401, 418, 3, 2, 2, 2, 402, 418, 9, 13, 2, 2, 403, 418, 7, 81, 2, 2, 404, 418, 7, 82, 2, 2, 405, 418, 7, 83, 2, 2, 406, 418, 7, 79, 2, 2, 407, 418, 7, 80, 2, 2, 408, 418, 5, 64, 33, 2, 409, 418, 5, 66, 34, 2, 410, 418, 7, 86, 2, 2, 411, 412, 9, 14, 2, 2, 412, 418, 5, 70, 36, 2, 413, 414, 7, 25, 2, 2, 414, 415, 5, 28, 15, 2, 415, 416, 5, 70, 36, 2, 416, 418, 3, 2, 2, 2, 417, 398, 3, 2, 2, 2, 417, 402, 3, 2, 2, 2, 417, 403, 3, 2, 2, 2, 417, 404, 3, 2, 2, 2, 417, 405, 3, 2, 2, 2, 417, 406, 3, 2, 2, 2, 417, 407, 3, 2, 2, 2, 417, 408, 3, 2, 2, 2, 417, 409, 3, 2, 2, 2, 417, 410, 3, 2, 2, 2, 417, 411, 3, 2, 2, 2, 417, 413, 3, 2, 2, 2, 418, 51, 3, 2, 2, 2, 419, 423, 5, 56, 29, 2, 420, 423, 5, 58, 30, 2, 421, 423, 5, 60, 31, 2, 422, 419, 3, 2, 2, 2, 422, 420, 3, 2, 2, 2, 422, 421, 3, 2, 2, 2, 423, 53, 3, 2, 2, 2, 424, 427, 5, 56, 29, 2, 425, 427, 5, 58, 30, 2, 426, 424, 3, 2, 2, 2, 426, 425, 3, 2, 2, 2, 427, 55, 3, 2, 2, 2, 428, 429, 9, 15, 2, 2, 429, 430, 7, 88, 2, 2, 430, 431, 5, 70, 36, 2, 431, 57, 3, 2, 2, 2, 432, 433, 9, 15, 2, 2, 433, 434, 9, 16, 2, 2, 434, 59, 3, 2, 2, 2, 435, 436, 7, 7, 2, 2, 436, 437, 5, 36, 19, 2, 437, 438, 7, 8, 2, 2, 438, 61, 3, 2, 2, 2, 439, 440, 7, 25, 2, 2, 440, 445, 5, 28, 15, 2, 441, 442, 7, 7, 2, 2, 442, 443, 5, 36, 19, 2, 443, 444, 7, 8, 2, 2, 444, 446, 3, 2, 2, 2, 445, 441, 3, 2, 2, 2, 446, 447, 3, 2, 2, 2, 447, 445, 3, 2, 2, 2, 447, 448, 3, 2, 2, 2, 448, 456, 3, 2, 2, 2, 449, 453, 5, 54, 28, 2, 450, 452, 5, 52, 27, 2, 451, 450, 3, 2, 2, 2, 452, 455, 3, 2, 2, 2, 453, 451, 3, 2, 2, 2, 453, 454, 3, 2, 2, 2, 454, 457, 3, 2, 2, 2, 455, 453, 3, 2, 2, 2, 456, 449, 3, 2, 2, 2, 456, 457, 3, 2, 2, 2, 457, 481, 3, 2, 2, 2, 458, 459, 7, 25, 2, 2, 459, 460, 5, 28, 15, 2, 460, 461, 7, 7, 2, 2, 461, 462, 7, 8, 2, 2, 462, 471, 7, 5, 2, 2, 463, 468, 5, 36, 19, 2, 464, 465, 7, 14, 2, 2, 465, 467, 5, 36, 19, 2, 466, 464, 3, 2, 2, 2, 467, 470, 3, 2, 2, 2, 468, 466, 3, 2, 2, 2, 468, 469, 3, 2, 2, 2, 469, 472, 3, 2, 2, 2, 470, 468, 3, 2, 2, 2, 471, 463, 3, 2, 2, 2, 471, 472, 3, 2, 2, 2, 472, 473, 3, 2, 2, 2, 473, 477, 7, 6, 2, 2, 474, 476, 5, 52, 27, 2, 475, 474, 3, 2, 2, 2, 476, 479, 3, 2, 2, 2, 477, 475, 3, 2, 2, 2, 477, 478, 3, 2, 2, 2, 478, 481, 3, 2, 2, 2, 479, 477, 3, 2, 2, 2, 480, 439, 3, 2, 2, 2, 480, 458, 3, 2, 2, 2, 481, 63, 3, 2, 2, 2, 482, 483, 7, 7, 2, 2, 483, 488, 5, 36, 19, 2, 484, 485, 7, 14, 2, 2, 485, 487, 5, 36, 19, 2, 486, 484, 3, 2, 2, 2, 487, 490, 3, 2, 2, 2, 488, 486, 3, 2, 2, 2, 488, 489, 3, 2, 2, 2, 489, 491, 3, 2, 2, 2, 490, 488, 3, 2, 2, 2, 491, 492, 7, 8, 2, 2, 492, 496, 3, 2, 2, 2, 493, 494, 7, 7, 2, 2, 494, 496, 7, 8, 2, 2, 495, 482, 3, 2, 2, 2, 495, 493, 3, 2, 2, 2, 496, 65, 3, 2, 2, 2, 497, 498, 7, 7, 2, 2, 498, 503, 5, 68, 35, 2, 499, 500, 7, 14, 2, 2, 500, 502, 5, 68, 35, 2, 501, 499, 3, 2, 2, 2, 502, 505, 3, 2, 2, 2, 503, 501, 3, 2, 2, 2, 503, 504, 3, 2, 2, 2, 504, 506, 3, 2, 2, 2, 505, 503, 3, 2, 2, 2, 506, 507, 7, 8, 2, 2, 507, 512, 3, 2, 2, 2, 508, 509, 7, 7, 2, 2, 509, 510, 7, 55, 2, 2, 510, 512, 7, 8, 2, 2, 511, 497, 3, 2, 2, 2, 511, 508, 3, 2, 2, 2, 512, 67, 3, 2, 2, 2, 513, 514, 5, 36, 19, 2, 514, 515, 7, 55, 2, 2, 515, 516, 5, 36, 19, 2, 516, 69, 3, 2, 2, 2, 517, 526, 7, 9, 2, 2, 518, 523, 5, 72, 37, 2, 519, 520, 7, 14, 2, 2, 520, 522, 5, 72, 37, 2, 521, 519, 3, 2, 2, 2, 522, 525, 3, 2, 2, 2, 523, 521, 3, 2, 2, 2, 523, 524, 3, 2, 2, 2, 524, 527, 3, 2, 2, 2, 525, 523, 3, 2, 2, 2, 526, 518, 3, 2, 2, 2, 526, 527, 3, 2, 2, 2, 527, 528, 3, 2, 2, 2, 528, 529, 7, 10, 2, 2, 529, 71, 3, 2, 2, 2, 530, 534, 5, 36, 19, 2, 531, 534, 5, 74, 38, 2, 532, 534, 5, 78, 40, 2, 533, 530, 3, 2, 2, 2, 533, 531, 3, 2, 2, 2, 533, 532, 3, 2, 2, 2, 534, 73, 3, 2, 2, 2, 535, 549, 5, 76, 39, 2, 536, 545, 7, 9, 2, 2, 537, 542, 5, 76, 39, 2, 538, 539, 7, 14, 2, 2, 539, 541, 5, 76, 39, 2, 540, 538, 3, 2, 2, 2, 541, 544, 3, 2, 2, 2, 542, 540, 3, 2, 2, 2, 542, 543, 3, 2, 2, 2, 543, 546, 3, 2, 2, 2, 544, 542, 3, 2, 2, 2, 545, 537, 3, 2, 2, 2, 545, 546, 3, 2, 2, 2, 546, 547, 3, 2, 2, 2, 547, 549, 7, 10, 2, 2, 548, 535, 3, 2, 2, 2, 548, 536, 3, 2, 2, 2, 549, 550, 3, 2, 2, 2, 550, 553, 7, 58, 2, 2, 551, 554, 5, 16, 9, 2, 552, 554, 5, 36, 19, 2, 553, 551, 3, 2, 2, 2, 553, 552, 3, 2, 2, 2, 554, 75, 3, 2, 2, 2, 555, 557, 5, 26, 14, 2, 556, 555, 3, 2, 2, 2, 556, 557, 3, 2, 2, 2, 557, 558, 3, 2, 2, 2, 558, 559, 7, 86, 2, 2, 559, 77, 3, 2, 2, 2, 560, 561, 5, 26, 14, 2, 561, 562, 7, 57, 2, 2, 562, 563, 7, 86, 2, 2, 563, 572, 3, 2, 2, 2, 564, 565, 5, 26, 14, 2, 565, 566, 7, 57, 2, 2, 566, 567, 7, 25, 2, 2, 567, 572, 3, 2, 2, 2, 568, 569, 7, 29, 2, 2, 569, 570, 7, 57, 2, 2, 570, 572, 7, 86, 2, 2, 571, 560, 3, 2, 2, 2, 571, 564, 3, 2, 2, 2, 571, 568, 3, 2, 2, 2, 572, 79, 3, 2, 2, 2, 62, 83, 89, 108, 111, 119, 129, 137, 142, 146, 150, 155, 179, 181, 195, 200, 204, 210, 214, 222, 232, 240, 250, 253, 258, 309, 311, 325, 332, 341, 353, 362, 369, 376, 383, 386, 392, 396, 417, 422, 426, 447, 453, 456, 468, 471, 477, 480, 488, 495, 503, 511, 523, 526, 533, 542, 545, 548, 553, 556, 571] \ No newline at end of file diff --git a/packages/kbn-monaco/src/painless/antlr/painless_parser.tokens b/packages/kbn-monaco/src/painless/antlr/painless_parser.tokens index ff62343c92ba5..3a1af2a5154d3 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_parser.tokens +++ b/packages/kbn-monaco/src/painless/antlr/painless_parser.tokens @@ -6,153 +6,155 @@ LBRACE=5 RBRACE=6 LP=7 RP=8 -DOT=9 -NSDOT=10 -COMMA=11 -SEMICOLON=12 -IF=13 -IN=14 -ELSE=15 -WHILE=16 -DO=17 -FOR=18 -CONTINUE=19 -BREAK=20 -RETURN=21 -NEW=22 -TRY=23 -CATCH=24 -THROW=25 -THIS=26 -INSTANCEOF=27 -BOOLNOT=28 -BWNOT=29 -MUL=30 -DIV=31 -REM=32 -ADD=33 -SUB=34 -LSH=35 -RSH=36 -USH=37 -LT=38 -LTE=39 -GT=40 -GTE=41 -EQ=42 -EQR=43 -NE=44 -NER=45 -BWAND=46 -XOR=47 -BWOR=48 -BOOLAND=49 -BOOLOR=50 -COND=51 -COLON=52 -ELVIS=53 -REF=54 -ARROW=55 -FIND=56 -MATCH=57 -INCR=58 -DECR=59 -ASSIGN=60 -AADD=61 -ASUB=62 -AMUL=63 -ADIV=64 -AREM=65 -AAND=66 -AXOR=67 -AOR=68 -ALSH=69 -ARSH=70 -AUSH=71 -OCTAL=72 -HEX=73 -INTEGER=74 -DECIMAL=75 -STRING=76 -REGEX=77 -TRUE=78 -FALSE=79 -NULL=80 -PRIMITIVE=81 -DEF=82 -ID=83 -DOTINTEGER=84 -DOTID=85 +DOLLAR=9 +DOT=10 +NSDOT=11 +COMMA=12 +SEMICOLON=13 +IF=14 +IN=15 +ELSE=16 +WHILE=17 +DO=18 +FOR=19 +CONTINUE=20 +BREAK=21 +RETURN=22 +NEW=23 +TRY=24 +CATCH=25 +THROW=26 +THIS=27 +INSTANCEOF=28 +BOOLNOT=29 +BWNOT=30 +MUL=31 +DIV=32 +REM=33 +ADD=34 +SUB=35 +LSH=36 +RSH=37 +USH=38 +LT=39 +LTE=40 +GT=41 +GTE=42 +EQ=43 +EQR=44 +NE=45 +NER=46 +BWAND=47 +XOR=48 +BWOR=49 +BOOLAND=50 +BOOLOR=51 +COND=52 +COLON=53 +ELVIS=54 +REF=55 +ARROW=56 +FIND=57 +MATCH=58 +INCR=59 +DECR=60 +ASSIGN=61 +AADD=62 +ASUB=63 +AMUL=64 +ADIV=65 +AREM=66 +AAND=67 +AXOR=68 +AOR=69 +ALSH=70 +ARSH=71 +AUSH=72 +OCTAL=73 +HEX=74 +INTEGER=75 +DECIMAL=76 +STRING=77 +REGEX=78 +TRUE=79 +FALSE=80 +NULL=81 +PRIMITIVE=82 +DEF=83 +ID=84 +DOTINTEGER=85 +DOTID=86 '{'=3 '}'=4 '['=5 ']'=6 '('=7 ')'=8 -'.'=9 -'?.'=10 -','=11 -';'=12 -'if'=13 -'in'=14 -'else'=15 -'while'=16 -'do'=17 -'for'=18 -'continue'=19 -'break'=20 -'return'=21 -'new'=22 -'try'=23 -'catch'=24 -'throw'=25 -'this'=26 -'instanceof'=27 -'!'=28 -'~'=29 -'*'=30 -'/'=31 -'%'=32 -'+'=33 -'-'=34 -'<<'=35 -'>>'=36 -'>>>'=37 -'<'=38 -'<='=39 -'>'=40 -'>='=41 -'=='=42 -'==='=43 -'!='=44 -'!=='=45 -'&'=46 -'^'=47 -'|'=48 -'&&'=49 -'||'=50 -'?'=51 -':'=52 -'?:'=53 -'::'=54 -'->'=55 -'=~'=56 -'==~'=57 -'++'=58 -'--'=59 -'='=60 -'+='=61 -'-='=62 -'*='=63 -'/='=64 -'%='=65 -'&='=66 -'^='=67 -'|='=68 -'<<='=69 -'>>='=70 -'>>>='=71 -'true'=78 -'false'=79 -'null'=80 -'def'=82 +'$'=9 +'.'=10 +'?.'=11 +','=12 +';'=13 +'if'=14 +'in'=15 +'else'=16 +'while'=17 +'do'=18 +'for'=19 +'continue'=20 +'break'=21 +'return'=22 +'new'=23 +'try'=24 +'catch'=25 +'throw'=26 +'this'=27 +'instanceof'=28 +'!'=29 +'~'=30 +'*'=31 +'/'=32 +'%'=33 +'+'=34 +'-'=35 +'<<'=36 +'>>'=37 +'>>>'=38 +'<'=39 +'<='=40 +'>'=41 +'>='=42 +'=='=43 +'==='=44 +'!='=45 +'!=='=46 +'&'=47 +'^'=48 +'|'=49 +'&&'=50 +'||'=51 +'?'=52 +':'=53 +'?:'=54 +'::'=55 +'->'=56 +'=~'=57 +'==~'=58 +'++'=59 +'--'=60 +'='=61 +'+='=62 +'-='=63 +'*='=64 +'/='=65 +'%='=66 +'&='=67 +'^='=68 +'|='=69 +'<<='=70 +'>>='=71 +'>>>='=72 +'true'=79 +'false'=80 +'null'=81 +'def'=83 diff --git a/packages/kbn-monaco/src/painless/antlr/painless_parser.ts b/packages/kbn-monaco/src/painless/antlr/painless_parser.ts index 320e310a0a9a2..760c9b2c7319a 100644 --- a/packages/kbn-monaco/src/painless/antlr/painless_parser.ts +++ b/packages/kbn-monaco/src/painless/antlr/painless_parser.ts @@ -35,83 +35,84 @@ export class painless_parser extends Parser { public static readonly RBRACE = 6; public static readonly LP = 7; public static readonly RP = 8; - public static readonly DOT = 9; - public static readonly NSDOT = 10; - public static readonly COMMA = 11; - public static readonly SEMICOLON = 12; - public static readonly IF = 13; - public static readonly IN = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly DO = 17; - public static readonly FOR = 18; - public static readonly CONTINUE = 19; - public static readonly BREAK = 20; - public static readonly RETURN = 21; - public static readonly NEW = 22; - public static readonly TRY = 23; - public static readonly CATCH = 24; - public static readonly THROW = 25; - public static readonly THIS = 26; - public static readonly INSTANCEOF = 27; - public static readonly BOOLNOT = 28; - public static readonly BWNOT = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly REM = 32; - public static readonly ADD = 33; - public static readonly SUB = 34; - public static readonly LSH = 35; - public static readonly RSH = 36; - public static readonly USH = 37; - public static readonly LT = 38; - public static readonly LTE = 39; - public static readonly GT = 40; - public static readonly GTE = 41; - public static readonly EQ = 42; - public static readonly EQR = 43; - public static readonly NE = 44; - public static readonly NER = 45; - public static readonly BWAND = 46; - public static readonly XOR = 47; - public static readonly BWOR = 48; - public static readonly BOOLAND = 49; - public static readonly BOOLOR = 50; - public static readonly COND = 51; - public static readonly COLON = 52; - public static readonly ELVIS = 53; - public static readonly REF = 54; - public static readonly ARROW = 55; - public static readonly FIND = 56; - public static readonly MATCH = 57; - public static readonly INCR = 58; - public static readonly DECR = 59; - public static readonly ASSIGN = 60; - public static readonly AADD = 61; - public static readonly ASUB = 62; - public static readonly AMUL = 63; - public static readonly ADIV = 64; - public static readonly AREM = 65; - public static readonly AAND = 66; - public static readonly AXOR = 67; - public static readonly AOR = 68; - public static readonly ALSH = 69; - public static readonly ARSH = 70; - public static readonly AUSH = 71; - public static readonly OCTAL = 72; - public static readonly HEX = 73; - public static readonly INTEGER = 74; - public static readonly DECIMAL = 75; - public static readonly STRING = 76; - public static readonly REGEX = 77; - public static readonly TRUE = 78; - public static readonly FALSE = 79; - public static readonly NULL = 80; - public static readonly PRIMITIVE = 81; - public static readonly DEF = 82; - public static readonly ID = 83; - public static readonly DOTINTEGER = 84; - public static readonly DOTID = 85; + public static readonly DOLLAR = 9; + public static readonly DOT = 10; + public static readonly NSDOT = 11; + public static readonly COMMA = 12; + public static readonly SEMICOLON = 13; + public static readonly IF = 14; + public static readonly IN = 15; + public static readonly ELSE = 16; + public static readonly WHILE = 17; + public static readonly DO = 18; + public static readonly FOR = 19; + public static readonly CONTINUE = 20; + public static readonly BREAK = 21; + public static readonly RETURN = 22; + public static readonly NEW = 23; + public static readonly TRY = 24; + public static readonly CATCH = 25; + public static readonly THROW = 26; + public static readonly THIS = 27; + public static readonly INSTANCEOF = 28; + public static readonly BOOLNOT = 29; + public static readonly BWNOT = 30; + public static readonly MUL = 31; + public static readonly DIV = 32; + public static readonly REM = 33; + public static readonly ADD = 34; + public static readonly SUB = 35; + public static readonly LSH = 36; + public static readonly RSH = 37; + public static readonly USH = 38; + public static readonly LT = 39; + public static readonly LTE = 40; + public static readonly GT = 41; + public static readonly GTE = 42; + public static readonly EQ = 43; + public static readonly EQR = 44; + public static readonly NE = 45; + public static readonly NER = 46; + public static readonly BWAND = 47; + public static readonly XOR = 48; + public static readonly BWOR = 49; + public static readonly BOOLAND = 50; + public static readonly BOOLOR = 51; + public static readonly COND = 52; + public static readonly COLON = 53; + public static readonly ELVIS = 54; + public static readonly REF = 55; + public static readonly ARROW = 56; + public static readonly FIND = 57; + public static readonly MATCH = 58; + public static readonly INCR = 59; + public static readonly DECR = 60; + public static readonly ASSIGN = 61; + public static readonly AADD = 62; + public static readonly ASUB = 63; + public static readonly AMUL = 64; + public static readonly ADIV = 65; + public static readonly AREM = 66; + public static readonly AAND = 67; + public static readonly AXOR = 68; + public static readonly AOR = 69; + public static readonly ALSH = 70; + public static readonly ARSH = 71; + public static readonly AUSH = 72; + public static readonly OCTAL = 73; + public static readonly HEX = 74; + public static readonly INTEGER = 75; + public static readonly DECIMAL = 76; + public static readonly STRING = 77; + public static readonly REGEX = 78; + public static readonly TRUE = 79; + public static readonly FALSE = 80; + public static readonly NULL = 81; + public static readonly PRIMITIVE = 82; + public static readonly DEF = 83; + public static readonly ID = 84; + public static readonly DOTINTEGER = 85; + public static readonly DOTID = 86; public static readonly RULE_source = 0; public static readonly RULE_function = 1; public static readonly RULE_parameters = 2; @@ -164,27 +165,27 @@ export class painless_parser extends Parser { private static readonly _LITERAL_NAMES: Array = [ undefined, undefined, undefined, "'{'", "'}'", "'['", "']'", "'('", "')'", - "'.'", "'?.'", "','", "';'", "'if'", "'in'", "'else'", "'while'", "'do'", - "'for'", "'continue'", "'break'", "'return'", "'new'", "'try'", "'catch'", - "'throw'", "'this'", "'instanceof'", "'!'", "'~'", "'*'", "'/'", "'%'", - "'+'", "'-'", "'<<'", "'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", "'=='", - "'==='", "'!='", "'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", - "':'", "'?:'", "'::'", "'->'", "'=~'", "'==~'", "'++'", "'--'", "'='", - "'+='", "'-='", "'*='", "'/='", "'%='", "'&='", "'^='", "'|='", "'<<='", - "'>>='", "'>>>='", undefined, undefined, undefined, undefined, undefined, - undefined, "'true'", "'false'", "'null'", undefined, "'def'", + "'$'", "'.'", "'?.'", "','", "';'", "'if'", "'in'", "'else'", "'while'", + "'do'", "'for'", "'continue'", "'break'", "'return'", "'new'", "'try'", + "'catch'", "'throw'", "'this'", "'instanceof'", "'!'", "'~'", "'*'", "'/'", + "'%'", "'+'", "'-'", "'<<'", "'>>'", "'>>>'", "'<'", "'<='", "'>'", "'>='", + "'=='", "'==='", "'!='", "'!=='", "'&'", "'^'", "'|'", "'&&'", "'||'", + "'?'", "':'", "'?:'", "'::'", "'->'", "'=~'", "'==~'", "'++'", "'--'", + "'='", "'+='", "'-='", "'*='", "'/='", "'%='", "'&='", "'^='", "'|='", + "'<<='", "'>>='", "'>>>='", undefined, undefined, undefined, undefined, + undefined, undefined, "'true'", "'false'", "'null'", undefined, "'def'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ undefined, "WS", "COMMENT", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "LP", - "RP", "DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", "WHILE", - "DO", "FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", "THROW", - "THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", "ADD", - "SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", "NE", - "NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", "ELVIS", - "REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", "ASUB", - "AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", "AUSH", - "OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", "FALSE", - "NULL", "PRIMITIVE", "DEF", "ID", "DOTINTEGER", "DOTID", + "RP", "DOLLAR", "DOT", "NSDOT", "COMMA", "SEMICOLON", "IF", "IN", "ELSE", + "WHILE", "DO", "FOR", "CONTINUE", "BREAK", "RETURN", "NEW", "TRY", "CATCH", + "THROW", "THIS", "INSTANCEOF", "BOOLNOT", "BWNOT", "MUL", "DIV", "REM", + "ADD", "SUB", "LSH", "RSH", "USH", "LT", "LTE", "GT", "GTE", "EQ", "EQR", + "NE", "NER", "BWAND", "XOR", "BWOR", "BOOLAND", "BOOLOR", "COND", "COLON", + "ELVIS", "REF", "ARROW", "FIND", "MATCH", "INCR", "DECR", "ASSIGN", "AADD", + "ASUB", "AMUL", "ADIV", "AREM", "AAND", "AXOR", "AOR", "ALSH", "ARSH", + "AUSH", "OCTAL", "HEX", "INTEGER", "DECIMAL", "STRING", "REGEX", "TRUE", + "FALSE", "NULL", "PRIMITIVE", "DEF", "ID", "DOTINTEGER", "DOTID", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(painless_parser._LITERAL_NAMES, painless_parser._SYMBOLIC_NAMES, []); @@ -236,7 +237,7 @@ export class painless_parser extends Parser { this.state = 87; this._errHandler.sync(this); _la = this._input.LA(1); - while (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.IF - 5)) | (1 << (painless_parser.WHILE - 5)) | (1 << (painless_parser.DO - 5)) | (1 << (painless_parser.FOR - 5)) | (1 << (painless_parser.CONTINUE - 5)) | (1 << (painless_parser.BREAK - 5)) | (1 << (painless_parser.RETURN - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.TRY - 5)) | (1 << (painless_parser.THROW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.PRIMITIVE - 58)) | (1 << (painless_parser.DEF - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + while (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.IF - 5)) | (1 << (painless_parser.WHILE - 5)) | (1 << (painless_parser.DO - 5)) | (1 << (painless_parser.FOR - 5)) | (1 << (painless_parser.CONTINUE - 5)) | (1 << (painless_parser.BREAK - 5)) | (1 << (painless_parser.RETURN - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.TRY - 5)) | (1 << (painless_parser.THROW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.PRIMITIVE - 59)) | (1 << (painless_parser.DEF - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { { this.state = 84; @@ -309,7 +310,7 @@ export class painless_parser extends Parser { this.state = 109; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 81)) & ~0x1F) === 0 && ((1 << (_la - 81)) & ((1 << (painless_parser.PRIMITIVE - 81)) | (1 << (painless_parser.DEF - 81)) | (1 << (painless_parser.ID - 81)))) !== 0)) { + if (((((_la - 82)) & ~0x1F) === 0 && ((1 << (_la - 82)) & ((1 << (painless_parser.PRIMITIVE - 82)) | (1 << (painless_parser.DEF - 82)) | (1 << (painless_parser.ID - 82)))) !== 0)) { { this.state = 98; this.decltype(); @@ -375,6 +376,7 @@ export class painless_parser extends Parser { break; case painless_parser.LBRACE: case painless_parser.LP: + case painless_parser.DOLLAR: case painless_parser.DO: case painless_parser.CONTINUE: case painless_parser.BREAK: @@ -501,6 +503,7 @@ export class painless_parser extends Parser { case painless_parser.LBRACK: case painless_parser.LBRACE: case painless_parser.LP: + case painless_parser.DOLLAR: case painless_parser.IF: case painless_parser.WHILE: case painless_parser.DO: @@ -557,7 +560,7 @@ export class painless_parser extends Parser { this.state = 140; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.PRIMITIVE - 58)) | (1 << (painless_parser.DEF - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.PRIMITIVE - 59)) | (1 << (painless_parser.DEF - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 139; this.initializer(); @@ -569,7 +572,7 @@ export class painless_parser extends Parser { this.state = 144; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 143; this.expression(); @@ -581,7 +584,7 @@ export class painless_parser extends Parser { this.state = 148; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 147; this.afterthought(); @@ -596,6 +599,7 @@ export class painless_parser extends Parser { case painless_parser.LBRACK: case painless_parser.LBRACE: case painless_parser.LP: + case painless_parser.DOLLAR: case painless_parser.IF: case painless_parser.WHILE: case painless_parser.DO: @@ -795,7 +799,7 @@ export class painless_parser extends Parser { this.state = 193; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 192; this.expression(); @@ -857,6 +861,7 @@ export class painless_parser extends Parser { break; case painless_parser.LBRACE: case painless_parser.LP: + case painless_parser.DOLLAR: case painless_parser.IF: case painless_parser.WHILE: case painless_parser.DO: @@ -939,7 +944,7 @@ export class painless_parser extends Parser { this.state = 212; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DO - 5)) | (1 << (painless_parser.CONTINUE - 5)) | (1 << (painless_parser.BREAK - 5)) | (1 << (painless_parser.RETURN - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.THROW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.PRIMITIVE - 58)) | (1 << (painless_parser.DEF - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.DO - 5)) | (1 << (painless_parser.CONTINUE - 5)) | (1 << (painless_parser.BREAK - 5)) | (1 << (painless_parser.RETURN - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.THROW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.PRIMITIVE - 59)) | (1 << (painless_parser.DEF - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 211; this.dstatement(); @@ -1332,7 +1337,7 @@ export class painless_parser extends Parser { } this.state = 269; _la = this._input.LA(1); - if (!(((((_la - 30)) & ~0x1F) === 0 && ((1 << (_la - 30)) & ((1 << (painless_parser.MUL - 30)) | (1 << (painless_parser.DIV - 30)) | (1 << (painless_parser.REM - 30)))) !== 0))) { + if (!(((((_la - 31)) & ~0x1F) === 0 && ((1 << (_la - 31)) & ((1 << (painless_parser.MUL - 31)) | (1 << (painless_parser.DIV - 31)) | (1 << (painless_parser.REM - 31)))) !== 0))) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1407,7 +1412,7 @@ export class painless_parser extends Parser { } this.state = 278; _la = this._input.LA(1); - if (!(((((_la - 35)) & ~0x1F) === 0 && ((1 << (_la - 35)) & ((1 << (painless_parser.LSH - 35)) | (1 << (painless_parser.RSH - 35)) | (1 << (painless_parser.USH - 35)))) !== 0))) { + if (!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & ((1 << (painless_parser.LSH - 36)) | (1 << (painless_parser.RSH - 36)) | (1 << (painless_parser.USH - 36)))) !== 0))) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1432,7 +1437,7 @@ export class painless_parser extends Parser { } this.state = 281; _la = this._input.LA(1); - if (!(((((_la - 38)) & ~0x1F) === 0 && ((1 << (_la - 38)) & ((1 << (painless_parser.LT - 38)) | (1 << (painless_parser.LTE - 38)) | (1 << (painless_parser.GT - 38)) | (1 << (painless_parser.GTE - 38)))) !== 0))) { + if (!(((((_la - 39)) & ~0x1F) === 0 && ((1 << (_la - 39)) & ((1 << (painless_parser.LT - 39)) | (1 << (painless_parser.LTE - 39)) | (1 << (painless_parser.GT - 39)) | (1 << (painless_parser.GTE - 39)))) !== 0))) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1457,7 +1462,7 @@ export class painless_parser extends Parser { } this.state = 284; _la = this._input.LA(1); - if (!(((((_la - 42)) & ~0x1F) === 0 && ((1 << (_la - 42)) & ((1 << (painless_parser.EQ - 42)) | (1 << (painless_parser.EQR - 42)) | (1 << (painless_parser.NE - 42)) | (1 << (painless_parser.NER - 42)))) !== 0))) { + if (!(((((_la - 43)) & ~0x1F) === 0 && ((1 << (_la - 43)) & ((1 << (painless_parser.EQ - 43)) | (1 << (painless_parser.EQR - 43)) | (1 << (painless_parser.NE - 43)) | (1 << (painless_parser.NER - 43)))) !== 0))) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1642,7 +1647,7 @@ export class painless_parser extends Parser { this.noncondexpression(0); this.state = 320; _la = this._input.LA(1); - if (!(((((_la - 60)) & ~0x1F) === 0 && ((1 << (_la - 60)) & ((1 << (painless_parser.ASSIGN - 60)) | (1 << (painless_parser.AADD - 60)) | (1 << (painless_parser.ASUB - 60)) | (1 << (painless_parser.AMUL - 60)) | (1 << (painless_parser.ADIV - 60)) | (1 << (painless_parser.AREM - 60)) | (1 << (painless_parser.AAND - 60)) | (1 << (painless_parser.AXOR - 60)) | (1 << (painless_parser.AOR - 60)) | (1 << (painless_parser.ALSH - 60)) | (1 << (painless_parser.ARSH - 60)) | (1 << (painless_parser.AUSH - 60)))) !== 0))) { + if (!(((((_la - 61)) & ~0x1F) === 0 && ((1 << (_la - 61)) & ((1 << (painless_parser.ASSIGN - 61)) | (1 << (painless_parser.AADD - 61)) | (1 << (painless_parser.ASUB - 61)) | (1 << (painless_parser.AMUL - 61)) | (1 << (painless_parser.ADIV - 61)) | (1 << (painless_parser.AREM - 61)) | (1 << (painless_parser.AAND - 61)) | (1 << (painless_parser.AXOR - 61)) | (1 << (painless_parser.AOR - 61)) | (1 << (painless_parser.ALSH - 61)) | (1 << (painless_parser.ARSH - 61)) | (1 << (painless_parser.AUSH - 61)))) !== 0))) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1725,6 +1730,7 @@ export class painless_parser extends Parser { break; case painless_parser.LBRACE: case painless_parser.LP: + case painless_parser.DOLLAR: case painless_parser.NEW: case painless_parser.BOOLNOT: case painless_parser.BWNOT: @@ -2134,7 +2140,7 @@ export class painless_parser extends Parser { { this.state = 400; _la = this._input.LA(1); - if (!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & ((1 << (painless_parser.OCTAL - 72)) | (1 << (painless_parser.HEX - 72)) | (1 << (painless_parser.INTEGER - 72)) | (1 << (painless_parser.DECIMAL - 72)))) !== 0))) { + if (!(((((_la - 73)) & ~0x1F) === 0 && ((1 << (_la - 73)) & ((1 << (painless_parser.OCTAL - 73)) | (1 << (painless_parser.HEX - 73)) | (1 << (painless_parser.INTEGER - 73)) | (1 << (painless_parser.DECIMAL - 73)))) !== 0))) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -2224,7 +2230,17 @@ export class painless_parser extends Parser { this.enterOuterAlt(_localctx, 11); { this.state = 409; - this.match(painless_parser.ID); + _la = this._input.LA(1); + if (!(_la === painless_parser.DOLLAR || _la === painless_parser.ID)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } this.state = 410; this.arguments(); } @@ -2549,7 +2565,7 @@ export class painless_parser extends Parser { this.state = 469; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 461; this.expression(); @@ -2777,7 +2793,7 @@ export class painless_parser extends Parser { this.state = 524; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.THIS - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (painless_parser.INCR - 58)) | (1 << (painless_parser.DECR - 58)) | (1 << (painless_parser.OCTAL - 58)) | (1 << (painless_parser.HEX - 58)) | (1 << (painless_parser.INTEGER - 58)) | (1 << (painless_parser.DECIMAL - 58)) | (1 << (painless_parser.STRING - 58)) | (1 << (painless_parser.REGEX - 58)) | (1 << (painless_parser.TRUE - 58)) | (1 << (painless_parser.FALSE - 58)) | (1 << (painless_parser.NULL - 58)) | (1 << (painless_parser.PRIMITIVE - 58)) | (1 << (painless_parser.DEF - 58)) | (1 << (painless_parser.ID - 58)))) !== 0)) { + if (((((_la - 5)) & ~0x1F) === 0 && ((1 << (_la - 5)) & ((1 << (painless_parser.LBRACE - 5)) | (1 << (painless_parser.LP - 5)) | (1 << (painless_parser.DOLLAR - 5)) | (1 << (painless_parser.NEW - 5)) | (1 << (painless_parser.THIS - 5)) | (1 << (painless_parser.BOOLNOT - 5)) | (1 << (painless_parser.BWNOT - 5)) | (1 << (painless_parser.ADD - 5)) | (1 << (painless_parser.SUB - 5)))) !== 0) || ((((_la - 59)) & ~0x1F) === 0 && ((1 << (_la - 59)) & ((1 << (painless_parser.INCR - 59)) | (1 << (painless_parser.DECR - 59)) | (1 << (painless_parser.OCTAL - 59)) | (1 << (painless_parser.HEX - 59)) | (1 << (painless_parser.INTEGER - 59)) | (1 << (painless_parser.DECIMAL - 59)) | (1 << (painless_parser.STRING - 59)) | (1 << (painless_parser.REGEX - 59)) | (1 << (painless_parser.TRUE - 59)) | (1 << (painless_parser.FALSE - 59)) | (1 << (painless_parser.NULL - 59)) | (1 << (painless_parser.PRIMITIVE - 59)) | (1 << (painless_parser.DEF - 59)) | (1 << (painless_parser.ID - 59)))) !== 0)) { { this.state = 516; this.argument(); @@ -2892,7 +2908,7 @@ export class painless_parser extends Parser { this.state = 543; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 81)) & ~0x1F) === 0 && ((1 << (_la - 81)) & ((1 << (painless_parser.PRIMITIVE - 81)) | (1 << (painless_parser.DEF - 81)) | (1 << (painless_parser.ID - 81)))) !== 0)) { + if (((((_la - 82)) & ~0x1F) === 0 && ((1 << (_la - 82)) & ((1 << (painless_parser.PRIMITIVE - 82)) | (1 << (painless_parser.DEF - 82)) | (1 << (painless_parser.ID - 82)))) !== 0)) { { this.state = 535; this.lamtype(); @@ -2935,6 +2951,7 @@ export class painless_parser extends Parser { break; case painless_parser.LBRACE: case painless_parser.LP: + case painless_parser.DOLLAR: case painless_parser.NEW: case painless_parser.BOOLNOT: case painless_parser.BWNOT: @@ -3137,7 +3154,7 @@ export class painless_parser extends Parser { private static readonly _serializedATNSegments: number = 2; private static readonly _serializedATNSegment0: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03W\u023E\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03X\u023E\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + @@ -3200,63 +3217,63 @@ export class painless_parser extends Parser { "\")\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02" + "\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02" + "(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02" + - "D\x02F\x02H\x02J\x02L\x02N\x02\x02\x10\x03\x03\x0E\x0E\x03\x02 \"\x03" + - "\x02#$\x03\x02:;\x03\x02%\'\x03\x02(+\x03\x02,/\x03\x02>I\x03\x02<=\x03" + - "\x02\x1E\x1F\x03\x02ST\x03\x02JM\x03\x02\v\f\x03\x02VW\x02\u0279\x02S" + - "\x03\x02\x02\x02\x04^\x03\x02\x02\x02\x06c\x03\x02\x02\x02\bw\x03\x02" + - "\x02\x02\n\xB5\x03\x02\x02\x02\f\xC8\x03\x02\x02\x02\x0E\xCC\x03\x02\x02" + - "\x02\x10\xCE\x03\x02\x02\x02\x12\xDA\x03\x02\x02\x02\x14\xDE\x03\x02\x02" + - "\x02\x16\xE0\x03\x02\x02\x02\x18\xE2\x03\x02\x02\x02\x1A\xEB\x03\x02\x02" + - "\x02\x1C\xFD\x03\x02\x02\x02\x1E\xFF\x03\x02\x02\x02 \u0104\x03\x02\x02" + - "\x02\"\u010B\x03\x02\x02\x02$\u0145\x03\x02\x02\x02&\u014C\x03\x02\x02" + - "\x02(\u0155\x03\x02\x02\x02*\u0161\x03\x02\x02\x02,\u0163\x03\x02\x02" + - "\x02.\u0182\x03\x02\x02\x020\u018C\x03\x02\x02\x022\u01A1\x03\x02\x02" + - "\x024\u01A6\x03\x02\x02\x026\u01AA\x03\x02\x02\x028\u01AC\x03\x02\x02" + - "\x02:\u01B0\x03\x02\x02\x02<\u01B3\x03\x02\x02\x02>\u01E0\x03\x02\x02" + - "\x02@\u01EF\x03\x02\x02\x02B\u01FF\x03\x02\x02\x02D\u0201\x03\x02\x02" + - "\x02F\u0205\x03\x02\x02\x02H\u0215\x03\x02\x02\x02J\u0224\x03\x02\x02" + - "\x02L\u022C\x03\x02\x02\x02N\u023B\x03\x02\x02\x02PR\x05\x04\x03\x02Q" + - "P\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02ST\x03\x02\x02\x02" + + "D\x02F\x02H\x02J\x02L\x02N\x02\x02\x11\x03\x03\x0F\x0F\x03\x02!#\x03\x02" + + "$%\x03\x02;<\x03\x02&(\x03\x02),\x03\x02-0\x03\x02?J\x03\x02=>\x03\x02" + + "\x1F \x03\x02TU\x03\x02KN\x04\x02\v\vVV\x03\x02\f\r\x03\x02WX\x02\u0279" + + "\x02S\x03\x02\x02\x02\x04^\x03\x02\x02\x02\x06c\x03\x02\x02\x02\bw\x03" + + "\x02\x02\x02\n\xB5\x03\x02\x02\x02\f\xC8\x03\x02\x02\x02\x0E\xCC\x03\x02" + + "\x02\x02\x10\xCE\x03\x02\x02\x02\x12\xDA\x03\x02\x02\x02\x14\xDE\x03\x02" + + "\x02\x02\x16\xE0\x03\x02\x02\x02\x18\xE2\x03\x02\x02\x02\x1A\xEB\x03\x02" + + "\x02\x02\x1C\xFD\x03\x02\x02\x02\x1E\xFF\x03\x02\x02\x02 \u0104\x03\x02" + + "\x02\x02\"\u010B\x03\x02\x02\x02$\u0145\x03\x02\x02\x02&\u014C\x03\x02" + + "\x02\x02(\u0155\x03\x02\x02\x02*\u0161\x03\x02\x02\x02,\u0163\x03\x02" + + "\x02\x02.\u0182\x03\x02\x02\x020\u018C\x03\x02\x02\x022\u01A1\x03\x02" + + "\x02\x024\u01A6\x03\x02\x02\x026\u01AA\x03\x02\x02\x028\u01AC\x03\x02" + + "\x02\x02:\u01B0\x03\x02\x02\x02<\u01B3\x03\x02\x02\x02>\u01E0\x03\x02" + + "\x02\x02@\u01EF\x03\x02\x02\x02B\u01FF\x03\x02\x02\x02D\u0201\x03\x02" + + "\x02\x02F\u0205\x03\x02\x02\x02H\u0215\x03\x02\x02\x02J\u0224\x03\x02" + + "\x02\x02L\u022C\x03\x02\x02\x02N\u023B\x03\x02\x02\x02PR\x05\x04\x03\x02" + + "QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02ST\x03\x02\x02\x02" + "TY\x03\x02\x02\x02US\x03\x02\x02\x02VX\x05\b\x05\x02WV\x03\x02\x02\x02" + "X[\x03\x02\x02\x02YW\x03\x02\x02\x02YZ\x03\x02\x02\x02Z\\\x03\x02\x02" + "\x02[Y\x03\x02\x02\x02\\]\x07\x02\x02\x03]\x03\x03\x02\x02\x02^_\x05\x1A" + - "\x0E\x02_`\x07U\x02\x02`a\x05\x06\x04\x02ab\x05\x10\t\x02b\x05\x03\x02" + - "\x02\x02co\x07\t\x02\x02de\x05\x1A\x0E\x02el\x07U\x02\x02fg\x07\r\x02" + - "\x02gh\x05\x1A\x0E\x02hi\x07U\x02\x02ik\x03\x02\x02\x02jf\x03\x02\x02" + + "\x0E\x02_`\x07V\x02\x02`a\x05\x06\x04\x02ab\x05\x10\t\x02b\x05\x03\x02" + + "\x02\x02co\x07\t\x02\x02de\x05\x1A\x0E\x02el\x07V\x02\x02fg\x07\x0E\x02" + + "\x02gh\x05\x1A\x0E\x02hi\x07V\x02\x02ik\x03\x02\x02\x02jf\x03\x02\x02" + "\x02kn\x03\x02\x02\x02lj\x03\x02\x02\x02lm\x03\x02\x02\x02mp\x03\x02\x02" + "\x02nl\x03\x02\x02\x02od\x03\x02\x02\x02op\x03\x02\x02\x02pq\x03\x02\x02" + "\x02qr\x07\n\x02\x02r\x07\x03\x02\x02\x02sx\x05\n\x06\x02tu\x05\f\x07" + "\x02uv\t\x02\x02\x02vx\x03\x02\x02\x02ws\x03\x02\x02\x02wt\x03\x02\x02" + - "\x02x\t\x03\x02\x02\x02yz\x07\x0F\x02\x02z{\x07\t\x02\x02{|\x05$\x13\x02" + - "|}\x07\n\x02\x02}\x81\x05\x0E\b\x02~\x7F\x07\x11\x02\x02\x7F\x82\x05\x0E" + + "\x02x\t\x03\x02\x02\x02yz\x07\x10\x02\x02z{\x07\t\x02\x02{|\x05$\x13\x02" + + "|}\x07\n\x02\x02}\x81\x05\x0E\b\x02~\x7F\x07\x12\x02\x02\x7F\x82\x05\x0E" + "\b\x02\x80\x82\x06\x06\x02\x02\x81~\x03\x02\x02\x02\x81\x80\x03\x02\x02" + - "\x02\x82\xB6\x03\x02\x02\x02\x83\x84\x07\x12\x02\x02\x84\x85\x07\t\x02" + + "\x02\x82\xB6\x03\x02\x02\x02\x83\x84\x07\x13\x02\x02\x84\x85\x07\t\x02" + "\x02\x85\x86\x05$\x13\x02\x86\x89\x07\n\x02\x02\x87\x8A\x05\x0E\b\x02" + "\x88\x8A\x05\x12\n\x02\x89\x87\x03\x02\x02\x02\x89\x88\x03\x02\x02\x02" + - "\x8A\xB6\x03\x02\x02\x02\x8B\x8C\x07\x14\x02\x02\x8C\x8E\x07\t\x02\x02" + + "\x8A\xB6\x03\x02\x02\x02\x8B\x8C\x07\x15\x02\x02\x8C\x8E\x07\t\x02\x02" + "\x8D\x8F\x05\x14\v\x02\x8E\x8D\x03\x02\x02\x02\x8E\x8F\x03\x02\x02\x02" + - "\x8F\x90\x03\x02\x02\x02\x90\x92\x07\x0E\x02\x02\x91\x93\x05$\x13\x02" + + "\x8F\x90\x03\x02\x02\x02\x90\x92\x07\x0F\x02\x02\x91\x93\x05$\x13\x02" + "\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03\x02\x02\x02" + - "\x94\x96\x07\x0E\x02\x02\x95\x97\x05\x16\f\x02\x96\x95\x03\x02\x02\x02" + + "\x94\x96\x07\x0F\x02\x02\x95\x97\x05\x16\f\x02\x96\x95\x03\x02\x02\x02" + "\x96\x97\x03\x02\x02\x02\x97\x98\x03\x02\x02\x02\x98\x9B\x07\n\x02\x02" + "\x99\x9C\x05\x0E\b\x02\x9A\x9C\x05\x12\n\x02\x9B\x99\x03\x02\x02\x02\x9B" + - "\x9A\x03\x02\x02\x02\x9C\xB6\x03\x02\x02\x02\x9D\x9E\x07\x14\x02\x02\x9E" + - "\x9F\x07\t\x02\x02\x9F\xA0\x05\x1A\x0E\x02\xA0\xA1\x07U\x02\x02\xA1\xA2" + - "\x076\x02\x02\xA2\xA3\x05$\x13\x02\xA3\xA4\x07\n\x02\x02\xA4\xA5\x05\x0E" + - "\b\x02\xA5\xB6\x03\x02\x02\x02\xA6\xA7\x07\x14\x02\x02\xA7\xA8\x07\t\x02" + - "\x02\xA8\xA9\x07U\x02\x02\xA9\xAA\x07\x10\x02\x02\xAA\xAB\x05$\x13\x02" + + "\x9A\x03\x02\x02\x02\x9C\xB6\x03\x02\x02\x02\x9D\x9E\x07\x15\x02\x02\x9E" + + "\x9F\x07\t\x02\x02\x9F\xA0\x05\x1A\x0E\x02\xA0\xA1\x07V\x02\x02\xA1\xA2" + + "\x077\x02\x02\xA2\xA3\x05$\x13\x02\xA3\xA4\x07\n\x02\x02\xA4\xA5\x05\x0E" + + "\b\x02\xA5\xB6\x03\x02\x02\x02\xA6\xA7\x07\x15\x02\x02\xA7\xA8\x07\t\x02" + + "\x02\xA8\xA9\x07V\x02\x02\xA9\xAA\x07\x11\x02\x02\xAA\xAB\x05$\x13\x02" + "\xAB\xAC\x07\n\x02\x02\xAC\xAD\x05\x0E\b\x02\xAD\xB6\x03\x02\x02\x02\xAE" + - "\xAF\x07\x19\x02\x02\xAF\xB1\x05\x10\t\x02\xB0\xB2\x05 \x11\x02\xB1\xB0" + + "\xAF\x07\x1A\x02\x02\xAF\xB1\x05\x10\t\x02\xB0\xB2\x05 \x11\x02\xB1\xB0" + "\x03\x02\x02\x02\xB2\xB3\x03\x02\x02\x02\xB3\xB1\x03\x02\x02\x02\xB3\xB4" + "\x03\x02\x02\x02\xB4\xB6\x03\x02\x02\x02\xB5y\x03\x02\x02\x02\xB5\x83" + "\x03\x02\x02\x02\xB5\x8B\x03\x02\x02\x02\xB5\x9D\x03\x02\x02\x02\xB5\xA6" + "\x03\x02\x02\x02\xB5\xAE\x03\x02\x02\x02\xB6\v\x03\x02\x02\x02\xB7\xB8" + - "\x07\x13\x02\x02\xB8\xB9\x05\x10\t\x02\xB9\xBA\x07\x12\x02\x02\xBA\xBB" + + "\x07\x14\x02\x02\xB8\xB9\x05\x10\t\x02\xB9\xBA\x07\x13\x02\x02\xBA\xBB" + "\x07\t\x02\x02\xBB\xBC\x05$\x13\x02\xBC\xBD\x07\n\x02\x02\xBD\xC9\x03" + - "\x02\x02\x02\xBE\xC9\x05\x18\r\x02\xBF\xC9\x07\x15\x02\x02\xC0\xC9\x07" + - "\x16\x02\x02\xC1\xC3\x07\x17\x02\x02\xC2\xC4\x05$\x13\x02\xC3\xC2\x03" + + "\x02\x02\x02\xBE\xC9\x05\x18\r\x02\xBF\xC9\x07\x16\x02\x02\xC0\xC9\x07" + + "\x17\x02\x02\xC1\xC3\x07\x18\x02\x02\xC2\xC4\x05$\x13\x02\xC3\xC2\x03" + "\x02\x02\x02\xC3\xC4\x03\x02\x02\x02\xC4\xC9\x03\x02\x02\x02\xC5\xC6\x07" + - "\x1B\x02\x02\xC6\xC9\x05$\x13\x02\xC7\xC9\x05$\x13\x02\xC8\xB7\x03\x02" + + "\x1C\x02\x02\xC6\xC9\x05$\x13\x02\xC7\xC9\x05$\x13\x02\xC8\xB7\x03\x02" + "\x02\x02\xC8\xBE\x03\x02\x02\x02\xC8\xBF\x03\x02\x02\x02\xC8\xC0\x03\x02" + "\x02\x02\xC8\xC1\x03\x02\x02\x02\xC8\xC5\x03\x02\x02\x02\xC8\xC7\x03\x02" + "\x02\x02\xC9\r\x03\x02\x02\x02\xCA\xCD\x05\x10\t\x02\xCB\xCD\x05\b\x05" + @@ -3265,25 +3282,25 @@ export class painless_parser extends Parser { "\x02\xD1\xD4\x03\x02\x02\x02\xD2\xD0\x03\x02\x02\x02\xD2\xD3\x03\x02\x02" + "\x02\xD3\xD6\x03\x02\x02\x02\xD4\xD2\x03\x02\x02\x02\xD5\xD7\x05\f\x07" + "\x02\xD6\xD5\x03\x02\x02\x02\xD6\xD7\x03\x02\x02\x02\xD7\xD8\x03\x02\x02" + - "\x02\xD8\xD9\x07\x06\x02\x02\xD9\x11\x03\x02\x02\x02\xDA\xDB\x07\x0E\x02" + + "\x02\xD8\xD9\x07\x06\x02\x02\xD9\x11\x03\x02\x02\x02\xDA\xDB\x07\x0F\x02" + "\x02\xDB\x13\x03\x02\x02\x02\xDC\xDF\x05\x18\r\x02\xDD\xDF\x05$\x13\x02" + "\xDE\xDC\x03\x02\x02\x02\xDE\xDD\x03\x02\x02\x02\xDF\x15\x03\x02\x02\x02" + "\xE0\xE1\x05$\x13\x02\xE1\x17\x03\x02\x02\x02\xE2\xE3\x05\x1A\x0E\x02" + - "\xE3\xE8\x05\x1E\x10\x02\xE4\xE5\x07\r\x02\x02\xE5\xE7\x05\x1E\x10\x02" + + "\xE3\xE8\x05\x1E\x10\x02\xE4\xE5\x07\x0E\x02\x02\xE5\xE7\x05\x1E\x10\x02" + "\xE6\xE4\x03\x02\x02\x02\xE7\xEA\x03\x02\x02\x02\xE8\xE6\x03\x02\x02\x02" + "\xE8\xE9\x03\x02\x02\x02\xE9\x19\x03\x02\x02\x02\xEA\xE8\x03\x02\x02\x02" + "\xEB\xF0\x05\x1C\x0F\x02\xEC\xED\x07\x07\x02\x02\xED\xEF\x07\b\x02\x02" + "\xEE\xEC\x03\x02\x02\x02\xEF\xF2\x03\x02\x02\x02\xF0\xEE\x03\x02\x02\x02" + "\xF0\xF1\x03\x02\x02\x02\xF1\x1B\x03\x02\x02\x02\xF2\xF0\x03\x02\x02\x02" + - "\xF3\xFE\x07T\x02\x02\xF4\xFE\x07S\x02\x02\xF5\xFA\x07U\x02\x02\xF6\xF7" + - "\x07\v\x02\x02\xF7\xF9\x07W\x02\x02\xF8\xF6\x03\x02\x02\x02\xF9\xFC\x03" + + "\xF3\xFE\x07U\x02\x02\xF4\xFE\x07T\x02\x02\xF5\xFA\x07V\x02\x02\xF6\xF7" + + "\x07\f\x02\x02\xF7\xF9\x07X\x02\x02\xF8\xF6\x03\x02\x02\x02\xF9\xFC\x03" + "\x02\x02\x02\xFA\xF8\x03\x02\x02\x02\xFA\xFB\x03\x02\x02\x02\xFB\xFE\x03" + "\x02\x02\x02\xFC\xFA\x03\x02\x02\x02\xFD\xF3\x03\x02\x02\x02\xFD\xF4\x03" + "\x02\x02\x02\xFD\xF5\x03\x02\x02\x02\xFE\x1D\x03\x02\x02\x02\xFF\u0102" + - "\x07U\x02\x02\u0100\u0101\x07>\x02\x02\u0101\u0103\x05$\x13\x02\u0102" + + "\x07V\x02\x02\u0100\u0101\x07?\x02\x02\u0101\u0103\x05$\x13\x02\u0102" + "\u0100\x03\x02\x02\x02\u0102\u0103\x03\x02\x02\x02\u0103\x1F\x03\x02\x02" + - "\x02\u0104\u0105\x07\x1A\x02\x02\u0105\u0106\x07\t\x02\x02\u0106\u0107" + - "\x05\x1C\x0F\x02\u0107\u0108\x07U\x02\x02\u0108\u0109\x07\n\x02\x02\u0109" + + "\x02\u0104\u0105\x07\x1B\x02\x02\u0105\u0106\x07\t\x02\x02\u0106\u0107" + + "\x05\x1C\x0F\x02\u0107\u0108\x07V\x02\x02\u0108\u0109\x07\n\x02\x02\u0109" + "\u010A\x05\x10\t\x02\u010A!\x03\x02\x02\x02\u010B\u010C\b\x12\x01\x02" + "\u010C\u010D\x05&\x14\x02\u010D\u0137\x03\x02\x02\x02\u010E\u010F\f\x0F" + "\x02\x02\u010F\u0110\t\x03\x02\x02\u0110\u0136\x05\"\x12\x10\u0111\u0112" + @@ -3292,14 +3309,14 @@ export class painless_parser extends Parser { "\u0117\u0118\f\f\x02\x02\u0118\u0119\t\x06\x02\x02\u0119\u0136\x05\"\x12" + "\r\u011A\u011B\f\v\x02\x02\u011B\u011C\t\x07\x02\x02\u011C\u0136\x05\"" + "\x12\f\u011D\u011E\f\t\x02\x02\u011E\u011F\t\b\x02\x02\u011F\u0136\x05" + - "\"\x12\n\u0120\u0121\f\b\x02\x02\u0121\u0122\x070\x02\x02\u0122\u0136" + - "\x05\"\x12\t\u0123\u0124\f\x07\x02\x02\u0124\u0125\x071\x02\x02\u0125" + - "\u0136\x05\"\x12\b\u0126\u0127\f\x06\x02\x02\u0127\u0128\x072\x02\x02" + - "\u0128\u0136\x05\"\x12\x07\u0129\u012A\f\x05\x02\x02\u012A\u012B\x073" + + "\"\x12\n\u0120\u0121\f\b\x02\x02\u0121\u0122\x071\x02\x02\u0122\u0136" + + "\x05\"\x12\t\u0123\u0124\f\x07\x02\x02\u0124\u0125\x072\x02\x02\u0125" + + "\u0136\x05\"\x12\b\u0126\u0127\f\x06\x02\x02\u0127\u0128\x073\x02\x02" + + "\u0128\u0136\x05\"\x12\x07\u0129\u012A\f\x05\x02\x02\u012A\u012B\x074" + "\x02\x02\u012B\u0136\x05\"\x12\x06\u012C\u012D\f\x04\x02\x02\u012D\u012E" + - "\x074\x02\x02\u012E\u0136\x05\"\x12\x05\u012F\u0130\f\x03\x02\x02\u0130" + - "\u0131\x077\x02\x02\u0131\u0136\x05\"\x12\x03\u0132\u0133\f\n\x02\x02" + - "\u0133\u0134\x07\x1D\x02\x02\u0134\u0136\x05\x1A\x0E\x02\u0135\u010E\x03" + + "\x075\x02\x02\u012E\u0136\x05\"\x12\x05\u012F\u0130\f\x03\x02\x02\u0130" + + "\u0131\x078\x02\x02\u0131\u0136\x05\"\x12\x03\u0132\u0133\f\n\x02\x02" + + "\u0133\u0134\x07\x1E\x02\x02\u0134\u0136\x05\x1A\x0E\x02\u0135\u010E\x03" + "\x02\x02\x02\u0135\u0111\x03\x02\x02\x02\u0135\u0114\x03\x02\x02\x02\u0135" + "\u0117\x03\x02\x02\x02\u0135\u011A\x03\x02\x02\x02\u0135\u011D\x03\x02" + "\x02\x02\u0135\u0120\x03\x02\x02\x02\u0135\u0123\x03\x02\x02\x02\u0135" + @@ -3307,8 +3324,8 @@ export class painless_parser extends Parser { "\x02\x02\u0135\u012F\x03\x02\x02\x02\u0135\u0132\x03\x02\x02\x02\u0136" + "\u0139\x03\x02\x02\x02\u0137\u0135\x03\x02\x02\x02\u0137\u0138\x03\x02" + "\x02\x02\u0138#\x03\x02\x02\x02\u0139\u0137\x03\x02\x02\x02\u013A\u0146" + - "\x05\"\x12\x02\u013B\u013C\x05\"\x12\x02\u013C\u013D\x075\x02\x02\u013D" + - "\u013E\x05$\x13\x02\u013E\u013F\x076\x02\x02\u013F\u0140\x05$\x13\x02" + + "\x05\"\x12\x02\u013B\u013C\x05\"\x12\x02\u013C\u013D\x076\x02\x02\u013D" + + "\u013E\x05$\x13\x02\u013E\u013F\x077\x02\x02\u013F\u0140\x05$\x13\x02" + "\u0140\u0146\x03\x02\x02\x02\u0141\u0142\x05\"\x12\x02\u0142\u0143\t\t" + "\x02\x02\u0143\u0144\x05$\x13\x02\u0144\u0146\x03\x02\x02\x02\u0145\u013A" + "\x03\x02\x02\x02\u0145\u013B\x03\x02\x02\x02\u0145\u0141\x03\x02\x02\x02" + @@ -3325,14 +3342,14 @@ export class painless_parser extends Parser { "\t\x02\x02\u015D\u015E\x05.\x18\x02\u015E\u015F\x07\n\x02\x02\u015F\u0160" + "\x05(\x15\x02\u0160\u0162\x03\x02\x02\x02\u0161\u0157\x03\x02\x02\x02" + "\u0161\u015C\x03\x02\x02\x02\u0162+\x03\x02\x02\x02\u0163\u0164\t\f\x02" + - "\x02\u0164-\x03\x02\x02\x02\u0165\u0168\x07T\x02\x02\u0166\u0167\x07\x07" + + "\x02\u0164-\x03\x02\x02\x02\u0165\u0168\x07U\x02\x02\u0166\u0167\x07\x07" + "\x02\x02\u0167\u0169\x07\b\x02\x02\u0168\u0166\x03\x02\x02\x02\u0169\u016A" + "\x03\x02\x02\x02\u016A\u0168\x03\x02\x02\x02\u016A\u016B\x03\x02\x02\x02" + - "\u016B\u0183\x03\x02\x02\x02\u016C\u016F\x07S\x02\x02\u016D\u016E\x07" + + "\u016B\u0183\x03\x02\x02\x02\u016C\u016F\x07T\x02\x02\u016D\u016E\x07" + "\x07\x02\x02\u016E\u0170\x07\b\x02\x02\u016F\u016D\x03\x02\x02\x02\u0170" + "\u0171\x03\x02\x02\x02\u0171\u016F\x03\x02\x02\x02\u0171\u0172\x03\x02" + - "\x02\x02\u0172\u0183\x03\x02\x02\x02\u0173\u0178\x07U\x02\x02\u0174\u0175" + - "\x07\v\x02\x02\u0175\u0177\x07W\x02\x02\u0176\u0174\x03\x02\x02\x02\u0177" + + "\x02\x02\u0172\u0183\x03\x02\x02\x02\u0173\u0178\x07V\x02\x02\u0174\u0175" + + "\x07\f\x02\x02\u0175\u0177\x07X\x02\x02\u0176\u0174\x03\x02\x02\x02\u0177" + "\u017A\x03\x02\x02\x02\u0178\u0176\x03\x02\x02\x02\u0178\u0179\x03\x02" + "\x02\x02\u0179\u017F\x03\x02\x02\x02\u017A\u0178\x03\x02\x02\x02\u017B" + "\u017C\x07\x07\x02\x02\u017C\u017E\x07\b\x02\x02\u017D\u017B\x03\x02\x02" + @@ -3345,11 +3362,11 @@ export class painless_parser extends Parser { "\x02\x02\x02\u018A\u0188\x03\x02\x02\x02\u018B\u018D\x05> \x02\u018C\u0184" + "\x03\x02\x02\x02\u018C\u018B\x03\x02\x02\x02\u018D1\x03\x02\x02\x02\u018E" + "\u018F\x07\t\x02\x02\u018F\u0190\x05$\x13\x02\u0190\u0191\x07\n\x02\x02" + - "\u0191\u01A2\x03\x02\x02\x02\u0192\u01A2\t\r\x02\x02\u0193\u01A2\x07P" + - "\x02\x02\u0194\u01A2\x07Q\x02\x02\u0195\u01A2\x07R\x02\x02\u0196\u01A2" + - "\x07N\x02\x02\u0197\u01A2\x07O\x02\x02\u0198\u01A2\x05@!\x02\u0199\u01A2" + - "\x05B\"\x02\u019A\u01A2\x07U\x02\x02\u019B\u019C\x07U\x02\x02\u019C\u01A2" + - "\x05F$\x02\u019D\u019E\x07\x18\x02\x02\u019E\u019F\x05\x1C\x0F\x02\u019F" + + "\u0191\u01A2\x03\x02\x02\x02\u0192\u01A2\t\r\x02\x02\u0193\u01A2\x07Q" + + "\x02\x02\u0194\u01A2\x07R\x02\x02\u0195\u01A2\x07S\x02\x02\u0196\u01A2" + + "\x07O\x02\x02\u0197\u01A2\x07P\x02\x02\u0198\u01A2\x05@!\x02\u0199\u01A2" + + "\x05B\"\x02\u019A\u01A2\x07V\x02\x02\u019B\u019C\t\x0E\x02\x02\u019C\u01A2" + + "\x05F$\x02\u019D\u019E\x07\x19\x02\x02\u019E\u019F\x05\x1C\x0F\x02\u019F" + "\u01A0\x05F$\x02\u01A0\u01A2\x03\x02\x02\x02\u01A1\u018E\x03\x02\x02\x02" + "\u01A1\u0192\x03\x02\x02\x02\u01A1\u0193\x03\x02\x02\x02\u01A1\u0194\x03" + "\x02\x02\x02\u01A1\u0195\x03\x02\x02\x02\u01A1\u0196\x03\x02\x02\x02\u01A1" + @@ -3360,11 +3377,11 @@ export class painless_parser extends Parser { "\x02\x02\u01A6\u01A4\x03\x02\x02\x02\u01A6\u01A5\x03\x02\x02\x02\u01A7" + "5\x03\x02\x02\x02\u01A8\u01AB\x058\x1D\x02\u01A9\u01AB\x05:\x1E\x02\u01AA" + "\u01A8\x03\x02\x02\x02\u01AA\u01A9\x03\x02\x02\x02\u01AB7\x03\x02\x02" + - "\x02\u01AC\u01AD\t\x0E\x02\x02\u01AD\u01AE\x07W\x02\x02\u01AE\u01AF\x05" + - "F$\x02\u01AF9\x03\x02\x02\x02\u01B0\u01B1\t\x0E\x02\x02\u01B1\u01B2\t" + - "\x0F\x02\x02\u01B2;\x03\x02\x02\x02\u01B3\u01B4\x07\x07\x02\x02\u01B4" + + "\x02\u01AC\u01AD\t\x0F\x02\x02\u01AD\u01AE\x07X\x02\x02\u01AE\u01AF\x05" + + "F$\x02\u01AF9\x03\x02\x02\x02\u01B0\u01B1\t\x0F\x02\x02\u01B1\u01B2\t" + + "\x10\x02\x02\u01B2;\x03\x02\x02\x02\u01B3\u01B4\x07\x07\x02\x02\u01B4" + "\u01B5\x05$\x13\x02\u01B5\u01B6\x07\b\x02\x02\u01B6=\x03\x02\x02\x02\u01B7" + - "\u01B8\x07\x18\x02\x02\u01B8\u01BD\x05\x1C\x0F\x02\u01B9\u01BA\x07\x07" + + "\u01B8\x07\x19\x02\x02\u01B8\u01BD\x05\x1C\x0F\x02\u01B9\u01BA\x07\x07" + "\x02\x02\u01BA\u01BB\x05$\x13\x02\u01BB\u01BC\x07\b\x02\x02\u01BC\u01BE" + "\x03\x02\x02\x02\u01BD\u01B9\x03\x02\x02\x02\u01BE\u01BF\x03\x02\x02\x02" + "\u01BF\u01BD\x03\x02\x02\x02\u01BF\u01C0\x03\x02\x02\x02\u01C0\u01C8\x03" + @@ -3372,63 +3389,63 @@ export class painless_parser extends Parser { "\x03\x02\x02\x02\u01C4\u01C7\x03\x02\x02\x02\u01C5\u01C3\x03\x02\x02\x02" + "\u01C5\u01C6\x03\x02\x02\x02\u01C6\u01C9\x03\x02\x02\x02\u01C7\u01C5\x03" + "\x02\x02\x02\u01C8\u01C1\x03\x02\x02\x02\u01C8\u01C9\x03\x02\x02\x02\u01C9" + - "\u01E1\x03\x02\x02\x02\u01CA\u01CB\x07\x18\x02\x02\u01CB\u01CC\x05\x1C" + + "\u01E1\x03\x02\x02\x02\u01CA\u01CB\x07\x19\x02\x02\u01CB\u01CC\x05\x1C" + "\x0F\x02\u01CC\u01CD\x07\x07\x02\x02\u01CD\u01CE\x07\b\x02\x02\u01CE\u01D7" + - "\x07\x05\x02\x02\u01CF\u01D4\x05$\x13\x02\u01D0\u01D1\x07\r\x02\x02\u01D1" + - "\u01D3\x05$\x13\x02\u01D2\u01D0\x03\x02\x02\x02\u01D3\u01D6\x03\x02\x02" + - "\x02\u01D4\u01D2\x03\x02\x02\x02\u01D4\u01D5\x03\x02\x02\x02\u01D5\u01D8" + - "\x03\x02\x02\x02\u01D6\u01D4\x03\x02\x02\x02\u01D7\u01CF\x03\x02\x02\x02" + - "\u01D7\u01D8\x03\x02\x02\x02\u01D8\u01D9\x03\x02\x02\x02\u01D9\u01DD\x07" + - "\x06\x02\x02\u01DA\u01DC\x054\x1B\x02\u01DB\u01DA\x03\x02\x02\x02\u01DC" + - "\u01DF\x03\x02\x02\x02\u01DD\u01DB\x03\x02\x02\x02\u01DD\u01DE\x03\x02" + - "\x02\x02\u01DE\u01E1\x03\x02\x02\x02\u01DF\u01DD\x03\x02\x02\x02\u01E0" + - "\u01B7\x03\x02\x02\x02\u01E0\u01CA\x03\x02\x02\x02\u01E1?\x03\x02\x02" + - "\x02\u01E2\u01E3\x07\x07\x02\x02\u01E3\u01E8\x05$\x13\x02\u01E4\u01E5" + - "\x07\r\x02\x02\u01E5\u01E7\x05$\x13\x02\u01E6\u01E4\x03\x02\x02\x02\u01E7" + - "\u01EA\x03\x02\x02\x02\u01E8\u01E6\x03\x02\x02\x02\u01E8\u01E9\x03\x02" + - "\x02\x02\u01E9\u01EB\x03\x02\x02\x02\u01EA\u01E8\x03\x02\x02\x02\u01EB" + + "\x07\x05\x02\x02\u01CF\u01D4\x05$\x13\x02\u01D0\u01D1\x07\x0E\x02\x02" + + "\u01D1\u01D3\x05$\x13\x02\u01D2\u01D0\x03\x02\x02\x02\u01D3\u01D6\x03" + + "\x02\x02\x02\u01D4\u01D2\x03\x02\x02\x02\u01D4\u01D5\x03\x02\x02\x02\u01D5" + + "\u01D8\x03\x02\x02\x02\u01D6\u01D4\x03\x02\x02\x02\u01D7\u01CF\x03\x02" + + "\x02\x02\u01D7\u01D8\x03\x02\x02\x02\u01D8\u01D9\x03\x02\x02\x02\u01D9" + + "\u01DD\x07\x06\x02\x02\u01DA\u01DC\x054\x1B\x02\u01DB\u01DA\x03\x02\x02" + + "\x02\u01DC\u01DF\x03\x02\x02\x02\u01DD\u01DB\x03\x02\x02\x02\u01DD\u01DE" + + "\x03\x02\x02\x02\u01DE\u01E1\x03\x02\x02\x02\u01DF\u01DD\x03\x02\x02\x02" + + "\u01E0\u01B7\x03\x02\x02\x02\u01E0\u01CA\x03\x02\x02\x02\u01E1?\x03\x02" + + "\x02\x02\u01E2\u01E3\x07\x07\x02\x02\u01E3\u01E8\x05$\x13\x02\u01E4\u01E5" + + "\x07\x0E\x02\x02\u01E5\u01E7\x05$\x13\x02\u01E6\u01E4\x03\x02\x02\x02" + + "\u01E7\u01EA\x03\x02\x02\x02\u01E8\u01E6\x03\x02\x02\x02\u01E8\u01E9\x03" + + "\x02\x02\x02\u01E9\u01EB\x03\x02\x02\x02\u01EA\u01E8\x03\x02\x02\x02\u01EB" + "\u01EC\x07\b\x02\x02\u01EC\u01F0\x03\x02\x02\x02\u01ED\u01EE\x07\x07\x02" + "\x02\u01EE\u01F0\x07\b\x02\x02\u01EF\u01E2\x03\x02\x02\x02\u01EF\u01ED" + "\x03\x02\x02\x02\u01F0A\x03\x02\x02\x02\u01F1\u01F2\x07\x07\x02\x02\u01F2" + - "\u01F7\x05D#\x02\u01F3\u01F4\x07\r\x02\x02\u01F4\u01F6\x05D#\x02\u01F5" + + "\u01F7\x05D#\x02\u01F3\u01F4\x07\x0E\x02\x02\u01F4\u01F6\x05D#\x02\u01F5" + "\u01F3\x03\x02\x02\x02\u01F6\u01F9\x03\x02\x02\x02\u01F7\u01F5\x03\x02" + "\x02\x02\u01F7\u01F8\x03\x02\x02\x02\u01F8\u01FA\x03\x02\x02\x02\u01F9" + "\u01F7\x03\x02\x02\x02\u01FA\u01FB\x07\b\x02\x02\u01FB\u0200\x03\x02\x02" + - "\x02\u01FC\u01FD\x07\x07\x02\x02\u01FD\u01FE\x076\x02\x02\u01FE\u0200" + + "\x02\u01FC\u01FD\x07\x07\x02\x02\u01FD\u01FE\x077\x02\x02\u01FE\u0200" + "\x07\b\x02\x02\u01FF\u01F1\x03\x02\x02\x02\u01FF\u01FC\x03\x02\x02\x02" + - "\u0200C\x03\x02\x02\x02\u0201\u0202\x05$\x13\x02\u0202\u0203\x076\x02" + + "\u0200C\x03\x02\x02\x02\u0201\u0202\x05$\x13\x02\u0202\u0203\x077\x02" + "\x02\u0203\u0204\x05$\x13\x02\u0204E\x03\x02\x02\x02\u0205\u020E\x07\t" + - "\x02\x02\u0206\u020B\x05H%\x02\u0207\u0208\x07\r\x02\x02\u0208\u020A\x05" + - "H%\x02\u0209\u0207\x03\x02\x02\x02\u020A\u020D\x03\x02\x02\x02\u020B\u0209" + - "\x03\x02\x02\x02\u020B\u020C\x03\x02\x02\x02\u020C\u020F\x03\x02\x02\x02" + - "\u020D\u020B\x03\x02\x02\x02\u020E\u0206\x03\x02\x02\x02\u020E\u020F\x03" + - "\x02\x02\x02\u020F\u0210\x03\x02\x02\x02\u0210\u0211\x07\n\x02\x02\u0211" + - "G\x03\x02\x02\x02\u0212\u0216\x05$\x13\x02\u0213\u0216\x05J&\x02\u0214" + - "\u0216\x05N(\x02\u0215\u0212\x03\x02\x02\x02\u0215\u0213\x03\x02\x02\x02" + - "\u0215\u0214\x03\x02\x02\x02\u0216I\x03\x02\x02\x02\u0217\u0225\x05L\'" + - "\x02\u0218\u0221\x07\t\x02\x02\u0219\u021E\x05L\'\x02\u021A\u021B\x07" + - "\r\x02\x02\u021B\u021D\x05L\'\x02\u021C\u021A\x03\x02\x02\x02\u021D\u0220" + - "\x03\x02\x02\x02\u021E\u021C\x03\x02\x02\x02\u021E\u021F\x03\x02\x02\x02" + - "\u021F\u0222\x03\x02\x02\x02\u0220\u021E\x03\x02\x02\x02\u0221\u0219\x03" + - "\x02\x02\x02\u0221\u0222\x03\x02\x02\x02\u0222\u0223\x03\x02\x02\x02\u0223" + - "\u0225\x07\n\x02\x02\u0224\u0217\x03\x02\x02\x02\u0224\u0218\x03\x02\x02" + - "\x02\u0225\u0226"; + "\x02\x02\u0206\u020B\x05H%\x02\u0207\u0208\x07\x0E\x02\x02\u0208\u020A" + + "\x05H%\x02\u0209\u0207\x03\x02\x02\x02\u020A\u020D\x03\x02\x02\x02\u020B" + + "\u0209\x03\x02\x02\x02\u020B\u020C\x03\x02\x02\x02\u020C\u020F\x03\x02" + + "\x02\x02\u020D\u020B\x03\x02\x02\x02\u020E\u0206\x03\x02\x02\x02\u020E" + + "\u020F\x03\x02\x02\x02\u020F\u0210\x03\x02\x02\x02\u0210\u0211\x07\n\x02" + + "\x02\u0211G\x03\x02\x02\x02\u0212\u0216\x05$\x13\x02\u0213\u0216\x05J" + + "&\x02\u0214\u0216\x05N(\x02\u0215\u0212\x03\x02\x02\x02\u0215\u0213\x03" + + "\x02\x02\x02\u0215\u0214\x03\x02\x02\x02\u0216I\x03\x02\x02\x02\u0217" + + "\u0225\x05L\'\x02\u0218\u0221\x07\t\x02\x02\u0219\u021E\x05L\'\x02\u021A" + + "\u021B\x07\x0E\x02\x02\u021B\u021D\x05L\'\x02\u021C\u021A\x03\x02\x02" + + "\x02\u021D\u0220\x03\x02\x02\x02\u021E\u021C\x03\x02\x02\x02\u021E\u021F" + + "\x03\x02\x02\x02\u021F\u0222\x03\x02\x02\x02\u0220\u021E\x03\x02\x02\x02" + + "\u0221\u0219\x03\x02\x02\x02\u0221\u0222\x03\x02\x02\x02\u0222\u0223\x03" + + "\x02\x02\x02\u0223\u0225\x07\n\x02\x02\u0224\u0217\x03\x02\x02\x02\u0224" + + "\u0218"; private static readonly _serializedATNSegment1: string = - "\x03\x02\x02\x02\u0226\u0229\x079\x02\x02\u0227\u022A\x05\x10\t\x02\u0228" + - "\u022A\x05$\x13\x02\u0229\u0227\x03\x02\x02\x02\u0229\u0228\x03\x02\x02" + - "\x02\u022AK\x03\x02\x02\x02\u022B\u022D\x05\x1A\x0E\x02\u022C\u022B\x03" + - "\x02\x02\x02\u022C\u022D\x03\x02\x02\x02\u022D\u022E\x03\x02\x02\x02\u022E" + - "\u022F\x07U\x02\x02\u022FM\x03\x02\x02\x02\u0230\u0231\x05\x1A\x0E\x02" + - "\u0231\u0232\x078\x02\x02\u0232\u0233\x07U\x02\x02\u0233\u023C\x03\x02" + - "\x02\x02\u0234\u0235\x05\x1A\x0E\x02\u0235\u0236\x078\x02\x02\u0236\u0237" + - "\x07\x18\x02\x02\u0237\u023C\x03\x02\x02\x02\u0238\u0239\x07\x1C\x02\x02" + - "\u0239\u023A\x078\x02\x02\u023A\u023C\x07U\x02\x02\u023B\u0230\x03\x02" + - "\x02\x02\u023B\u0234\x03\x02\x02\x02\u023B\u0238\x03\x02\x02\x02\u023C" + - "O\x03\x02\x02\x02>SYlow\x81\x89\x8E\x92\x96\x9B\xB3\xB5\xC3\xC8\xCC\xD2" + - "\xD6\xDE\xE8\xF0\xFA\xFD\u0102\u0135\u0137\u0145\u014C\u0155\u0161\u016A" + - "\u0171\u0178\u017F\u0182\u0188\u018C\u01A1\u01A6\u01AA\u01BF\u01C5\u01C8" + - "\u01D4\u01D7\u01DD\u01E0\u01E8\u01EF\u01F7\u01FF\u020B\u020E\u0215\u021E" + - "\u0221\u0224\u0229\u022C\u023B"; + "\x03\x02\x02\x02\u0225\u0226\x03\x02\x02\x02\u0226\u0229\x07:\x02\x02" + + "\u0227\u022A\x05\x10\t\x02\u0228\u022A\x05$\x13\x02\u0229\u0227\x03\x02" + + "\x02\x02\u0229\u0228\x03\x02\x02\x02\u022AK\x03\x02\x02\x02\u022B\u022D" + + "\x05\x1A\x0E\x02\u022C\u022B\x03\x02\x02\x02\u022C\u022D\x03\x02\x02\x02" + + "\u022D\u022E\x03\x02\x02\x02\u022E\u022F\x07V\x02\x02\u022FM\x03\x02\x02" + + "\x02\u0230\u0231\x05\x1A\x0E\x02\u0231\u0232\x079\x02\x02\u0232\u0233" + + "\x07V\x02\x02\u0233\u023C\x03\x02\x02\x02\u0234\u0235\x05\x1A\x0E\x02" + + "\u0235\u0236\x079\x02\x02\u0236\u0237\x07\x19\x02\x02\u0237\u023C\x03" + + "\x02\x02\x02\u0238\u0239\x07\x1D\x02\x02\u0239\u023A\x079\x02\x02\u023A" + + "\u023C\x07V\x02\x02\u023B\u0230\x03\x02\x02\x02\u023B\u0234\x03\x02\x02" + + "\x02\u023B\u0238\x03\x02\x02\x02\u023CO\x03\x02\x02\x02>SYlow\x81\x89" + + "\x8E\x92\x96\x9B\xB3\xB5\xC3\xC8\xCC\xD2\xD6\xDE\xE8\xF0\xFA\xFD\u0102" + + "\u0135\u0137\u0145\u014C\u0155\u0161\u016A\u0171\u0178\u017F\u0182\u0188" + + "\u018C\u01A1\u01A6\u01AA\u01BF\u01C5\u01C8\u01D4\u01D7\u01DD\u01E0\u01E8" + + "\u01EF\u01F7\u01FF\u020B\u020E\u0215\u021E\u0221\u0224\u0229\u022C\u023B"; public static readonly _serializedATN: string = Utils.join( [ painless_parser._serializedATNSegment0, @@ -5184,10 +5201,11 @@ export class VariableContext extends PrimaryContext { } } export class CalllocalContext extends PrimaryContext { - public ID(): TerminalNode { return this.getToken(painless_parser.ID, 0); } public arguments(): ArgumentsContext { return this.getRuleContext(0, ArgumentsContext); } + public ID(): TerminalNode | undefined { return this.tryGetToken(painless_parser.ID, 0); } + public DOLLAR(): TerminalNode | undefined { return this.tryGetToken(painless_parser.DOLLAR, 0); } constructor(ctx: PrimaryContext) { super(ctx.parent, ctx.invokingState); this.copyFrom(ctx); From 888d144802a573d6db25ed70db743de2d239abaf Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Thu, 17 Feb 2022 07:18:52 -0800 Subject: [PATCH 061/104] [DOCS] Updates Discover docs for 8.1 (#125706) * [DOCS] Updates Discover docs for 8.1 * [DOCS] Updates screenshots * Update docs/user/discover.asciidoc Co-authored-by: Matthias Wilhelm * [DOCS] Addresses review comments * [DOCS] Minor editors Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Matthias Wilhelm --- docs/concepts/data-views.asciidoc | 8 ++--- docs/discover/document-explorer.asciidoc | 30 +++++++++++++++--- docs/discover/field-statistics.asciidoc | 6 ++-- .../images/add-field-to-data-view.png | Bin 49973 -> 71873 bytes docs/discover/images/customer.png | Bin 209284 -> 212809 bytes .../discover-context-filters-inactive.png | Bin 19015 -> 0 bytes docs/discover/images/discover-context.png | Bin 209683 -> 252597 bytes .../images/discover-from-visualize.png | Bin 125415 -> 130741 bytes .../images/discover-search-for-relevance.png | Bin 221184 -> 219355 bytes docs/discover/images/discover-visualize.png | Bin 112706 -> 97513 bytes docs/discover/images/discover.png | Bin 370808 -> 398232 bytes .../images/document-explorer-expand.png | Bin 340078 -> 325423 bytes .../images/document-explorer-row-height.png | Bin 0 -> 29402 bytes docs/discover/images/document-explorer.png | Bin 249466 -> 261127 bytes .../images/document-table-expanded.png | Bin 196471 -> 166076 bytes docs/discover/images/document-table.png | Bin 188424 -> 197694 bytes docs/discover/images/hello-field.png | Bin 218057 -> 239302 bytes docs/discover/images/row-height-icon.png | Bin 0 -> 3108 bytes docs/discover/save-search.asciidoc | 4 +-- docs/discover/view-document.asciidoc | 9 ++---- docs/user/discover.asciidoc | 25 +++++++++------ 21 files changed, 50 insertions(+), 32 deletions(-) delete mode 100644 docs/discover/images/discover-context-filters-inactive.png create mode 100644 docs/discover/images/document-explorer-row-height.png create mode 100644 docs/discover/images/row-height-icon.png diff --git a/docs/concepts/data-views.asciidoc b/docs/concepts/data-views.asciidoc index 98bbba5392b15..807b829c7481a 100644 --- a/docs/concepts/data-views.asciidoc +++ b/docs/concepts/data-views.asciidoc @@ -32,16 +32,16 @@ uploaded a file, or added sample data, you get a data view for free, and can start exploring your data. If you loaded your own data, follow these steps to create a data view. -. Open the main menu, then click to *Stack Management > Data Views*. +. Open the main menu, then click *Stack Management > Data Views*. . Click *Create data view*. -[role="screenshot"] -image:management/index-patterns/images/create-data-view.png["Create data view"] - . Start typing in the *name* field, and {kib} looks for the names of indices, data streams, and aliases that match your input. + +[role="screenshot"] +image:management/index-patterns/images/create-data-view.png["Create data view"] ++ ** To match multiple sources, use a wildcard (*). For example, `filebeat-*` matches `filebeat-apache-a`, `filebeat-apache-b`, and so on. + diff --git a/docs/discover/document-explorer.asciidoc b/docs/discover/document-explorer.asciidoc index 8d334b14b1387..99447a2478b3a 100644 --- a/docs/discover/document-explorer.asciidoc +++ b/docs/discover/document-explorer.asciidoc @@ -31,6 +31,18 @@ To resize a column, drag the right edge of the column header until the column is Column widths are stored with a saved search. When you visualize saved searches on dashboards, the saved search appears the same as in **Discover**. +[float] +[[document-explorer-row-height]] +=== Adjust row height + +To set the row height to 1 or more lines, or automatically +adjust the height to fit the contents, click the row height icon +image:images/row-height-icon.png[icon to open the Row height pop-up]. + +[role="screenshot"] +image::images/document-explorer-row-height.png[Row height settings for Document Explroer, width="75%"] + + [float] [[document-explorer-sort-data]] === Sort data @@ -43,7 +55,7 @@ The default sort is based on the time field, from new to old. [role="screenshot"] image::images/document-explorer-sort-data.png[Pop-up in Document Explorer for sorting columns, width="75%"] -. To add more fields to the sort, expand the dropdown menu. +. To add more fields to the sort, select from the dropdown menu. + By default, columns are sorted in the order they are added. For example, to sort by `order_date` then `geo.country_iso_code`, make sure `order_date` appears first. @@ -77,14 +89,22 @@ the documents that occurred before and after it. image:images/expand-icon-2.png[double arrow icon to open a flyout with the document details]. + [role="screenshot"] -image::images/document-explorer-expand.png[Multi field sort in Document Explorer] +image::images/document-explorer-expand.png[Expanded view in Document Explorer] -. Scan through the fields and their values. If you find a field of interest, +. Scan through the fields and their values, or search for a field by name. + +. When you find a field of interest, click -image:images/actions-icon.png[three dots icon in table column] in the *Actions* column for filters and other controls. -. To view documents that occurred before or after the event you are looking at, click <>. +image:images/actions-icon.png[three dots icon in table column] in the *Actions* column +to: +.. Filter the view of the data +.. Toggle the field in or out the document table +.. Pin the field so it stays at the top + . For direct access to a particular document, click <>. +. To view documents that occurred before or after the event you are looking at, click <>. + [float] [[document-explorer-full-screen]] === View documents in fullscreen diff --git a/docs/discover/field-statistics.asciidoc b/docs/discover/field-statistics.asciidoc index f20b5488ec003..750b25c714aa3 100644 --- a/docs/discover/field-statistics.asciidoc +++ b/docs/discover/field-statistics.asciidoc @@ -14,11 +14,9 @@ for the data and its cardinality? This example explores the fields in the <>, or you can use your own data. -. Open the main menu, click *Stack Managment > Advanced Settings*, search for *Show field statistics*, -and turn on the setting. +. Open the main menu, and click *Discover*. -. Open the main menu, click *Discover*, expand the {data-source} dropdown, -and select *kibana_sample_data_logs*. +. Expand the {data-source} dropdown, and select *kibana_sample_data_logs*. . If you don’t see any results, expand the time range, for example, to *Last 7 days*. diff --git a/docs/discover/images/add-field-to-data-view.png b/docs/discover/images/add-field-to-data-view.png index 6e30ee0116c86c1a2ef5a5ddebf2f96409514368..e4352e814fa0be51469682b933671b7be5db52da 100644 GIT binary patch literal 71873 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

m-KbVFt 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

g3v!dtKsy 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 NSxLn=C9jPF{~r#23z7f; literal 209284 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

fR=3Ywa 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 diff --git a/docs/discover/images/discover-context.png b/docs/discover/images/discover-context.png index f73cba203f8f127ebf13784c715a0a20a667625b..770c5fb921a5d3ce854946339fa357769fd5608d 100644 GIT binary patch literal 252597 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 Jx-r);@QWYxv1=@M0-XqjYOBT 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 x} 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%0ARpSI*+`q^}6?-2<$9%nu#xa@oAEW`e7p&UUP%- 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≪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%0DbqEc=(1Ihm+LZ4+VPTNY>`B#txb{ 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