From 7849d9ebb3073c8a7c135c08142a4a8df61f8f2c Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Tue, 12 Apr 2022 12:39:45 +0200 Subject: [PATCH 01/15] Hide welcome page privacy statement on cloud instances (#129198) * Add new hidePrivacyStatement flag to Telemetry * Remove hidePrivacyStatement from asciidocs --- .../resources/base/bin/kibana-docker | 1 + src/plugins/telemetry/public/plugin.test.ts | 60 +++++++++++++++++++ src/plugins/telemetry/public/plugin.ts | 4 +- .../public/services/telemetry_service.test.ts | 13 ++++ .../public/services/telemetry_service.ts | 4 +- src/plugins/telemetry/server/config/config.ts | 2 + .../test_suites/core_plugins/rendering.ts | 1 + 7 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/plugins/telemetry/public/plugin.test.ts diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index 191f53208df72..7ce7459d6eefd 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -170,6 +170,7 @@ kibana_vars=( status.v6ApiFormat telemetry.allowChangingOptInStatus telemetry.enabled + telemetry.hidePrivacyStatement telemetry.optIn telemetry.sendUsageTo telemetry.sendUsageFrom diff --git a/src/plugins/telemetry/public/plugin.test.ts b/src/plugins/telemetry/public/plugin.test.ts new file mode 100644 index 0000000000000..4473e41572fef --- /dev/null +++ b/src/plugins/telemetry/public/plugin.test.ts @@ -0,0 +1,60 @@ +/* + * 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 { TelemetryPlugin } from './plugin'; +import { coreMock } from '../../../core/public/mocks'; +import { homePluginMock } from '../../home/public/mocks'; +import { screenshotModePluginMock } from '../../screenshot_mode/public/mocks'; +import { HomePublicPluginSetup } from '../../home/public'; +import { ScreenshotModePluginSetup } from '../../screenshot_mode/public'; + +let screenshotMode: ScreenshotModePluginSetup; +let home: HomePublicPluginSetup; + +describe('TelemetryPlugin', () => { + beforeEach(() => { + screenshotMode = screenshotModePluginMock.createSetupContract(); + home = homePluginMock.createSetupContract(); + }); + + describe('setup', () => { + describe('when home is provided', () => { + describe('and hidePrivacyStatement is false (default)', () => { + it('registers the telemetry notice renderer and onRendered handlers', () => { + const initializerContext = coreMock.createPluginInitializerContext(); + + new TelemetryPlugin(initializerContext).setup(coreMock.createSetup(), { + screenshotMode, + home, + }); + + expect(home.welcomeScreen.registerTelemetryNoticeRenderer).toHaveBeenCalledWith( + expect.any(Function) + ); + expect(home.welcomeScreen.registerOnRendered).toHaveBeenCalledWith(expect.any(Function)); + }); + }); + + describe('and hidePrivacyStatement is true', () => { + it('does not register the telemetry notice renderer and onRendered handlers', () => { + const initializerContext = coreMock.createPluginInitializerContext({ + hidePrivacyStatement: true, + }); + + new TelemetryPlugin(initializerContext).setup(coreMock.createSetup(), { + screenshotMode, + home, + }); + + expect(home.welcomeScreen.registerTelemetryNoticeRenderer).not.toBeCalled(); + expect(home.welcomeScreen.registerOnRendered).not.toBeCalled(); + }); + }); + }); + }); +}); diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index a758715e62ba8..b227a0b751e03 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -109,6 +109,8 @@ export interface TelemetryPluginConfig { telemetryNotifyUserAboutOptInDefault?: boolean; /** Does the user have enough privileges to change the settings? **/ userCanChangeSettings?: boolean; + /** Should we hide the privacy statement notice? Useful on some environments, e.g. Cloud */ + hidePrivacyStatement?: boolean; } function getTelemetryConstants(docLinks: DocLinksStart): TelemetryConstants { @@ -155,7 +157,7 @@ export class TelemetryPlugin implements Plugin { if (this.telemetryService?.userCanChangeSettings) { this.telemetryNotifications?.setOptedInNoticeSeen(); diff --git a/src/plugins/telemetry/public/services/telemetry_service.test.ts b/src/plugins/telemetry/public/services/telemetry_service.test.ts index 778dd2fbfe0b0..03564f5b6f632 100644 --- a/src/plugins/telemetry/public/services/telemetry_service.test.ts +++ b/src/plugins/telemetry/public/services/telemetry_service.test.ts @@ -219,6 +219,19 @@ describe('TelemetryService', () => { }); describe('getUserShouldSeeOptInNotice', () => { + it('should return false if the telemetry notice is hidden by config', () => { + const telemetryService = mockTelemetryService({ + config: { + userCanChangeSettings: true, + telemetryNotifyUserAboutOptInDefault: true, + hidePrivacyStatement: true, + }, + }); + expect(telemetryService.config.userCanChangeSettings).toBe(true); + expect(telemetryService.userCanChangeSettings).toBe(true); + expect(telemetryService.getUserShouldSeeOptInNotice()).toBe(false); + }); + it('returns whether the user can update the telemetry config (has SavedObjects access)', () => { const telemetryService = mockTelemetryService({ config: { userCanChangeSettings: undefined }, diff --git a/src/plugins/telemetry/public/services/telemetry_service.ts b/src/plugins/telemetry/public/services/telemetry_service.ts index 55dc623a8ccf8..7499a403bcd95 100644 --- a/src/plugins/telemetry/public/services/telemetry_service.ts +++ b/src/plugins/telemetry/public/services/telemetry_service.ts @@ -113,7 +113,9 @@ export class TelemetryService { */ public getUserShouldSeeOptInNotice(): boolean { return ( - (this.config.telemetryNotifyUserAboutOptInDefault && this.config.userCanChangeSettings) ?? + (!this.config.hidePrivacyStatement && + this.config.telemetryNotifyUserAboutOptInDefault && + this.config.userCanChangeSettings) ?? false ); } diff --git a/src/plugins/telemetry/server/config/config.ts b/src/plugins/telemetry/server/config/config.ts index 166598371fe36..020a01f3b41b8 100644 --- a/src/plugins/telemetry/server/config/config.ts +++ b/src/plugins/telemetry/server/config/config.ts @@ -18,6 +18,7 @@ const clusterEnvSchema: [Type<'prod'>, Type<'staging'>] = [ const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), allowChangingOptInStatus: schema.boolean({ defaultValue: true }), + hidePrivacyStatement: schema.boolean({ defaultValue: false }), optIn: schema.conditional( schema.siblingRef('allowChangingOptInStatus'), schema.literal(false), @@ -50,5 +51,6 @@ export const config: PluginConfigDescriptor = { optIn: true, sendUsageFrom: true, sendUsageTo: true, + hidePrivacyStatement: true, }, }; diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index c18e38cc1a4d6..d7789b5e62a3b 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -129,6 +129,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'telemetry.allowChangingOptInStatus (boolean)', 'telemetry.banner (boolean)', 'telemetry.enabled (boolean)', + 'telemetry.hidePrivacyStatement (boolean)', 'telemetry.optIn (any)', 'telemetry.sendUsageFrom (alternatives)', 'telemetry.sendUsageTo (any)', From 623070bbde6bccab9e07b00579f4fd485e716701 Mon Sep 17 00:00:00 2001 From: mgiota Date: Tue, 12 Apr 2022 12:46:20 +0200 Subject: [PATCH 02/15] Codeowners observability change (#129980) * remove observability-ui from Observability Shared * observability rules page owned by actionable observability --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b846bc0801870..a06ddaf49822f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -88,7 +88,6 @@ ### Observability Plugins # Observability Shared -/x-pack/plugins/observability/ @elastic/observability-ui /x-pack/plugins/observability/public/components/shared/date_picker/ @elastic/uptime # Unified Observability @@ -103,6 +102,7 @@ /x-pack/plugins/observability/public/rules @elastic/actionable-observability /x-pack/plugins/observability/public/pages/alerts @elastic/actionable-observability /x-pack/plugins/observability/public/pages/cases @elastic/actionable-observability +/x-pack/plugins/observability/public/pages/rules @elastic/actionable-observability # Infra Monitoring /x-pack/plugins/infra/ @elastic/infra-monitoring-ui From a8977474a7c75e72c3aa0f66bccc6ab95fb2b7eb Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Tue, 12 Apr 2022 13:06:27 +0200 Subject: [PATCH 03/15] Deprecate outdated detection rules Bulk APIs (#129448) --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + packages/kbn-doc-links/src/types.ts | 1 + .../security_solution/common/constants.ts | 6 +++ .../routes/__mocks__/request_responses.ts | 17 +++--- .../rules/create_rules_bulk_route.test.ts | 16 +++--- .../routes/rules/create_rules_bulk_route.ts | 25 +++++++-- .../rules/delete_rules_bulk_route.test.ts | 12 +++-- .../routes/rules/delete_rules_bulk_route.ts | 26 ++++++--- .../rules/patch_rules_bulk_route.test.ts | 23 ++++---- .../routes/rules/patch_rules_bulk_route.ts | 25 +++++++-- .../rules/update_rules_bulk_route.test.ts | 18 ++++--- .../routes/rules/update_rules_bulk_route.ts | 25 +++++++-- .../routes/rules/utils/deprecation.ts | 42 +++++++++++++++ .../security_solution/server/routes/index.ts | 8 +-- .../basic/tests/create_rules_bulk.ts | 12 ++--- .../basic/tests/delete_rules_bulk.ts | 26 ++++----- .../basic/tests/patch_rules_bulk.ts | 28 +++++----- .../basic/tests/update_rules_bulk.ts | 29 +++++----- .../tests/create_rules_bulk.ts | 32 ++++++++--- .../tests/delete_rules_bulk.ts | 48 +++++++++++------ .../tests/patch_rules_bulk.ts | 50 +++++++++++------ .../tests/update_rules_bulk.ts | 54 +++++++++++++------ .../detection_engine_api_integration/utils.ts | 14 ++--- 23 files changed, 367 insertions(+), 171 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/deprecation.ts diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 690765f3d0c4d..c52407a864c31 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -328,6 +328,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { detectionsReq: `${SECURITY_SOLUTION_DOCS}detections-permissions-section.html`, networkMap: `${SECURITY_SOLUTION_DOCS}conf-map-ui.html`, troubleshootGaps: `${SECURITY_SOLUTION_DOCS}alerts-ui-monitor.html#troubleshoot-gaps`, + ruleApiOverview: `${SECURITY_SOLUTION_DOCS}rule-api-overview.html`, }, securitySolution: { trustedApps: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/trusted-apps-ov.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 5e85d01c22ce2..f017c2ec4be00 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -233,6 +233,7 @@ export interface DocLinks { readonly detectionsReq: string; readonly networkMap: string; readonly troubleshootGaps: string; + readonly ruleApiOverview: string; }; readonly securitySolution: { readonly trustedApps: string; diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 3b820b16ef8a4..74f9bff078b89 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -235,6 +235,12 @@ export const DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL = export const DETECTION_ENGINE_RULES_BULK_ACTION = `${DETECTION_ENGINE_RULES_URL}/_bulk_action` as const; export const DETECTION_ENGINE_RULES_PREVIEW = `${DETECTION_ENGINE_RULES_URL}/preview` as const; +export const DETECTION_ENGINE_RULES_BULK_DELETE = + `${DETECTION_ENGINE_RULES_URL}/_bulk_delete` as const; +export const DETECTION_ENGINE_RULES_BULK_CREATE = + `${DETECTION_ENGINE_RULES_URL}/_bulk_create` as const; +export const DETECTION_ENGINE_RULES_BULK_UPDATE = + `${DETECTION_ENGINE_RULES_URL}/_bulk_update` as const; /** * Internal detection engine routes diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 94c4de459a2ea..e38df7657f512 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -24,6 +24,9 @@ import { DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL, DETECTION_ENGINE_RULES_BULK_ACTION, DETECTION_ENGINE_RULE_EXECUTION_EVENTS_URL, + DETECTION_ENGINE_RULES_BULK_UPDATE, + DETECTION_ENGINE_RULES_BULK_DELETE, + DETECTION_ENGINE_RULES_BULK_CREATE, } from '../../../../../common/constants'; import { GetAggregateRuleExecutionEventsResponse } from '../../../../../common/detection_engine/schemas/response'; import { RuleAlertType, HapiReadableStream } from '../../rules/types'; @@ -110,21 +113,21 @@ export const getFindRequest = () => export const getReadBulkRequest = () => requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, body: [getCreateRulesSchemaMock()], }); export const getUpdateBulkRequest = () => requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [getCreateRulesSchemaMock()], }); export const getPatchBulkRequest = () => requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [getCreateRulesSchemaMock()], }); @@ -145,28 +148,28 @@ export const getBulkActionEditRequest = () => export const getDeleteBulkRequest = () => requestMock.create({ method: 'delete', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, body: [{ rule_id: 'rule-1' }], }); export const getDeleteBulkRequestById = () => requestMock.create({ method: 'delete', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, body: [{ id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd' }], }); export const getDeleteAsPostBulkRequestById = () => requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, body: [{ id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd' }], }); export const getDeleteAsPostBulkRequest = () => requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, body: [{ rule_id: 'rule-1' }], }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index 68a3ec0733b60..1d63a977e2480 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { DETECTION_ENGINE_RULES_BULK_CREATE } from '../../../../../common/constants'; import { mlServicesMock, mlAuthzMock as mockMlAuthzFactory } from '../../../machine_learning/mocks'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { @@ -23,6 +23,7 @@ import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { loggingSystemMock } from '../../../../../../../../src/core/server/mocks'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -38,6 +39,7 @@ describe.each([ server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); + const logger = loggingSystemMock.createLogger(); clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); // no existing rules clients.rulesClient.create.mockResolvedValue( @@ -47,7 +49,7 @@ describe.each([ context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise(getBasicEmptySearchResponse()) ); - createRulesBulkRoute(server.router, ml, isRuleRegistryEnabled); + createRulesBulkRoute(server.router, ml, isRuleRegistryEnabled, logger); }); describe('status codes', () => { @@ -137,7 +139,7 @@ describe.each([ test('returns an error object if duplicate rule_ids found in request payload', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, body: [getCreateRulesSchemaMock(), getCreateRulesSchemaMock()], }); const response = await server.inject(request, context); @@ -158,7 +160,7 @@ describe.each([ test('allows rule type of query', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, body: [{ ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -169,7 +171,7 @@ describe.each([ test('allows rule type of query and custom from and interval', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, body: [{ from: 'now-7m', interval: '5m', ...getCreateRulesSchemaMock() }], }); const result = server.validate(request); @@ -180,7 +182,7 @@ describe.each([ test('disallows unknown rule type', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, body: [{ ...getCreateRulesSchemaMock(), type: 'unexpected_type' }], }); const result = server.validate(request); @@ -191,7 +193,7 @@ describe.each([ test('disallows invalid "from" param on rule', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, body: [ { from: 'now-3755555555555555.67s', 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 74f777b29ca01..8a350e7e12f46 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 @@ -12,7 +12,7 @@ import { createRulesBulkSchema } from '../../../../../common/detection_engine/sc import { rulesBulkSchema } from '../../../../../common/detection_engine/schemas/response/rules_bulk_schema'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { - DETECTION_ENGINE_RULES_URL, + DETECTION_ENGINE_RULES_BULK_CREATE, NOTIFICATION_THROTTLE_NO_ACTIONS, } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; @@ -25,15 +25,21 @@ import { buildRouteValidation } from '../../../../utils/build_validation/route_v import { transformBulkError, createBulkErrorObject, buildSiemResponse } from '../utils'; import { convertCreateAPIToInternalSchema } from '../../schemas/rule_converters'; +import { getDeprecatedBulkEndpointHeader, logDeprecatedBulkEndpoint } from './utils/deprecation'; +import { Logger } from '../../../../../../../../src/core/server'; +/** + * @deprecated since version 8.2.0. Use the detection_engine/rules/_bulk_action API instead + */ export const createRulesBulkRoute = ( router: SecuritySolutionPluginRouter, ml: SetupPlugins['ml'], - isRuleRegistryEnabled: boolean + isRuleRegistryEnabled: boolean, + logger: Logger ) => { router.post( { - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + path: DETECTION_ENGINE_RULES_BULK_CREATE, validate: { body: buildRouteValidation(createRulesBulkSchema), }, @@ -42,6 +48,8 @@ export const createRulesBulkRoute = ( }, }, async (context, request, response) => { + logDeprecatedBulkEndpoint(logger, DETECTION_ENGINE_RULES_BULK_CREATE); + const siemResponse = buildSiemResponse(response); const rulesClient = context.alerting.getRulesClient(); const esClient = context.core.elasticsearch.client; @@ -138,9 +146,16 @@ export const createRulesBulkRoute = ( ]; const [validated, errors] = validate(rulesBulk, rulesBulkSchema); if (errors != null) { - return siemResponse.error({ statusCode: 500, body: errors }); + return siemResponse.error({ + statusCode: 500, + body: errors, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_CREATE), + }); } else { - return response.ok({ body: validated ?? {} }); + return response.ok({ + body: validated ?? {}, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_CREATE), + }); } } ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts index 4ac4822c412fa..9d46ebabb7c8a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { DETECTION_ENGINE_RULES_BULK_DELETE } from '../../../../../common/constants'; import { getEmptyFindResult, getFindResultWithSingleHit, @@ -17,6 +17,7 @@ import { } from '../__mocks__/request_responses'; import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { deleteRulesBulkRoute } from './delete_rules_bulk_route'; +import { loggingSystemMock } from '../../../../../../../../src/core/server/mocks'; describe.each([ ['Legacy', false], @@ -28,12 +29,13 @@ describe.each([ beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); + const logger = loggingSystemMock.createLogger(); clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // rule exists clients.rulesClient.delete.mockResolvedValue({}); // successful deletion clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); // rule status request - deleteRulesBulkRoute(server.router, isRuleRegistryEnabled); + deleteRulesBulkRoute(server.router, isRuleRegistryEnabled, logger); }); describe('status codes with actionClient and alertClient', () => { @@ -42,7 +44,7 @@ describe.each([ expect(response.status).toEqual(200); }); - test('resturns 200 when deleting a single rule and related rule status', async () => { + test('returns 200 when deleting a single rule and related rule status', async () => { const response = await server.inject(getDeleteBulkRequest(), context); expect(response.status).toEqual(200); }); @@ -88,7 +90,7 @@ describe.each([ test('rejects requests without IDs', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, body: [{}], }); const response = await server.inject(request, context); @@ -104,7 +106,7 @@ describe.each([ test('rejects requests with both id and rule_id', async () => { const request = requestMock.create({ method: 'post', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, body: [{ id: 'c1e1b359-7ac1-4e96-bc81-c683c092436f', rule_id: 'rule_1' }], }); const response = await server.inject(request, context); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts index 442b707532ea6..cd3c219675ccb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts @@ -14,18 +14,19 @@ import { QueryRulesBulkSchemaDecoded, } from '../../../../../common/detection_engine/schemas/request/query_rules_bulk_schema'; import { rulesBulkSchema } from '../../../../../common/detection_engine/schemas/response/rules_bulk_schema'; -import type { RouteConfig, RequestHandler } from '../../../../../../../../src/core/server'; +import type { RouteConfig, RequestHandler, Logger } from '../../../../../../../../src/core/server'; import type { SecuritySolutionPluginRouter, SecuritySolutionRequestHandlerContext, } from '../../../../types'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { DETECTION_ENGINE_RULES_BULK_DELETE } from '../../../../../common/constants'; import { getIdBulkError } from './utils'; import { transformValidateBulkError } from './validate'; import { transformBulkError, buildSiemResponse, createBulkErrorObject } from '../utils'; import { deleteRules } from '../../rules/delete_rules'; import { readRules } from '../../rules/read_rules'; import { legacyMigrate } from '../../rules/utils'; +import { getDeprecatedBulkEndpointHeader, logDeprecatedBulkEndpoint } from './utils/deprecation'; type Config = RouteConfig; type Handler = RequestHandler< @@ -36,9 +37,13 @@ type Handler = RequestHandler< 'delete' | 'post' >; +/** + * @deprecated since version 8.2.0. Use the detection_engine/rules/_bulk_action API instead + */ export const deleteRulesBulkRoute = ( router: SecuritySolutionPluginRouter, - isRuleRegistryEnabled: boolean + isRuleRegistryEnabled: boolean, + logger: Logger ) => { const config: Config = { validate: { @@ -46,12 +51,14 @@ export const deleteRulesBulkRoute = ( queryRulesBulkSchema ), }, - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, + path: DETECTION_ENGINE_RULES_BULK_DELETE, options: { tags: ['access:securitySolution'], }, }; const handler: Handler = async (context, request, response) => { + logDeprecatedBulkEndpoint(logger, DETECTION_ENGINE_RULES_BULK_DELETE); + const siemResponse = buildSiemResponse(response); const rulesClient = context.alerting.getRulesClient(); const ruleExecutionLog = context.securitySolution.getRuleExecutionLog(); @@ -102,9 +109,16 @@ export const deleteRulesBulkRoute = ( ); const [validated, errors] = validate(rules, rulesBulkSchema); if (errors != null) { - return siemResponse.error({ statusCode: 500, body: errors }); + return siemResponse.error({ + statusCode: 500, + body: errors, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_DELETE), + }); } else { - return response.ok({ body: validated ?? {} }); + return response.ok({ + body: validated ?? {}, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_DELETE), + }); } }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index 6b3fa7ad83c68..9539ad2cb9c7b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -5,7 +5,10 @@ * 2.0. */ -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { + DETECTION_ENGINE_RULES_BULK_UPDATE, + DETECTION_ENGINE_RULES_URL, +} from '../../../../../common/constants'; import { mlServicesMock, mlAuthzMock as mockMlAuthzFactory } from '../../../machine_learning/mocks'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { @@ -19,6 +22,7 @@ import { serverMock, requestContextMock, requestMock } from '../__mocks__'; import { patchRulesBulkRoute } from './patch_rules_bulk_route'; import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { loggingSystemMock } from '../../../../../../../../src/core/server/mocks'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -34,13 +38,14 @@ describe.each([ server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); + const logger = loggingSystemMock.createLogger(); clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // rule exists clients.rulesClient.update.mockResolvedValue( getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); // update succeeds - patchRulesBulkRoute(server.router, ml, isRuleRegistryEnabled); + patchRulesBulkRoute(server.router, ml, isRuleRegistryEnabled, logger); }); describe('status codes', () => { @@ -96,7 +101,7 @@ describe.each([ }); const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [typicalMlRulePayload()], }); const response = await server.inject(request, context); @@ -122,7 +127,7 @@ describe.each([ const { type, ...payloadWithoutType } = typicalMlRulePayload(); const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [payloadWithoutType], }); const response = await server.inject(request, context); @@ -144,7 +149,7 @@ describe.each([ test('rejects payloads with no ID', async () => { const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ ...getCreateRulesSchemaMock(), rule_id: undefined }], }); const response = await server.inject(request, context); @@ -164,7 +169,7 @@ describe.each([ test('allows query rule type', async () => { const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -175,7 +180,7 @@ describe.each([ test('rejects unknown rule type', async () => { const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ ...getCreateRulesSchemaMock(), type: 'unknown_type' }], }); const result = server.validate(request); @@ -188,7 +193,7 @@ describe.each([ test('allows rule type of query and custom from and interval', async () => { const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ from: 'now-7m', interval: '5m', ...getCreateRulesSchemaMock() }], }); const result = server.validate(request); @@ -199,7 +204,7 @@ describe.each([ test('disallows invalid "from" param on rule', async () => { const request = requestMock.create({ method: 'patch', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [ { from: 'now-3755555555555555.67s', 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 58d364cb34b5c..aedb78a248c34 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 @@ -14,7 +14,7 @@ import { import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { rulesBulkSchema } from '../../../../../common/detection_engine/schemas/response/rules_bulk_schema'; import type { SecuritySolutionPluginRouter } from '../../../../types'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { throwAuthzError } from '../../../machine_learning/validation'; @@ -25,15 +25,21 @@ import { patchRules } from '../../rules/patch_rules'; import { readRules } from '../../rules/read_rules'; import { PartialFilter } from '../../types'; import { legacyMigrate } from '../../rules/utils'; +import { getDeprecatedBulkEndpointHeader, logDeprecatedBulkEndpoint } from './utils/deprecation'; +import { Logger } from '../../../../../../../../src/core/server'; +/** + * @deprecated since version 8.2.0. Use the detection_engine/rules/_bulk_action API instead + */ export const patchRulesBulkRoute = ( router: SecuritySolutionPluginRouter, ml: SetupPlugins['ml'], - isRuleRegistryEnabled: boolean + isRuleRegistryEnabled: boolean, + logger: Logger ) => { router.patch( { - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, validate: { body: buildRouteValidation( patchRulesBulkSchema @@ -44,6 +50,8 @@ export const patchRulesBulkRoute = ( }, }, async (context, request, response) => { + logDeprecatedBulkEndpoint(logger, DETECTION_ENGINE_RULES_BULK_UPDATE); + const siemResponse = buildSiemResponse(response); const rulesClient = context.alerting.getRulesClient(); @@ -207,9 +215,16 @@ export const patchRulesBulkRoute = ( const [validated, errors] = validate(rules, rulesBulkSchema); if (errors != null) { - return siemResponse.error({ statusCode: 500, body: errors }); + return siemResponse.error({ + statusCode: 500, + body: errors, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_UPDATE), + }); } else { - return response.ok({ body: validated ?? {} }); + return response.ok({ + body: validated ?? {}, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_UPDATE), + }); } } ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index 88c15f99ed6f7..12b7968b9793a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../../common/constants'; import { mlServicesMock, mlAuthzMock as mockMlAuthzFactory } from '../../../machine_learning/mocks'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { @@ -20,6 +20,7 @@ import { updateRulesBulkRoute } from './update_rules_bulk_route'; import { BulkError } from '../utils'; import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { loggingSystemMock } from '../../../../../../../../src/core/server/mocks'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -35,6 +36,7 @@ describe.each([ server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); + const logger = loggingSystemMock.createLogger(); clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); clients.rulesClient.update.mockResolvedValue( @@ -43,7 +45,7 @@ describe.each([ clients.appClient.getSignalsIndex.mockReturnValue('.siem-signals-test-index'); - updateRulesBulkRoute(server.router, ml, isRuleRegistryEnabled); + updateRulesBulkRoute(server.router, ml, isRuleRegistryEnabled, logger); }); describe('status codes', () => { @@ -90,7 +92,7 @@ describe.each([ }); const request = requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [typicalMlRulePayload()], }); @@ -112,7 +114,7 @@ describe.each([ test('rejects payloads with no ID', async () => { const noIdRequest = requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ ...getCreateRulesSchemaMock(), rule_id: undefined }], }); const response = await server.inject(noIdRequest, context); @@ -127,7 +129,7 @@ describe.each([ test('allows query rule type', async () => { const request = requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -138,7 +140,7 @@ describe.each([ test('rejects unknown rule type', async () => { const request = requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ ...getCreateRulesSchemaMock(), type: 'unknown_type' }], }); const result = server.validate(request); @@ -149,7 +151,7 @@ describe.each([ test('allows rule type of query and custom from and interval', async () => { const request = requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [{ from: 'now-7m', interval: '5m', ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -160,7 +162,7 @@ describe.each([ test('disallows invalid "from" param on rule', async () => { const request = requestMock.create({ method: 'put', - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, body: [ { from: 'now-3755555555555555.67s', 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 d1df5713914df..646fab5077dec 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 @@ -11,7 +11,7 @@ import { buildRouteValidation } from '../../../../utils/build_validation/route_v import { updateRulesBulkSchema } from '../../../../../common/detection_engine/schemas/request/update_rules_bulk_schema'; import { rulesBulkSchema } from '../../../../../common/detection_engine/schemas/response/rules_bulk_schema'; import type { SecuritySolutionPluginRouter } from '../../../../types'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; +import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../../common/constants'; import { SetupPlugins } from '../../../../plugin'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { throwAuthzError } from '../../../machine_learning/validation'; @@ -21,15 +21,21 @@ import { transformBulkError, buildSiemResponse, createBulkErrorObject } from '.. import { updateRules } from '../../rules/update_rules'; import { legacyMigrate } from '../../rules/utils'; import { readRules } from '../../rules/read_rules'; +import { getDeprecatedBulkEndpointHeader, logDeprecatedBulkEndpoint } from './utils/deprecation'; +import { Logger } from '../../../../../../../../src/core/server'; +/** + * @deprecated since version 8.2.0. Use the detection_engine/rules/_bulk_action API instead + */ export const updateRulesBulkRoute = ( router: SecuritySolutionPluginRouter, ml: SetupPlugins['ml'], - isRuleRegistryEnabled: boolean + isRuleRegistryEnabled: boolean, + logger: Logger ) => { router.put( { - path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + path: DETECTION_ENGINE_RULES_BULK_UPDATE, validate: { body: buildRouteValidation(updateRulesBulkSchema), }, @@ -38,6 +44,8 @@ export const updateRulesBulkRoute = ( }, }, async (context, request, response) => { + logDeprecatedBulkEndpoint(logger, DETECTION_ENGINE_RULES_BULK_UPDATE); + const siemResponse = buildSiemResponse(response); const rulesClient = context.alerting.getRulesClient(); @@ -105,9 +113,16 @@ export const updateRulesBulkRoute = ( const [validated, errors] = validate(rules, rulesBulkSchema); if (errors != null) { - return siemResponse.error({ statusCode: 500, body: errors }); + return siemResponse.error({ + statusCode: 500, + body: errors, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_UPDATE), + }); } else { - return response.ok({ body: validated ?? {} }); + return response.ok({ + body: validated ?? {}, + headers: getDeprecatedBulkEndpointHeader(DETECTION_ENGINE_RULES_BULK_UPDATE), + }); } } ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/deprecation.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/deprecation.ts new file mode 100644 index 0000000000000..18f77bfa85bc3 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/deprecation.ts @@ -0,0 +1,42 @@ +/* + * 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 { getDocLinks } from '@kbn/doc-links'; +import { Logger } from 'src/core/server'; +import { DETECTION_ENGINE_RULES_BULK_ACTION } from '../../../../../../common/constants'; + +/** + * Helper method for building deprecation messages + * + * @param path Deprecated endpoint path + * @returns string + */ +export const buildDeprecatedBulkEndpointMessage = (path: string) => { + const docsLink = getDocLinks({ kibanaBranch: 'main' }).siem.ruleApiOverview; + return `Deprecated endpoint: ${path} API is deprecated since v8.2. Please use the ${DETECTION_ENGINE_RULES_BULK_ACTION} API instead. See ${docsLink} for more detail.`; +}; + +/** + * Logs usages of a deprecated bulk endpoint + * + * @param logger System logger + * @param path Deprecated endpoint path + */ +export const logDeprecatedBulkEndpoint = (logger: Logger, path: string) => { + logger.warn(buildDeprecatedBulkEndpointMessage(path), { tags: ['deprecation'] }); +}; + +/** + * Creates a warning header with a message formatted according to RFC7234. + * We follow the same formatting as Elasticsearch + * https://github.com/elastic/elasticsearch/blob/5baabff6670a8ed49297488ca8cac8ec12a2078d/server/src/main/java/org/elasticsearch/common/logging/HeaderWarning.java#L55 + * + * @param path Deprecated endpoint path + */ +export const getDeprecatedBulkEndpointHeader = (path: string) => ({ + warning: `299 Kibana "${buildDeprecatedBulkEndpointMessage(path)}"`, +}); diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts index 2efb132c96ff6..8646cb54088c5 100644 --- a/x-pack/plugins/security_solution/server/routes/index.ts +++ b/x-pack/plugins/security_solution/server/routes/index.ts @@ -112,10 +112,10 @@ export const initRoutes = ( addPrepackedRulesRoute(router); getPrepackagedRulesStatusRoute(router, config, security, isRuleRegistryEnabled); - createRulesBulkRoute(router, ml, isRuleRegistryEnabled); - updateRulesBulkRoute(router, ml, isRuleRegistryEnabled); - patchRulesBulkRoute(router, ml, isRuleRegistryEnabled); - deleteRulesBulkRoute(router, isRuleRegistryEnabled); + createRulesBulkRoute(router, ml, isRuleRegistryEnabled, logger); + updateRulesBulkRoute(router, ml, isRuleRegistryEnabled, logger); + patchRulesBulkRoute(router, ml, isRuleRegistryEnabled, logger); + deleteRulesBulkRoute(router, isRuleRegistryEnabled, logger); performBulkActionRoute(router, ml, logger, isRuleRegistryEnabled); getRuleExecutionEventsRoute(router); diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/create_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/basic/tests/create_rules_bulk.ts index b54e1432f5463..bb450d8f0efdc 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/create_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/create_rules_bulk.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { DETECTION_ENGINE_RULES_BULK_CREATE } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, @@ -48,7 +48,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should create a single rule with a rule_id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRule()]) .expect(200); @@ -59,7 +59,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should create a single rule without a rule_id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRuleWithoutRuleId()]) .expect(200); @@ -70,7 +70,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return a 200 ok but have a 409 conflict if we attempt to create the same rule_id twice', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRule(), getSimpleRule()]) .expect(200); @@ -88,13 +88,13 @@ export default ({ getService }: FtrProviderContext): void => { it('should return a 200 ok but have a 409 conflict if we attempt to create the same rule_id that already exists', async () => { await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRule()]) .expect(200); const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'foo') .send([getSimpleRule()]) .expect(200); diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/delete_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/basic/tests/delete_rules_bulk.ts index b7517697ad2a9..09c2f5960fae5 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/delete_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/delete_rules_bulk.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { DETECTION_ENGINE_RULES_BULK_DELETE } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createRule, @@ -43,7 +43,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete the rule in bulk const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1' }]) .expect(200); @@ -57,7 +57,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its rule_id const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: bodyWithCreatedRule.rule_id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -71,7 +71,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its id const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -82,7 +82,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the ruled_id does not exist when trying to delete a rule_id', async () => { const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: 'fake_id' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -100,7 +100,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the id does not exist when trying to delete an id', async () => { const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -120,7 +120,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyWithCreatedRule = await createRule(supertest, log, getSimpleRuleWithoutRuleId()); const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }, { id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -155,7 +155,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete the rule in bulk const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1' }]) .expect(200); @@ -169,7 +169,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its rule_id const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: bodyWithCreatedRule.rule_id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -183,7 +183,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its id const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -194,7 +194,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the ruled_id does not exist when trying to delete a rule_id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: 'fake_id' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -212,7 +212,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the id does not exist when trying to delete an id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -232,7 +232,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyWithCreatedRule = await createRule(supertest, log, getSimpleRuleWithoutRuleId()); const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }, { id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/patch_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/basic/tests/patch_rules_bulk.ts index 0be23c1d8a289..dd1e36e4fb624 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/patch_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/patch_rules_bulk.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, @@ -42,7 +42,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', name: 'some other name' }]) .expect(200); @@ -60,7 +60,7 @@ export default ({ getService }: FtrProviderContext) => { // patch both rule names const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { rule_id: 'rule-1', name: 'some other name' }, @@ -87,7 +87,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ id: createRuleBody.id, name: 'some other name' }]) .expect(200); @@ -105,7 +105,7 @@ export default ({ getService }: FtrProviderContext) => { // patch both rule names const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { id: createRule1.id, name: 'some other name' }, @@ -132,7 +132,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ id: createdBody.id, name: 'some other name' }]) .expect(200); @@ -149,7 +149,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's enabled to false const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', enabled: false }]) .expect(200); @@ -166,7 +166,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's enabled to false and another property const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', severity: 'low', enabled: false }]) .expect(200); @@ -185,14 +185,14 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's timeline_title await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', timeline_title: 'some title', timeline_id: 'some id' }]) .expect(200); // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', name: 'some other name' }]) .expect(200); @@ -209,7 +209,7 @@ export default ({ getService }: FtrProviderContext) => { it('should return a 200 but give a 404 in the message if it is given a fake id', async () => { const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ id: '5096dec6-b6b9-4d8d-8f93-6c2602079d9d', name: 'some other name' }]) .expect(200); @@ -227,7 +227,7 @@ export default ({ getService }: FtrProviderContext) => { it('should return a 200 but give a 404 in the message if it is given a fake rule_id', async () => { const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'fake_id', name: 'some other name' }]) .expect(200); @@ -245,7 +245,7 @@ export default ({ getService }: FtrProviderContext) => { // patch one rule name and give a fake id for the second const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { rule_id: 'rule-1', name: 'some other name' }, @@ -275,7 +275,7 @@ export default ({ getService }: FtrProviderContext) => { // patch one rule name and give a fake id for the second const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { id: createdBody.id, name: 'some other name' }, diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts index 46e34869a8e03..a2043c49cdbc2 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts @@ -7,7 +7,10 @@ import expect from '@kbn/expect'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { + DETECTION_ENGINE_RULES_BULK_UPDATE, + DETECTION_ENGINE_RULES_URL, +} from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, @@ -46,7 +49,7 @@ export default ({ getService }: FtrProviderContext) => { // update a simple rule's name const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule]) .expect(200); @@ -76,7 +79,7 @@ export default ({ getService }: FtrProviderContext) => { // update both rule names const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1, updatedRule2]) .expect(200); @@ -105,7 +108,7 @@ export default ({ getService }: FtrProviderContext) => { delete updatedRule1.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1]) .expect(200); @@ -133,7 +136,7 @@ export default ({ getService }: FtrProviderContext) => { delete updatedRule2.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1, updatedRule2]) .expect(200); @@ -162,7 +165,7 @@ export default ({ getService }: FtrProviderContext) => { delete updatedRule1.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1]) .expect(200); @@ -183,7 +186,7 @@ export default ({ getService }: FtrProviderContext) => { updatedRule1.enabled = false; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1]) .expect(200); @@ -206,7 +209,7 @@ export default ({ getService }: FtrProviderContext) => { ruleUpdate.timeline_id = 'some id'; await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate]) .expect(200); @@ -216,7 +219,7 @@ export default ({ getService }: FtrProviderContext) => { ruleUpdate2.name = 'some other name'; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate2]) .expect(200); @@ -235,7 +238,7 @@ export default ({ getService }: FtrProviderContext) => { delete ruleUpdate.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate]) .expect(200); @@ -257,7 +260,7 @@ export default ({ getService }: FtrProviderContext) => { delete ruleUpdate.id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate]) .expect(200); @@ -283,7 +286,7 @@ export default ({ getService }: FtrProviderContext) => { // update one rule name and give a fake id for the second const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate, ruleUpdate2]) .expect(200); @@ -320,7 +323,7 @@ export default ({ getService }: FtrProviderContext) => { rule2.name = 'some other name'; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([rule1, rule2]) .expect(200); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules_bulk.ts index 7ea9e4cdb5f84..d2181d779e4e1 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules_bulk.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { DETECTION_ENGINE_RULES_BULK_CREATE } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, @@ -30,6 +30,24 @@ export default ({ getService }: FtrProviderContext): void => { const log = getService('log'); describe('create_rules_bulk', () => { + describe('deprecations', () => { + afterEach(async () => { + await deleteAllAlerts(supertest, log); + }); + + it('should return a warning header', async () => { + const { header } = await supertest + .post(DETECTION_ENGINE_RULES_BULK_CREATE) + .set('kbn-xsrf', 'true') + .send([getSimpleRule()]) + .expect(200); + + expect(header.warning).to.be( + '299 Kibana "Deprecated endpoint: /api/detection_engine/rules/_bulk_create API is deprecated since v8.2. Please use the /api/detection_engine/rules/_bulk_action API instead. See https://www.elastic.co/guide/en/security/master/rule-api-overview.html for more detail."' + ); + }); + }); + describe('creating rules in bulk', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); @@ -50,7 +68,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should create a single rule with a rule_id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRule()]) .expect(200); @@ -81,7 +99,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should create a single rule with a rule_id and validate it ran successfully', async () => { const simpleRule = getRuleForSignalTesting(['auditbeat-*']); const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([simpleRule]) .expect(200); @@ -91,7 +109,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should create a single rule without a rule_id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRuleWithoutRuleId()]) .expect(200); @@ -102,7 +120,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return a 200 ok but have a 409 conflict if we attempt to create the same rule_id twice', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRule(), getSimpleRule()]) .expect(200); @@ -120,13 +138,13 @@ export default ({ getService }: FtrProviderContext): void => { it('should return a 200 ok but have a 409 conflict if we attempt to create the same rule_id that already exists', async () => { await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'true') .send([getSimpleRule()]) .expect(200); const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`) + .post(DETECTION_ENGINE_RULES_BULK_CREATE) .set('kbn-xsrf', 'foo') .send([getSimpleRule()]) .expect(200); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts index 69be1f2eb0aff..a2c20f8496049 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { BASE_ALERTING_API_PATH } from '../../../../plugins/alerting/common'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { DETECTION_ENGINE_RULES_BULK_DELETE } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createLegacyRuleAction, @@ -31,6 +31,22 @@ export default ({ getService }: FtrProviderContext): void => { const log = getService('log'); describe('delete_rules_bulk', () => { + describe('deprecations', () => { + it('should return a warning header', async () => { + await createRule(supertest, log, getSimpleRule()); + + const { header } = await supertest + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) + .set('kbn-xsrf', 'true') + .send([{ rule_id: 'rule-1' }]) + .expect(200); + + expect(header.warning).to.be( + '299 Kibana "Deprecated endpoint: /api/detection_engine/rules/_bulk_delete API is deprecated since v8.2. Please use the /api/detection_engine/rules/_bulk_action API instead. See https://www.elastic.co/guide/en/security/master/rule-api-overview.html for more detail."' + ); + }); + }); + describe('deleting rules bulk using DELETE', () => { beforeEach(async () => { await createSignalsIndex(supertest, log); @@ -46,7 +62,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete the rule in bulk const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1' }]) .expect(200); @@ -60,7 +76,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its rule_id const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: bodyWithCreatedRule.rule_id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -74,7 +90,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its id const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -85,7 +101,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the ruled_id does not exist when trying to delete a rule_id', async () => { const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: 'fake_id' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -103,7 +119,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the id does not exist when trying to delete an id', async () => { const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -123,7 +139,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyWithCreatedRule = await createRule(supertest, log, getSimpleRuleWithoutRuleId()); const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }, { id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -158,7 +174,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete the rule in bulk const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1' }]) .expect(200); @@ -172,7 +188,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its rule_id const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: bodyWithCreatedRule.rule_id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -186,7 +202,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete that rule by its id const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -197,7 +213,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the ruled_id does not exist when trying to delete a rule_id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ rule_id: 'fake_id' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -215,7 +231,7 @@ export default ({ getService }: FtrProviderContext): void => { it('should return an error if the id does not exist when trying to delete an id', async () => { const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -235,7 +251,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyWithCreatedRule = await createRule(supertest, log, getSimpleRuleWithoutRuleId()); const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .post(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: bodyWithCreatedRule.id }, { id: 'c4e80a0d-e20f-4efc-84c1-08112da5a612' }]) .set('kbn-xsrf', 'true') .expect(200); @@ -272,7 +288,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete the rule with the legacy action const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: createRuleBody.id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -320,7 +336,7 @@ export default ({ getService }: FtrProviderContext): void => { // delete 2 rules where both have legacy actions const { body } = await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: createRuleBody1.id }, { id: createRuleBody2.id }]) .set('kbn-xsrf', 'true') .expect(200); @@ -372,7 +388,7 @@ export default ({ getService }: FtrProviderContext): void => { // bulk delete the rule await supertest - .delete(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) + .delete(DETECTION_ENGINE_RULES_BULK_DELETE) .send([{ id: createRuleBody.id }]) .set('kbn-xsrf', 'true') .expect(200); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules_bulk.ts index 51cf1a334a2c7..e860c097c9964 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules_bulk.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, @@ -28,6 +28,26 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); describe('patch_rules_bulk', () => { + describe('deprecations', () => { + afterEach(async () => { + await deleteAllAlerts(supertest, log); + }); + + it('should return a warning header', async () => { + await createRule(supertest, log, getSimpleRule('rule-1')); + + const { header } = await supertest + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) + .set('kbn-xsrf', 'true') + .send([{ rule_id: 'rule-1', name: 'some other name' }]) + .expect(200); + + expect(header.warning).to.be( + '299 Kibana "Deprecated endpoint: /api/detection_engine/rules/_bulk_update API is deprecated since v8.2. Please use the /api/detection_engine/rules/_bulk_action API instead. See https://www.elastic.co/guide/en/security/master/rule-api-overview.html for more detail."' + ); + }); + }); + describe('patch rules bulk', () => { beforeEach(async () => { await createSignalsIndex(supertest, log); @@ -43,7 +63,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', name: 'some other name' }]) .expect(200); @@ -61,7 +81,7 @@ export default ({ getService }: FtrProviderContext) => { // patch both rule names const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { rule_id: 'rule-1', name: 'some other name' }, @@ -88,7 +108,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ id: createRuleBody.id, name: 'some other name' }]) .expect(200); @@ -106,7 +126,7 @@ export default ({ getService }: FtrProviderContext) => { // patch both rule names const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { id: createRule1.id, name: 'some other name' }, @@ -149,7 +169,7 @@ export default ({ getService }: FtrProviderContext) => { ]); // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { id: rule1.id, enabled: false }, @@ -182,7 +202,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ id: createdBody.id, name: 'some other name' }]) .expect(200); @@ -199,7 +219,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's enabled to false const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', enabled: false }]) .expect(200); @@ -216,7 +236,7 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's enabled to false and another property const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', severity: 'low', enabled: false }]) .expect(200); @@ -235,14 +255,14 @@ export default ({ getService }: FtrProviderContext) => { // patch a simple rule's timeline_title await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', timeline_title: 'some title', timeline_id: 'some id' }]) .expect(200); // patch a simple rule's name const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'rule-1', name: 'some other name' }]) .expect(200); @@ -259,7 +279,7 @@ export default ({ getService }: FtrProviderContext) => { it('should return a 200 but give a 404 in the message if it is given a fake id', async () => { const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ id: '5096dec6-b6b9-4d8d-8f93-6c2602079d9d', name: 'some other name' }]) .expect(200); @@ -277,7 +297,7 @@ export default ({ getService }: FtrProviderContext) => { it('should return a 200 but give a 404 in the message if it is given a fake rule_id', async () => { const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([{ rule_id: 'fake_id', name: 'some other name' }]) .expect(200); @@ -295,7 +315,7 @@ export default ({ getService }: FtrProviderContext) => { // patch one rule name and give a fake id for the second const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { rule_id: 'rule-1', name: 'some other name' }, @@ -325,7 +345,7 @@ export default ({ getService }: FtrProviderContext) => { // patch one rule name and give a fake id for the second const { body } = await supertest - .patch(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .patch(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ { id: createdBody.id, name: 'some other name' }, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts index b165258237b41..e754cb2c02080 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts @@ -8,7 +8,10 @@ import expect from '@kbn/expect'; import { FullResponseSchema } from '../../../../plugins/security_solution/common/detection_engine/schemas/request'; -import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; +import { + DETECTION_ENGINE_RULES_URL, + DETECTION_ENGINE_RULES_BULK_UPDATE, +} from '../../../../plugins/security_solution/common/constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createSignalsIndex, @@ -30,6 +33,27 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); describe('update_rules_bulk', () => { + describe('deprecations', () => { + afterEach(async () => { + await deleteAllAlerts(supertest, log); + }); + + it('should return a warning header', async () => { + await createRule(supertest, log, getSimpleRule('rule-1')); + const updatedRule = getSimpleRuleUpdate('rule-1'); + + const { header } = await supertest + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) + .set('kbn-xsrf', 'true') + .send([updatedRule]) + .expect(200); + + expect(header.warning).to.be( + '299 Kibana "Deprecated endpoint: /api/detection_engine/rules/_bulk_update API is deprecated since v8.2. Please use the /api/detection_engine/rules/_bulk_action API instead. See https://www.elastic.co/guide/en/security/master/rule-api-overview.html for more detail."' + ); + }); + }); + describe('update rules bulk', () => { beforeEach(async () => { await createSignalsIndex(supertest, log); @@ -48,7 +72,7 @@ export default ({ getService }: FtrProviderContext) => { // update a simple rule's name const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule]) .expect(200); @@ -78,7 +102,7 @@ export default ({ getService }: FtrProviderContext) => { // update both rule names const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1, updatedRule2]) .expect(200); @@ -137,7 +161,7 @@ export default ({ getService }: FtrProviderContext) => { // update both rule names const { body }: { body: FullResponseSchema[] } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1, updatedRule2]) .expect(200); @@ -199,7 +223,7 @@ export default ({ getService }: FtrProviderContext) => { // update both rule names const { body }: { body: FullResponseSchema[] } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1, updatedRule2]) .expect(200); @@ -225,7 +249,7 @@ export default ({ getService }: FtrProviderContext) => { delete updatedRule1.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1]) .expect(200); @@ -253,7 +277,7 @@ export default ({ getService }: FtrProviderContext) => { delete updatedRule2.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1, updatedRule2]) .expect(200); @@ -282,7 +306,7 @@ export default ({ getService }: FtrProviderContext) => { delete updatedRule1.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1]) .expect(200); @@ -303,7 +327,7 @@ export default ({ getService }: FtrProviderContext) => { updatedRule1.enabled = false; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([updatedRule1]) .expect(200); @@ -326,7 +350,7 @@ export default ({ getService }: FtrProviderContext) => { ruleUpdate.timeline_id = 'some id'; await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate]) .expect(200); @@ -336,7 +360,7 @@ export default ({ getService }: FtrProviderContext) => { ruleUpdate2.name = 'some other name'; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate2]) .expect(200); @@ -355,7 +379,7 @@ export default ({ getService }: FtrProviderContext) => { delete ruleUpdate.rule_id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate]) .expect(200); @@ -377,7 +401,7 @@ export default ({ getService }: FtrProviderContext) => { delete ruleUpdate.id; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate]) .expect(200); @@ -403,7 +427,7 @@ export default ({ getService }: FtrProviderContext) => { // update one rule name and give a fake id for the second const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([ruleUpdate, ruleUpdate2]) .expect(200); @@ -440,7 +464,7 @@ export default ({ getService }: FtrProviderContext) => { rule2.name = 'some other name'; const { body } = await supertest - .put(`${DETECTION_ENGINE_RULES_URL}/_bulk_update`) + .put(DETECTION_ENGINE_RULES_BULK_UPDATE) .set('kbn-xsrf', 'true') .send([rule1, rule2]) .expect(200); diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index de66002343212..2087e0d6ab523 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -52,6 +52,7 @@ import { DETECTION_ENGINE_INDEX_URL, DETECTION_ENGINE_PREPACKAGED_URL, DETECTION_ENGINE_QUERY_SIGNALS_URL, + DETECTION_ENGINE_RULES_BULK_ACTION, DETECTION_ENGINE_RULES_URL, DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL, DETECTION_ENGINE_SIGNALS_MIGRATION_URL, @@ -513,18 +514,9 @@ export const deleteAllAlerts = async ( ): Promise => { await countDownTest( async () => { - const { body } = await supertest - .get(`${DETECTION_ENGINE_RULES_URL}/_find?per_page=9999`) - .set('kbn-xsrf', 'true') - .send(); - - const ids = body.data.map((rule: FullResponseSchema) => ({ - id: rule.id, - })); - await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`) - .send(ids) + .post(DETECTION_ENGINE_RULES_BULK_ACTION) + .send({ action: 'delete', query: '' }) .set('kbn-xsrf', 'true'); const { body: finalCheck } = await supertest From eaf6c84c20144383dea5e3a38bdf8689360b4a64 Mon Sep 17 00:00:00 2001 From: Baturalp Gurdin <9674241+suchcodemuchwow@users.noreply.github.com> Date: Tue, 12 Apr 2022 15:11:14 +0300 Subject: [PATCH 04/15] add login journey (#129976) --- .buildkite/scripts/steps/functional/performance_playwright.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/scripts/steps/functional/performance_playwright.sh b/.buildkite/scripts/steps/functional/performance_playwright.sh index 9a4301e94f7fe..d739f136992e7 100644 --- a/.buildkite/scripts/steps/functional/performance_playwright.sh +++ b/.buildkite/scripts/steps/functional/performance_playwright.sh @@ -20,7 +20,7 @@ sleep 120 cd "$XPACK_DIR" -journeys=("ecommerce_dashboard" "flight_dashboard" "web_logs_dashboard" "promotion_tracking_dashboard") +journeys=("login" "ecommerce_dashboard" "flight_dashboard" "web_logs_dashboard" "promotion_tracking_dashboard") for i in "${journeys[@]}"; do echo "JOURNEY[${i}] is running" From b0591a48db6379e76d7074d44337117907ca0b40 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Tue, 12 Apr 2022 15:16:32 +0300 Subject: [PATCH 05/15] [Maps][Visualize][Graph][Dashboard] Fixes the listingLimit settings url (#129701) * [Maps][Visualize][Graph][Dashboard] Fixes the listingLimit settings url * Check if user has permissions to alter the advanced setting * Use the uiSettings service instead of the deprecated savedObjects one * Address review comments - maps Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../dashboard_listing.test.tsx.snap | 238 ++++++++++++++++-- .../application/listing/dashboard_listing.tsx | 10 +- .../table_list_view/table_list_view.test.tsx | 3 +- .../table_list_view/table_list_view.tsx | 58 +++-- .../visualizations/common/constants.ts | 2 + src/plugins/visualizations/public/index.ts | 6 +- src/plugins/visualizations/public/plugin.ts | 1 - .../components/visualize_listing.tsx | 13 +- .../public/visualize_app/types.ts | 2 - .../graph/public/apps/listing_route.tsx | 12 +- x-pack/plugins/maps/public/kibana_services.ts | 2 +- .../routes/list_page/maps_list_view.tsx | 15 +- 12 files changed, 308 insertions(+), 54 deletions(-) diff --git a/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap b/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap index 598254ad2173f..6706deeaa1de4 100644 --- a/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap +++ b/src/plugins/dashboard/public/application/listing/__snapshots__/dashboard_listing.test.tsx.snap @@ -22,6 +22,38 @@ exports[`after fetch When given a title that matches multiple dashboards, filter title="search by title" > Promise.resolve({ total: 0, hits: [] })), theme: themeServiceMock.createStartContract(), + application: applicationServiceMock.createStartContract(), }; describe('TableListView', () => { diff --git a/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx b/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx index dd023d522dbb6..55e822e68f489 100644 --- a/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx +++ b/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ThemeServiceStart, HttpFetchError, ToastsStart } from 'kibana/public'; +import { ThemeServiceStart, HttpFetchError, ToastsStart, ApplicationStart } from 'kibana/public'; import { debounce, keyBy, sortBy, uniq } from 'lodash'; import React from 'react'; import { KibanaPageTemplate } from '../page_template'; @@ -58,6 +58,7 @@ export interface TableListViewProps { tableCaption: string; searchFilters?: SearchFilterConfig[]; theme: ThemeServiceStart; + application: ApplicationStart; } export interface TableListViewState { @@ -275,6 +276,11 @@ class TableListView extends React.Component< renderListingLimitWarning() { if (this.state.showLimitError) { + const canEditAdvancedSettings = this.props.application.capabilities.advancedSettings.save; + const setting = 'savedObjects:listingLimit'; + const advancedSettingsLink = this.props.application.getUrlForApp('management', { + path: `/kibana/settings?query=${setting}`, + }); return ( extends React.Component< iconType="help" >

- listingLimit, - advancedSettingsLink: ( - - - - ), - }} - /> + values={{ + entityNamePlural: this.props.entityNamePlural, + totalItems: this.state.totalItems, + listingLimitValue: this.props.listingLimit, + listingLimitText: listingLimit, + advancedSettingsLink: ( + + + + ), + }} + /> + ) : ( + listingLimit, + }} + /> + )}

diff --git a/src/plugins/visualizations/common/constants.ts b/src/plugins/visualizations/common/constants.ts index b901dacc62971..0b840c8ff13fc 100644 --- a/src/plugins/visualizations/common/constants.ts +++ b/src/plugins/visualizations/common/constants.ts @@ -7,6 +7,8 @@ */ export const VISUALIZE_ENABLE_LABS_SETTING = 'visualize:enableLabs'; +export const SAVED_OBJECTS_LIMIT_SETTING = 'savedObjects:listingLimit'; +export const SAVED_OBJECTS_PER_PAGE_SETTING = 'savedObjects:perPage'; export const VISUALIZE_EMBEDDABLE_TYPE = 'visualization'; export const STATE_STORAGE_KEY = '_a'; diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index de2af1d5cdcfb..73f02a44dac13 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -52,7 +52,11 @@ export type { VisualizationListItem, VisualizationStage, } from './vis_types/vis_type_alias_registry'; -export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants'; +export { + VISUALIZE_ENABLE_LABS_SETTING, + SAVED_OBJECTS_LIMIT_SETTING, + SAVED_OBJECTS_PER_PAGE_SETTING, +} from '../common/constants'; export type { SavedVisState, VisParams, Dimension } from '../common'; export { prepareLogTable } from '../common'; export type { ExpressionValueVisDimension } from '../common/expression_functions/vis_dimension'; diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 997d78b31163d..a4934e0b8edff 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -281,7 +281,6 @@ export class VisualizationsPlugin stateTransferService: pluginsStart.embeddable.getStateTransfer(), setActiveUrl, createVisEmbeddableFromObject: createVisEmbeddableFromObject({ start }), - savedObjectsPublic: pluginsStart.savedObjects, scopedHistory: params.history, restorePreviousUrl, setHeaderActionMenu: params.setHeaderActionMenu, diff --git a/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx b/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx index a180cf78feeb2..e38d854247786 100644 --- a/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx +++ b/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx @@ -22,7 +22,11 @@ import { showNewVisModal } from '../../wizard'; import { getTypes } from '../../services'; import { SavedObjectsFindOptionsReference } from '../../../../../core/public'; import { useKibana, TableListView, useExecutionContext } from '../../../../kibana_react/public'; -import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public'; +import { + VISUALIZE_ENABLE_LABS_SETTING, + SAVED_OBJECTS_LIMIT_SETTING, + SAVED_OBJECTS_PER_PAGE_SETTING, +} from '../../../../visualizations/public'; import { VisualizeServices } from '../types'; import { VisualizeConstants } from '../../../common/constants'; import { getTableColumns, getNoItemsMessage } from '../utils'; @@ -37,7 +41,6 @@ export const VisualizeListing = () => { toastNotifications, stateTransferService, savedObjects, - savedObjectsPublic, savedObjectsTagging, uiSettings, visualizeCapabilities, @@ -48,7 +51,8 @@ export const VisualizeListing = () => { } = useKibana(); const { pathname } = useLocation(); const closeNewVisModal = useRef(() => {}); - const listingLimit = savedObjectsPublic.settings.getListingLimit(); + const listingLimit = uiSettings.get(SAVED_OBJECTS_LIMIT_SETTING); + const initialPageSize = uiSettings.get(SAVED_OBJECTS_PER_PAGE_SETTING); useExecutionContext(executionContext, { type: 'application', @@ -193,7 +197,7 @@ export const VisualizeListing = () => { editItem={visualizeCapabilities.save ? editItem : undefined} tableColumns={tableColumns} listingLimit={listingLimit} - initialPageSize={savedObjectsPublic.settings.getPerPage()} + initialPageSize={initialPageSize} initialFilter={''} rowHeader="title" emptyPrompt={noItemsFragment} @@ -209,6 +213,7 @@ export const VisualizeListing = () => { toastNotifications={toastNotifications} searchFilters={searchFilters} theme={theme} + application={application} > {dashboardCapabilities.createNew && ( <> diff --git a/src/plugins/visualizations/public/visualize_app/types.ts b/src/plugins/visualizations/public/visualize_app/types.ts index 7c4c8155a9405..59cd94d210269 100644 --- a/src/plugins/visualizations/public/visualize_app/types.ts +++ b/src/plugins/visualizations/public/visualize_app/types.ts @@ -39,7 +39,6 @@ import type { Filter } from '@kbn/es-query'; import type { Query, DataPublicPluginStart, TimeRange } from 'src/plugins/data/public'; import type { DataViewsPublicPluginStart } from 'src/plugins/data_views/public'; import type { SharePluginStart } from 'src/plugins/share/public'; -import type { SavedObjectsStart } from 'src/plugins/saved_objects/public'; import type { EmbeddableStart, EmbeddableStateTransfer } from 'src/plugins/embeddable/public'; import type { UrlForwardingStart } from 'src/plugins/url_forwarding/public'; import type { PresentationUtilPluginStart } from 'src/plugins/presentation_util/public'; @@ -97,7 +96,6 @@ export interface VisualizeServices extends CoreStart { share?: SharePluginStart; visualizeCapabilities: Record>; dashboardCapabilities: Record>; - savedObjectsPublic: SavedObjectsStart; setActiveUrl: (newUrl: string) => void; createVisEmbeddableFromObject: ReturnType; restorePreviousUrl: () => void; diff --git a/x-pack/plugins/graph/public/apps/listing_route.tsx b/x-pack/plugins/graph/public/apps/listing_route.tsx index dc70d84155bf9..1683388841729 100644 --- a/x-pack/plugins/graph/public/apps/listing_route.tsx +++ b/x-pack/plugins/graph/public/apps/listing_route.tsx @@ -17,15 +17,18 @@ import { getEditPath, getEditUrl, getNewPath, setBreadcrumbs } from '../services import { GraphWorkspaceSavedObject } from '../types'; import { GraphServices } from '../application'; +const SAVED_OBJECTS_LIMIT_SETTING = 'savedObjects:listingLimit'; +const SAVED_OBJECTS_PER_PAGE_SETTING = 'savedObjects:perPage'; + export interface ListingRouteProps { - deps: GraphServices; + deps: Omit; } export function ListingRoute({ - deps: { chrome, savedObjects, savedObjectsClient, coreStart, capabilities, addBasePath }, + deps: { chrome, savedObjectsClient, coreStart, capabilities, addBasePath, uiSettings }, }: ListingRouteProps) { - const listingLimit = savedObjects.settings.getListingLimit(); - const initialPageSize = savedObjects.settings.getPerPage(); + const listingLimit = uiSettings.get(SAVED_OBJECTS_LIMIT_SETTING); + const initialPageSize = uiSettings.get(SAVED_OBJECTS_PER_PAGE_SETTING); const history = useHistory(); const query = new URLSearchParams(useLocation().search); const initialFilter = query.get('filter') || ''; @@ -103,6 +106,7 @@ export function ListingRoute({ defaultMessage: 'Graphs', })} theme={coreStart.theme} + application={coreStart.application} /> ); diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index f2345d2102a12..8b51fb5fbebc6 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -51,7 +51,6 @@ export const getVisualizeCapabilities = () => coreStart.application.capabilities export const getDocLinks = () => coreStart.docLinks; export const getCoreOverlays = () => coreStart.overlays; export const getData = () => pluginsStart.data; -export const getSavedObjects = () => pluginsStart.savedObjects; export const getUiActions = () => pluginsStart.uiActions; export const getCore = () => coreStart; export const getNavigation = () => pluginsStart.navigation; @@ -66,6 +65,7 @@ export const getSpacesApi = () => pluginsStart.spaces; export const getTheme = () => coreStart.theme; export const getUsageCollection = () => pluginsStart.usageCollection; export const getSharedUXPluginContext = () => pluginsStart.sharedUX; +export const getApplication = () => coreStart.application; // xpack.maps.* kibana.yml settings from this plugin let mapAppConfig: MapsConfigType; diff --git a/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx b/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx index dab284b0b71e4..f81d88da80b09 100644 --- a/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx +++ b/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx @@ -21,12 +21,16 @@ import { getNavigateToApp, getSavedObjectsClient, getSavedObjectsTagging, - getSavedObjects, + getUiSettings, getTheme, + getApplication, } from '../../kibana_services'; import { getAppTitle } from '../../../common/i18n_getters'; import { MapSavedObjectAttributes } from '../../../common/map_saved_object_type'; +const SAVED_OBJECTS_LIMIT_SETTING = 'savedObjects:listingLimit'; +const SAVED_OBJECTS_PER_PAGE_SETTING = 'savedObjects:perPage'; + interface MapItem { id: string; title: string; @@ -93,7 +97,7 @@ async function findMaps(searchQuery: string) { const resp = await getSavedObjectsClient().find({ type: MAP_SAVED_OBJECT_TYPE, search: searchTerm ? `${searchTerm}*` : undefined, - perPage: getSavedObjects().settings.getListingLimit(), + perPage: getUiSettings().get(SAVED_OBJECTS_LIMIT_SETTING), page: 1, searchFields: ['title^3', 'description'], defaultSearchOperator: 'AND', @@ -129,6 +133,8 @@ export function MapsListView() { }); const isReadOnly = !getMapsCapabilities().save; + const listingLimit = getUiSettings().get(SAVED_OBJECTS_LIMIT_SETTING); + const initialPageSize = getUiSettings().get(SAVED_OBJECTS_PER_PAGE_SETTING); getCoreChrome().docTitle.change(getAppTitle()); getCoreChrome().setBreadcrumbs([{ text: getAppTitle() }]); @@ -141,9 +147,9 @@ export function MapsListView() { findItems={findMaps} deleteItems={isReadOnly ? undefined : deleteMaps} tableColumns={tableColumns} - listingLimit={getSavedObjects().settings.getListingLimit()} + listingLimit={listingLimit} initialFilter={''} - initialPageSize={getSavedObjects().settings.getPerPage()} + initialPageSize={initialPageSize} entityName={i18n.translate('xpack.maps.mapListing.entityName', { defaultMessage: 'map', })} @@ -157,6 +163,7 @@ export function MapsListView() { toastNotifications={getToasts()} searchFilters={searchFilters} theme={getTheme()} + application={getApplication()} /> ); } From 092c71a21b771bb6ad4468f85cf1d442fd2deea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 12 Apr 2022 13:24:33 +0100 Subject: [PATCH 06/15] [Form lib] Fixes (#128489) --- .../components/use_array.test.tsx | 112 ++++++++++ .../hook_form_lib/components/use_array.ts | 8 +- .../components/use_field.test.tsx | 198 ++++++++++++++---- .../hook_form_lib/components/use_field.tsx | 9 + .../forms/hook_form_lib/hooks/use_field.ts | 62 +++--- .../forms/hook_form_lib/hooks/use_form.ts | 15 +- .../hooks/use_form_is_modified.test.tsx | 8 +- .../hooks/use_form_is_modified.ts | 42 ++-- .../static/forms/hook_form_lib/lib/index.ts | 4 +- .../forms/hook_form_lib/lib/utils.test.ts | 43 ++++ .../static/forms/hook_form_lib/lib/utils.ts | 43 +++- 11 files changed, 445 insertions(+), 99 deletions(-) create mode 100644 src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.test.tsx create mode 100644 src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.test.ts diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.test.tsx new file mode 100644 index 0000000000000..dc8695190bdaf --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.test.tsx @@ -0,0 +1,112 @@ +/* + * 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 React, { useEffect } from 'react'; +import { act } from 'react-dom/test-utils'; + +import { registerTestBed } from '../shared_imports'; +import { useForm } from '../hooks/use_form'; +import { useFormData } from '../hooks/use_form_data'; +import { Form } from './form'; +import { UseField } from './use_field'; +import { UseArray } from './use_array'; + +describe('', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + test('it should render by default 1 array item', () => { + const TestComp = () => { + const { form } = useForm(); + return ( +
+ + {({ items }) => { + return ( + <> + {items.map(({ id }) => { + return ( +

+ Array item +

+ ); + })} + + ); + }} +
+
+ ); + }; + + const setup = registerTestBed(TestComp, { + memoryRouter: { wrapComponent: false }, + }); + + const { find } = setup(); + + expect(find('arrayItem').length).toBe(1); + }); + + test('it should allow to listen to array item field value change', async () => { + const onFormData = jest.fn(); + + const TestComp = ({ onData }: { onData: (data: any) => void }) => { + const { form } = useForm(); + const [formData] = useFormData({ form, watch: 'users[0].name' }); + + useEffect(() => { + onData(formData); + }, [onData, formData]); + + return ( +
+ + {({ items }) => { + return ( + <> + {items.map(({ id, path }) => { + return ( + + ); + })} + + ); + }} + +
+ ); + }; + + const setup = registerTestBed(TestComp, { + defaultProps: { onData: onFormData }, + memoryRouter: { wrapComponent: false }, + }); + + const { + form: { setInputValue }, + } = setup(); + + await act(async () => { + setInputValue('nameField__0', 'John'); + }); + + const formData = onFormData.mock.calls[onFormData.mock.calls.length - 1][0]; + + expect(formData.users[0].name).toEqual('John'); + }); +}); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts index 3e7b061603458..78379aa9fffbf 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import uuid from 'uuid'; import { useEffect, useRef, useCallback, useMemo } from 'react'; import { FormHook, FieldConfig } from '../types'; @@ -53,7 +54,7 @@ export interface FormArrayField { */ export const UseArray = ({ path, - initialNumberOfItems, + initialNumberOfItems = 1, validations, readDefaultValueOnForm = true, children, @@ -92,6 +93,9 @@ export const UseArray = ({ // Create an internal hook field which behaves like any other form field except that it is not // outputed in the form data (when calling form.submit() or form.getFormData()) // This allow us to run custom validations (passed to the props) on the Array items + + const internalFieldPath = useMemo(() => `${path}__${uuid.v4()}`, [path]); + const fieldConfigBase: FieldConfig & InternalFieldConfig = { defaultValue: fieldDefaultValue, initialValue: fieldDefaultValue, @@ -103,7 +107,7 @@ export const UseArray = ({ ? { validations, ...fieldConfigBase } : fieldConfigBase; - const field = useField(form, path, fieldConfig); + const field = useField(form, internalFieldPath, fieldConfig); const { setValue, value, isChangingValue, errors } = field; // Derived state from the field diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx index cbf0d9d619636..36fd16209f5d4 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx @@ -26,41 +26,91 @@ describe('', () => { jest.useRealTimers(); }); - test('should read the default value from the prop and fallback to the config object', () => { - const onFormData = jest.fn(); + describe('defaultValue', () => { + test('should read the default value from the prop and fallback to the config object', () => { + const onFormData = jest.fn(); - const TestComp = ({ onData }: { onData: OnUpdateHandler }) => { - const { form } = useForm(); - const { subscribe } = form; + const TestComp = ({ onData }: { onData: OnUpdateHandler }) => { + const { form } = useForm(); + const { subscribe } = form; - useEffect(() => subscribe(onData).unsubscribe, [subscribe, onData]); + useEffect(() => subscribe(onData).unsubscribe, [subscribe, onData]); - return ( -
- - - - ); - }; + return ( +
+ + + + ); + }; + + const setup = registerTestBed(TestComp, { + defaultProps: { onData: onFormData }, + memoryRouter: { wrapComponent: false }, + }); - const setup = registerTestBed(TestComp, { - defaultProps: { onData: onFormData }, - memoryRouter: { wrapComponent: false }, + setup(); + + const [{ data }] = onFormData.mock.calls[ + onFormData.mock.calls.length - 1 + ] as Parameters; + + expect(data.internal).toEqual({ + name: 'John', + lastName: 'Snow', + }); }); - setup(); + test('should update the form.defaultValue when a field defaultValue is provided through prop', () => { + let formHook: FormHook | null = null; - const [{ data }] = onFormData.mock.calls[ - onFormData.mock.calls.length - 1 - ] as Parameters; + const TestComp = () => { + const [isFieldVisible, setIsFieldVisible] = useState(true); + const { form } = useForm(); + formHook = form; + + return ( +
+ {isFieldVisible && ( + <> + + + + + + + )} + + + ); + }; + + const setup = registerTestBed(TestComp, { + memoryRouter: { wrapComponent: false }, + }); + + const { find } = setup(); + + expect(formHook!.__getFormDefaultValue()).toEqual({ + name: 'John', + myArray: [ + { name: 'John', lastName: 'Snow' }, + { name: 'Foo', lastName: 'Bar' }, + ], + }); + + // Unmounts the field and make sure the form.defaultValue has been updated + act(() => { + find('unmountField').simulate('click'); + }); - expect(data.internal).toEqual({ - name: 'John', - lastName: 'Snow', + expect(formHook!.__getFormDefaultValue()).toEqual({}); }); }); @@ -205,7 +255,7 @@ describe('', () => { describe('validation', () => { let formHook: FormHook | null = null; - let fieldHook: FieldHook | null = null; + let fieldHook: FieldHook | null = null; beforeEach(() => { formHook = null; @@ -216,19 +266,24 @@ describe('', () => { formHook = form; }; - const onFieldHook = (field: FieldHook) => { + const onFieldHook = (field: FieldHook) => { fieldHook = field; }; - const getTestComp = (fieldConfig: FieldConfig) => { + const getTestComp = (fieldConfig?: FieldConfig) => { const TestComp = () => { - const { form } = useForm(); + const { form } = useForm(); const [isFieldActive, setIsFieldActive] = useState(true); + const [fieldPath, setFieldPath] = useState('name'); const unmountField = () => { setIsFieldActive(false); }; + const changeFieldPath = () => { + setFieldPath('newPath'); + }; + useEffect(() => { onFormHook(form); }, [form]); @@ -236,16 +291,12 @@ describe('', () => { return (
{isFieldActive && ( - + path={fieldPath} config={fieldConfig}> {(field) => { onFieldHook(field); return ( - + ); }} @@ -253,20 +304,23 @@ describe('', () => { + ); }; return TestComp; }; - const setup = (fieldConfig: FieldConfig) => { + const setup = (fieldConfig?: FieldConfig) => { return registerTestBed(getTestComp(fieldConfig), { memoryRouter: { wrapComponent: false }, })() as TestBed; }; test('should update the form validity whenever the field value changes', async () => { - const fieldConfig: FieldConfig = { + const fieldConfig: FieldConfig = { defaultValue: '', // empty string, which is not valid validations: [ { @@ -317,7 +371,7 @@ describe('', () => { }); test('should not update the state if the field has unmounted while validating', async () => { - const fieldConfig: FieldConfig = { + const fieldConfig: FieldConfig = { validations: [ { validator: () => { @@ -369,6 +423,40 @@ describe('', () => { console.error = originalConsoleError; // eslint-disable-line no-console }); + test('should not validate the field if the "path" changes but the value has not changed', async () => { + // This happens with the UseArray. When we delete an item from the array the path for + // the remaining items are recalculated and thus changed for every inside + // the array. We should not re-run the validation when adding/removing array items. + + const validator = jest.fn(); + const fieldConfig: FieldConfig = { + validations: [ + { + validator, + }, + ], + }; + + const { + find, + form: { setInputValue }, + } = setup(fieldConfig); + + await act(async () => { + setInputValue('myField', 'changedValue'); + }); + + expect(validator).toHaveBeenCalledTimes(1); + validator.mockReset(); + + await act(async () => { + // Change the field path + find('changeFieldPathBtn').simulate('click'); + }); + + expect(validator).not.toHaveBeenCalled(); + }); + describe('dynamic data', () => { let nameFieldHook: FieldHook | null = null; let lastNameFieldHook: FieldHook | null = null; @@ -708,32 +796,54 @@ describe('', () => { }); describe('change handlers', () => { + const onChange = jest.fn(); const onError = jest.fn(); beforeEach(() => { jest.resetAllMocks(); }); - const getTestComp = (fieldConfig: FieldConfig) => { + const getTestComp = (fieldConfig?: FieldConfig) => { const TestComp = () => { const { form } = useForm(); return (
- + ); }; return TestComp; }; - const setup = (fieldConfig: FieldConfig) => { + const setup = (fieldConfig?: FieldConfig) => { return registerTestBed(getTestComp(fieldConfig), { memoryRouter: { wrapComponent: false }, })() as TestBed; }; - it('calls onError when validation state changes', async () => { + test('calls onChange() prop when value state changes', async () => { + const { + form: { setInputValue }, + } = setup(); + + expect(onChange).toBeCalledTimes(0); + + await act(async () => { + setInputValue('myField', 'foo'); + }); + + expect(onChange).toBeCalledTimes(1); + expect(onChange).toBeCalledWith('foo'); + }); + + test('calls onError() prop when validation state changes', async () => { const { form: { setInputValue }, } = setup({ diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx index bc4e2ccf58294..7e216e3126ed8 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx @@ -128,11 +128,20 @@ function UseFieldComp(props: Props { + let needsCleanUp = false; + if (defaultValue !== undefined) { + needsCleanUp = true; // Update the form "defaultValue" ref object. // This allows us to reset the form and put back the defaultValue of each field __updateDefaultValueAt(path, defaultValue); } + + return () => { + if (needsCleanUp) { + __updateDefaultValueAt(path, undefined); + } + }; }, [path, defaultValue, __updateDefaultValueAt]); // Children prevails over anything else provided. diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts index f0c9c50c1033e..7ba06304b971b 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts @@ -26,6 +26,10 @@ export interface InternalFieldConfig { isIncludedInOutput?: boolean; } +const errorsToString = (errors: ValidationError[]): string[] | null => { + return errors.length ? errors.map((error) => error.message) : null; +}; + export const useField = ( form: FormHook, path: string, @@ -81,14 +85,13 @@ export const useField = ( const isMounted = useRef(false); const validateCounter = useRef(0); const changeCounter = useRef(0); - const hasBeenReset = useRef(false); const inflightValidation = useRef(null); const debounceTimeout = useRef(null); // Keep a ref of the last state (value and errors) notified to the consumer so they don't get // loads of updates whenever they don't wrap the "onChange()" and "onError()" handlers with a useCallback // e.g. { // inline code }} const lastNotifiedState = useRef<{ value?: I; errors: string[] | null }>({ - value: undefined, + value: initialValueDeserialized, errors: null, }); @@ -100,6 +103,9 @@ export const useField = ( [validations] ); + const valueHasChanged = value !== lastNotifiedState.current.value; + const errorsHaveChanged = lastNotifiedState.current.errors !== errorsToString(errors); + // ---------------------------------- // -- HELPERS // ---------------------------------- @@ -519,8 +525,8 @@ export const useField = ( setStateErrors([]); if (resetValue) { - hasBeenReset.current = true; const newValue = deserializeValue(updatedDefaultValue ?? defaultValue); + lastNotifiedState.current.value = newValue; setValue(newValue); return newValue; } @@ -604,36 +610,29 @@ export const useField = ( // might not be wrapped inside a "useCallback" and that would trigger a possible infinite // amount of effect executions. useEffect(() => { - if (!isMounted.current) { + if (!isMounted.current || value === undefined) { return; } - if (valueChangeListener && value !== lastNotifiedState.current.value) { + if (valueChangeListener && valueHasChanged) { valueChangeListener(value); - lastNotifiedState.current.value = value; } - }, [value, valueChangeListener]); + }, [value, valueHasChanged, valueChangeListener]); // Value change: update state and run validations useEffect(() => { - if (!isMounted.current) { + if (!isMounted.current || !valueHasChanged) { return; } - if (hasBeenReset.current) { - // If the field value has just been reset (triggering this useEffect) - // we don't want to set the "isPristine" state to true and validate the field - hasBeenReset.current = false; - } else { - setPristine(false); - setIsChangingValue(true); - - runValidationsOnValueChange(() => { - if (isMounted.current) { - setIsChangingValue(false); - } - }); - } + setPristine(false); + setIsChangingValue(true); + + runValidationsOnValueChange(() => { + if (isMounted.current) { + setIsChangingValue(false); + } + }); return () => { if (debounceTimeout.current) { @@ -641,7 +640,7 @@ export const useField = ( debounceTimeout.current = null; } }; - }, [value, runValidationsOnValueChange]); + }, [valueHasChanged, runValidationsOnValueChange]); // Value change: set "isModified" state useEffect(() => { @@ -659,13 +658,18 @@ export const useField = ( return; } - const errorMessages = errors.length ? errors.map((error) => error.message) : null; - - if (errorChangeListener && lastNotifiedState.current.errors !== errorMessages) { - errorChangeListener(errorMessages); - lastNotifiedState.current.errors = errorMessages; + if (errorChangeListener && errorsHaveChanged) { + errorChangeListener(errorsToString(errors)); } - }, [errors, errorChangeListener]); + }, [errors, errorsHaveChanged, errorChangeListener]); + + useEffect(() => { + lastNotifiedState.current.value = value; + }, [value]); + + useEffect(() => { + lastNotifiedState.current.errors = errorsToString(errors); + }, [errors]); useEffect(() => { isMounted.current = true; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts index 2160c09ef720e..3966f9cc61a70 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts @@ -11,7 +11,7 @@ import { get } from 'lodash'; import { set } from '@elastic/safer-lodash-set'; import { FormHook, FieldHook, FormData, FieldsMap, FormConfig } from '../types'; -import { mapFormFields, unflattenObject, Subject, Subscription } from '../lib'; +import { mapFormFields, unflattenObject, flattenObject, Subject, Subscription } from '../lib'; const DEFAULT_OPTIONS = { valueChangeDebounceTime: 500, @@ -205,7 +205,18 @@ export function useForm( if (defaultValueDeserialized.current === undefined) { defaultValueDeserialized.current = {} as I; } - set(defaultValueDeserialized.current!, path, value); + + // We allow "undefined" to be passed to be able to remove a value from the form `defaultValue` object. + // When mounts it calls `updateDefaultValueAt("foo", "bar")` to + // update the form "defaultValue" object. When that component unmounts we want to be able to clean up and + // remove its defaultValue on the form. + if (value === undefined) { + const updated = flattenObject(defaultValueDeserialized.current!); + delete updated[path]; + defaultValueDeserialized.current = unflattenObject(updated); + } else { + set(defaultValueDeserialized.current!, path, value); + } }, [] ); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.test.tsx index dc89cfe4f1fb6..7c0cd960999e8 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.test.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.test.tsx @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { act } from 'react-dom/test-utils'; import { registerTestBed } from '../shared_imports'; @@ -36,8 +36,10 @@ describe('useFormIsModified()', () => { const [isNameVisible, setIsNameVisible] = useState(true); const [isLastNameVisible, setIsLastNameVisible] = useState(true); - // Call our jest.spy() with the latest hook value - onIsModifiedChange(isModified); + useEffect(() => { + // Call our jest.spy() with the latest hook value + onIsModifiedChange(isModified); + }, [onIsModifiedChange, isModified]); return (
diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.ts index 08f5eaf76a083..e5e0fd6d61472 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_is_modified.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { get } from 'lodash'; import { FieldHook, FormHook } from '../types'; @@ -36,6 +36,8 @@ export const useFormIsModified = ({ form: formFromOptions, discard: fieldPathsToDiscard = [], }: Options = {}): boolean => { + const [isFormModified, setIsFormModified] = useState(false); + // Hook calls can not be conditional we first try to access the form through context let form = useFormContext({ throwIfNotFound: false }); @@ -76,28 +78,34 @@ export const useFormIsModified = ({ ? ([path]: [string, FieldHook]) => fieldsToDiscard[path] !== true : () => true; + // Calculate next state value // 1. Check if any field has been modified - let isModified = Object.entries(getFields()) + let nextIsModified = Object.entries(getFields()) .filter(isFieldIncluded) .some(([_, field]) => field.isModified); - if (isModified) { - return isModified; - } + if (!nextIsModified) { + // 2. Check if any field has been removed. + // If somme field has been removed **and** they were originaly present on the + // form "defaultValue" then the form has been modified. + const formDefaultValue = __getFormDefaultValue(); + const fieldOnFormDefaultValue = (path: string) => Boolean(get(formDefaultValue, path)); - // 2. Check if any field has been removed. - // If somme field has been removed **and** they were originaly present on the - // form "defaultValue" then the form has been modified. - const formDefaultValue = __getFormDefaultValue(); - const fieldOnFormDefaultValue = (path: string) => Boolean(get(formDefaultValue, path)); + const fieldsRemovedFromDOM: string[] = fieldsToDiscard + ? Object.keys(__getFieldsRemoved()) + .filter((path) => fieldsToDiscard[path] !== true) + .filter(fieldOnFormDefaultValue) + : Object.keys(__getFieldsRemoved()).filter(fieldOnFormDefaultValue); - const fieldsRemovedFromDOM: string[] = fieldsToDiscard - ? Object.keys(__getFieldsRemoved()) - .filter((path) => fieldsToDiscard[path] !== true) - .filter(fieldOnFormDefaultValue) - : Object.keys(__getFieldsRemoved()).filter(fieldOnFormDefaultValue); + nextIsModified = fieldsRemovedFromDOM.length > 0; + } - isModified = fieldsRemovedFromDOM.length > 0; + // Update the state **only** if it has changed to avoid creating an infinite re-render + if (nextIsModified && !isFormModified) { + setIsFormModified(true); + } else if (!nextIsModified && isFormModified) { + setIsFormModified(false); + } - return isModified; + return isFormModified; }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/index.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/index.ts index 0bbaedcf2e90e..b65dc0570acba 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/index.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/index.ts @@ -7,5 +7,7 @@ */ export type { Subscription } from './subject'; + export { Subject } from './subject'; -export * from './utils'; + +export { flattenObject, unflattenObject, mapFormFields } from './utils'; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.test.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.test.ts new file mode 100644 index 0000000000000..f7d7429889eb2 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { flattenObject } from './utils'; + +describe('Form lib utils', () => { + describe('flattenObject', () => { + test('should flatten an object', () => { + const obj = { + a: true, + b: { + foo: 'bar', + baz: [ + { + a: false, + b: 'foo', + }, + 'bar', + true, + [1, 2, { 3: false }], + ], + }, + }; + + expect(flattenObject(obj)).toEqual({ + a: true, + 'b.baz[0].a': false, + 'b.baz[0].b': 'foo', + 'b.baz[1]': 'bar', + 'b.baz[2]': true, + 'b.foo': 'bar', + 'b.baz[3][0]': 1, + 'b.baz[3][1]': 2, + 'b.baz[3][2].3': false, + }); + }); + }); +}); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts index 9d8801b1448c0..8df6506ec2e7b 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/lib/utils.ts @@ -9,12 +9,53 @@ import { set } from '@elastic/safer-lodash-set'; import { FieldHook } from '../types'; -export const unflattenObject = (object: object): T => +interface GenericObject { + [key: string]: any; +} + +export const unflattenObject = (object: object): T => Object.entries(object).reduce((acc, [key, value]) => { set(acc, key, value); return acc; }, {} as T); +/** + * Wrap the key with [] if it is a key from an Array + * @param key The object key + * @param isArrayItem Flag to indicate if it is the key of an Array + */ +const renderKey = (key: string, isArrayItem: boolean): string => (isArrayItem ? `[${key}]` : key); + +export const flattenObject = ( + obj: GenericObject, + prefix: string[] = [], + isArrayItem = false +): GenericObject => + Object.keys(obj).reduce((acc, k) => { + const nextValue = obj[k]; + + if (typeof nextValue === 'object' && nextValue !== null) { + const isNextValueArray = Array.isArray(nextValue); + const dotSuffix = isNextValueArray ? '' : '.'; + + if (Object.keys(nextValue).length > 0) { + return { + ...acc, + ...flattenObject( + nextValue, + [...prefix, `${renderKey(k, isArrayItem)}${dotSuffix}`], + isNextValueArray + ), + }; + } + } + + const fullPath = `${prefix.join('')}${renderKey(k, isArrayItem)}`; + acc[fullPath] = nextValue; + + return acc; + }, {}); + /** * Helper to map the object of fields to any of its value * From c2003d0663341579f533a0be3d7be48e834567c2 Mon Sep 17 00:00:00 2001 From: Or Ouziel Date: Tue, 12 Apr 2022 15:44:57 +0300 Subject: [PATCH 07/15] [Cloud Posture] add findings framework sources icons (#129883) --- .../public/assets/icons/cis_logo.svg | 25 +++++++++++++++++++ .../public/assets/icons/k8s_logo.svg | 7 ++++++ .../public/pages/findings/findings_flyout.tsx | 15 ++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/cloud_security_posture/public/assets/icons/cis_logo.svg create mode 100644 x-pack/plugins/cloud_security_posture/public/assets/icons/k8s_logo.svg diff --git a/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_logo.svg b/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_logo.svg new file mode 100644 index 0000000000000..c5e4849425d8a --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_logo.svg @@ -0,0 +1,25 @@ + + Logos/CIS/CIS_logo_no-tag_stacked_large + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/x-pack/plugins/cloud_security_posture/public/assets/icons/k8s_logo.svg b/x-pack/plugins/cloud_security_posture/public/assets/icons/k8s_logo.svg new file mode 100644 index 0000000000000..1949c06d51520 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/assets/icons/k8s_logo.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout.tsx index f53d76b82c177..65493bd493342 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout.tsx @@ -21,12 +21,15 @@ import { EuiFlexGrid, EuiCard, EuiFlexGroup, + EuiIcon, type PropsOf, } from '@elastic/eui'; import { assertNever } from '@kbn/std'; import type { CspFinding } from './types'; import { CspEvaluationBadge } from '../../components/csp_evaluation_badge'; import * as TEXT from './translations'; +import cisLogoIcon from '../../assets/icons/cis_logo.svg'; +import k8sLogoIcon from '../../assets/icons/k8s_logo.svg'; const tabs = ['remediation', 'resource', 'general'] as const; @@ -163,7 +166,17 @@ const getGeneralCards = ({ rule }: CspFinding): Card[] => [ [TEXT.SEVERITY, ''], [TEXT.INDEX, ''], [TEXT.RULE_EVALUATED_AT, ''], - [TEXT.FRAMEWORK_SOURCES, ''], + [ + TEXT.FRAMEWORK_SOURCES, + + + + + + + + , + ], [TEXT.SECTION, ''], [TEXT.PROFILE_APPLICABILITY, ''], [TEXT.AUDIT, ''], From bced9d2bd47cb74e047cec93463e313880309332 Mon Sep 17 00:00:00 2001 From: Karl Godard Date: Tue, 12 Apr 2022 07:11:07 -0700 Subject: [PATCH 08/15] [Session View] [8.2] beta label added to sessions tabs in timeline (#129965) * beta label added to sessions tabs in timeline * added test for isBeta * added test for isBeta * test revised Co-authored-by: mitodrummer --- .../navigation/tab_navigation/index.test.tsx | 18 ++++++++++++++++++ .../navigation/tab_navigation/index.tsx | 6 +++++- .../navigation/tab_navigation/types.ts | 1 + .../common/components/navigation/types.ts | 1 + .../public/common/translations.ts | 4 ++++ .../public/hosts/pages/nav_tabs.tsx | 1 + .../components/timeline/tabs_content/index.tsx | 4 +++- 7 files changed, 33 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx index d90709f69ee03..45eebab8c093f 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx @@ -126,4 +126,22 @@ describe('Table Navigation', () => { `/app/securitySolutionUI/hosts/siem-window/authentications${SEARCH_QUERY}` ); }); + + test('it renders a EuiBetaBadge only on the sessions tab', () => { + Object.keys(HostsTableType).forEach((tableType) => { + if (tableType !== HostsTableType.sessions) { + const wrapper = mount(); + + const betaBadge = wrapper.find( + `EuiTab[data-test-subj="navigation-${tableType}"] EuiBetaBadge` + ); + + if (tableType === HostsTableType.sessions) { + expect(betaBadge).toBeTruthy(); + } else { + expect(betaBadge).toEqual({}); + } + } + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx index 4d9a8a704dde5..03437bab93f38 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiTab, EuiTabs } from '@elastic/eui'; +import { EuiTab, EuiTabs, EuiBetaBadge } from '@elastic/eui'; import { getOr } from 'lodash/fp'; import React, { useEffect, useState, useCallback, useMemo } from 'react'; import { useLocation } from 'react-router-dom'; @@ -14,6 +14,7 @@ import deepEqual from 'fast-deep-equal'; import { useNavigation } from '../../../lib/kibana'; import { track, METRIC_TYPE, TELEMETRY_EVENT } from '../../../lib/telemetry'; import { TabNavigationProps, TabNavigationItemProps } from './types'; +import { BETA } from '../../../translations'; const TabNavigationItemComponent = ({ disabled, @@ -21,6 +22,7 @@ const TabNavigationItemComponent = ({ id, name, isSelected, + isBeta, }: TabNavigationItemProps) => { const { getAppUrl, navigateTo } = useNavigation(); @@ -45,6 +47,7 @@ const TabNavigationItemComponent = ({ isSelected={isSelected} href={appHref} onClick={handleClick} + append={isBeta && } > {name} @@ -92,6 +95,7 @@ export const TabNavigationComponent: React.FC = ({ name={tab.name} disabled={tab.disabled} isSelected={isSelected} + isBeta={tab.isBeta} /> ); }), diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts index 75f18abf75559..5630978bae87a 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts @@ -32,4 +32,5 @@ export interface TabNavigationItemProps { disabled: boolean; name: string; isSelected: boolean; + isBeta?: boolean; } diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts index b1903ef869d3d..1cb8a918ea481 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts @@ -38,6 +38,7 @@ export interface NavTab { disabled: boolean; urlKey?: UrlStateType; pageId?: SecurityPageName; + isBeta?: boolean; } export type SecurityNavKey = diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 2058eaf03b5e1..64d31e7f6530d 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -63,6 +63,10 @@ export const EMPTY_ACTION_ENDPOINT_DESCRIPTION = i18n.translate( } ); +export const BETA = i18n.translate('xpack.securitySolution.pages.common.beta', { + defaultMessage: 'Beta', +}); + export const UPDATE_ALERT_STATUS_FAILED = (conflicts: number) => i18n.translate('xpack.securitySolution.pages.common.updateAlertStatusFailed', { values: { conflicts }, diff --git a/x-pack/plugins/security_solution/public/hosts/pages/nav_tabs.tsx b/x-pack/plugins/security_solution/public/hosts/pages/nav_tabs.tsx index 59fb0d08f7dc7..ea46180f8df80 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/nav_tabs.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/nav_tabs.tsx @@ -71,6 +71,7 @@ export const navTabsHosts = ({ name: i18n.NAVIGATION_SESSIONS_TITLE, href: getTabsOnHostsUrl(HostsTableType.sessions), disabled: false, + isBeta: true, }, }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx index 2f5262c7c598f..b8b9d73932afd 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiBadge, EuiLoadingContent, EuiTabs, EuiTab } from '@elastic/eui'; +import { EuiBadge, EuiBetaBadge, EuiLoadingContent, EuiTabs, EuiTab } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import React, { lazy, memo, Suspense, useCallback, useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; @@ -37,6 +37,7 @@ import { getEventIdToNoteIdsSelector, } from './selectors'; import * as i18n from './translations'; +import { BETA } from '../../../../common/translations'; const HideShowContainer = styled.div.attrs<{ $isVisible: boolean; isOverflowYScroll: boolean }>( ({ $isVisible = false, isOverflowYScroll = false }) => ({ @@ -357,6 +358,7 @@ const TabsContentComponent: React.FC = ({ isSelected={activeTab === TimelineTabs.session} disabled={sessionViewConfig === null} key={TimelineTabs.session} + append={} > {i18n.SESSION_TAB} From e2ba9f19e35c43e0852f23a05e2ee4c9ba7561ba Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 12 Apr 2022 16:57:04 +0200 Subject: [PATCH 09/15] unskips and refactors alert details for unmapped fields tests (#130002) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../detection_alerts/alerts_details.spec.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts index 3e9adc9e66b44..e3612a9a125c9 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts @@ -31,8 +31,6 @@ describe('Alert details with unmapped fields', () => { esArchiverLoad('unmapped_fields'); login(); createCustomRuleEnabled(getUnmappedRule()); - }); - beforeEach(() => { visitWithoutDateRange(ALERTS_URL); waitForAlertsToPopulate(); expandFirstAlert(); @@ -52,10 +50,8 @@ describe('Alert details with unmapped fields', () => { }); }); - // This test needs to be updated to not look for the field in a specific row, as it prevents us from adding/removing fields - it.skip('Displays the unmapped field on the table', () => { + it('Displays the unmapped field on the table', () => { const expectedUnmmappedField = { - row: 83, field: 'unmapped', text: 'This is the unmapped field', }; @@ -63,10 +59,9 @@ describe('Alert details with unmapped fields', () => { openTable(); cy.get(ALERT_FLYOUT) .find(TABLE_ROWS) - .eq(expectedUnmmappedField.row) .within(() => { - cy.get(CELL_TEXT).eq(2).should('have.text', expectedUnmmappedField.field); - cy.get(CELL_TEXT).eq(4).should('have.text', expectedUnmmappedField.text); + cy.get(CELL_TEXT).should('contain', expectedUnmmappedField.field); + cy.get(CELL_TEXT).should('contain', expectedUnmmappedField.text); }); }); From 294fe2b93254d02ec21dd33cef91452ff007d9c3 Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Tue, 12 Apr 2022 10:15:17 -0500 Subject: [PATCH 10/15] [DOCS] Adds docs for URL drilldown support (#129666) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/user/dashboard/make-dashboards-interactive.asciidoc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/user/dashboard/make-dashboards-interactive.asciidoc b/docs/user/dashboard/make-dashboards-interactive.asciidoc index 2cb750afbe7d5..06c6675bedba3 100644 --- a/docs/user/dashboard/make-dashboards-interactive.asciidoc +++ b/docs/user/dashboard/make-dashboards-interactive.asciidoc @@ -196,7 +196,7 @@ image::images/drilldown_on_panel.png[Drilldown on data table that navigates to a [[url-drilldowns]] ==== Create URL drilldowns -URL drilldowns enable you to navigate from a dashboard to external websites. Destination URLs can be dynamic, depending on the dashboard context or user interaction with a panel. To create URL drilldowns, you add <> to a URL template, which configures the behavior of the drilldown. +URL drilldowns enable you to navigate from a dashboard to external websites. Destination URLs can be dynamic, depending on the dashboard context or user interaction with a panel. To create URL drilldowns, you add <> to a URL template, which configures the behavior of the drilldown. All panels that you create with the visualization editors support dashboard drilldowns. [role="screenshot"] image:images/url_drilldown_go_to_github.gif[Drilldown on pie chart that navigates to Github] @@ -210,13 +210,6 @@ The <> you use to create a < Date: Tue, 12 Apr 2022 17:36:12 +0200 Subject: [PATCH 11/15] [ILM] Fixed snapshot repositories and policies routes (#129200) * [ILM] Fixed snapshot repositories and policies routes * [ILM] Updated console.log to error Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../snapshot_policies/register_fetch_route.ts | 12 +--- .../register_fetch_route.ts | 2 +- .../{constants.js => constants.ts} | 2 + .../index_lifecycle_management/index.js | 2 + .../snapshot_policies.helpers.ts | 50 +++++++++++++++ .../snapshot_policies.ts | 45 +++++++++++++ .../snapshot_repositories.helpers.ts | 55 ++++++++++++++++ .../snapshot_repositories.ts | 63 +++++++++++++++++++ 8 files changed, 220 insertions(+), 11 deletions(-) rename x-pack/test/api_integration/apis/management/index_lifecycle_management/{constants.js => constants.ts} (84%) create mode 100644 x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.helpers.ts create mode 100644 x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.ts create mode 100644 x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.helpers.ts create mode 100644 x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.ts diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_policies/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_policies/register_fetch_route.ts index 6003ddf712a70..ebe8a2388a025 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_policies/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_policies/register_fetch_route.ts @@ -5,24 +5,16 @@ * 2.0. */ -import { ElasticsearchClient } from 'kibana/server'; - import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; -async function fetchSnapshotPolicies(client: ElasticsearchClient): Promise { - const response = await client.slm.getLifecycle(); - return response.body; -} - export function registerFetchRoute({ router, license, lib: { handleEsError } }: RouteDependencies) { router.get( { path: addBasePath('/snapshot_policies'), validate: false }, license.guardApiRoute(async (context, request, response) => { try { - const policiesByName = await fetchSnapshotPolicies( - context.core.elasticsearch.client.asCurrentUser - ); + const policiesByName = + await context.core.elasticsearch.client.asCurrentUser.slm.getLifecycle(); return response.ok({ body: Object.keys(policiesByName) }); } catch (error) { return handleEsError({ error, response }); diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts index 8787be8e936ba..a4bdbd5fc7afc 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts @@ -32,7 +32,7 @@ export const registerFetchRoute = ({ router, license }: RouteDependencies) => { name: '*', }); const repos: ListSnapshotReposResponse = { - repositories: Object.keys(esResult.body), + repositories: Object.keys(esResult), }; return response.ok({ body: repos }); } catch (e) { diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/constants.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/constants.ts similarity index 84% rename from x-pack/test/api_integration/apis/management/index_lifecycle_management/constants.js rename to x-pack/test/api_integration/apis/management/index_lifecycle_management/constants.ts index a907737fca125..b2ae24d03b990 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/constants.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/constants.ts @@ -10,3 +10,5 @@ export const DEFAULT_POLICY_NAME = 'watch-history-ilm-policy'; export const INDEX_TEMPLATE_NAME = 'api-integration-tests-template'; export const INDEX_TEMPLATE_PATTERN_PREFIX = 'api_integration_tests_'; export const NODE_CUSTOM_ATTRIBUTE = 'name:apiIntegrationTestNode'; +export const SNAPSHOT_REPOSITORY_NAME = 'test_repo'; +export const CLOUD_REPOSITORY_NAME = 'found-snapshots'; diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/index.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/index.js index 164ca6634a28a..1e9cb006f1663 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/index.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/index.js @@ -11,5 +11,7 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./templates')); loadTestFile(require.resolve('./indices')); loadTestFile(require.resolve('./nodes')); + loadTestFile(require.resolve('./snapshot_policies')); + loadTestFile(require.resolve('./snapshot_repositories')); }); } diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.helpers.ts b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.helpers.ts new file mode 100644 index 0000000000000..80c1794d675a6 --- /dev/null +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.helpers.ts @@ -0,0 +1,50 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; +import { API_BASE_PATH, SNAPSHOT_REPOSITORY_NAME } from './constants'; + +export const registerSnapshotPoliciesHelpers = (getService: FtrProviderContext['getService']) => { + const supertest = getService('supertest'); + const es = getService('es'); + + let policiesCreated: string[] = []; + + const loadSnapshotPolicies = () => supertest.get(`${API_BASE_PATH}/snapshot_policies`); + + const createSnapshotPolicy = (policyName: string, repositoryName?: string) => { + return es.slm + .putLifecycle({ + policy_id: policyName, + config: { + indices: 'test_index', + }, + name: policyName, + repository: repositoryName ?? SNAPSHOT_REPOSITORY_NAME, + schedule: '0 30 1 * * ?', + }) + .then(() => policiesCreated.push(policyName)); + }; + + const deletePolicy = (policyName: string) => es.slm.deleteLifecycle({ policy_id: policyName }); + + const cleanupPolicies = () => + Promise.all(policiesCreated.map(deletePolicy)) + .then(() => { + policiesCreated = []; + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.error(`[Cleanup error] Error deleting ES resources: ${err.message}`); + }); + + return { + loadSnapshotPolicies, + createSnapshotPolicy, + cleanupPolicies, + }; +}; diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.ts b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.ts new file mode 100644 index 0000000000000..2bfd0f0a3f56f --- /dev/null +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_policies.ts @@ -0,0 +1,45 @@ +/* + * 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'; +import { registerSnapshotPoliciesHelpers } from './snapshot_policies.helpers'; +import { registerSnapshotRepositoriesHelpers } from './snapshot_repositories.helpers'; +import { SNAPSHOT_REPOSITORY_NAME } from './constants'; + +const snapshotPolicyName = 'test_snapshot_policy'; +export default function ({ getService }: FtrProviderContext) { + const deployment = getService('deployment'); + + const { loadSnapshotPolicies, createSnapshotPolicy, cleanupPolicies } = + registerSnapshotPoliciesHelpers(getService); + + const { createSnapshotRepository, cleanupRepositories } = + registerSnapshotRepositoriesHelpers(getService); + + describe('snapshot policies', () => { + before(async () => Promise.all([cleanupPolicies(), cleanupRepositories()])); + after(async () => Promise.all([cleanupPolicies(), cleanupRepositories()])); + + it('returns empty array if no policies', async () => { + const { body } = await loadSnapshotPolicies().expect(200); + expect(body).to.eql([]); + }); + + it('returns policies', async () => { + const isCloud = await deployment.isCloud(); + if (!isCloud) { + await createSnapshotRepository(SNAPSHOT_REPOSITORY_NAME); + } + await createSnapshotPolicy(snapshotPolicyName); + const { body } = await loadSnapshotPolicies().expect(200); + + expect(body).to.have.length(1); + expect(body[0]).to.eql(snapshotPolicyName); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.helpers.ts b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.helpers.ts new file mode 100644 index 0000000000000..9d30d36b24917 --- /dev/null +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.helpers.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { API_BASE_PATH } from './constants'; + +export const registerSnapshotRepositoriesHelpers = ( + getService: FtrProviderContext['getService'] +) => { + const supertest = getService('supertest'); + const es = getService('es'); + + let repositoriesCreated: string[] = []; + + const loadSnapshotRepositories = () => supertest.get(`${API_BASE_PATH}/snapshot_repositories`); + + const createSnapshotRepository = (repositoryName: string) => { + return es.snapshot + .createRepository({ + name: repositoryName, + body: { + type: 'fs', + settings: { + location: '/tmp/repo', + }, + }, + verify: false, + }) + .then(() => repositoriesCreated.push(repositoryName)); + }; + + const deleteRepository = (repositoryName: string) => { + return es.snapshot.deleteRepository({ name: repositoryName }); + }; + + const cleanupRepositories = () => + Promise.all(repositoriesCreated.map(deleteRepository)) + .then(() => { + repositoriesCreated = []; + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.error(`[Cleanup error] Error deleting ES resources: ${err.message}`); + }); + + return { + loadSnapshotRepositories, + createSnapshotRepository, + cleanupRepositories, + }; +}; diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.ts b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.ts new file mode 100644 index 0000000000000..bc1acfd9a5a07 --- /dev/null +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/snapshot_repositories.ts @@ -0,0 +1,63 @@ +/* + * 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'; +import { registerSnapshotRepositoriesHelpers } from './snapshot_repositories.helpers'; +import { CLOUD_REPOSITORY_NAME } from './constants'; + +const repositoryName = 'test_repository'; + +export default function ({ getService }: FtrProviderContext) { + const deployment = getService('deployment'); + let isCloud: boolean; + + const { loadSnapshotRepositories, createSnapshotRepository, cleanupRepositories } = + registerSnapshotRepositoriesHelpers(getService); + + describe('snapshot repositories', () => { + before(async () => { + isCloud = await deployment.isCloud(); + await Promise.all([cleanupRepositories()]); + }); + after(async () => Promise.all([cleanupRepositories()])); + + it('returns empty array if no repositories ', async () => { + const { + body: { repositories }, + } = await loadSnapshotRepositories().expect(200); + if (!isCloud) { + expect(repositories).to.eql([]); + } + }); + + it('returns cloud default repository if on Cloud', async () => { + const { + body: { repositories }, + } = await loadSnapshotRepositories().expect(200); + if (isCloud) { + expect(repositories).to.have.length(1); + expect(repositories).to.eql([CLOUD_REPOSITORY_NAME]); + } + }); + + it('returns repositories', async () => { + await createSnapshotRepository(repositoryName); + const { + body: { repositories }, + } = await loadSnapshotRepositories().expect(200); + + if (isCloud) { + expect(repositories).to.have.length(2); + expect(repositories[0]).to.contain(repositoryName); + } else { + expect(repositories).to.have.length(1); + expect(repositories[0]).to.eql(repositoryName); + } + }); + }); +} From a395f411b7e717c612d714f0fcee874eaba9cfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Tue, 12 Apr 2022 11:40:51 -0400 Subject: [PATCH 12/15] [APM] Service environment should be selected when you edit the agent configuration (#129929) * fixing env selected * lets see if it works now * fixing test --- .../settings/agent_configurations.spec.ts | 106 ++++++++++++++++++ .../service_page/form_row_select.tsx | 24 ++-- .../form_row_suggestions_select.tsx | 3 + .../service_page/service_page.tsx | 2 + 4 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts new file mode 100644 index 0000000000000..61749461bdbda --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts @@ -0,0 +1,106 @@ +/* + * 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 { apm, timerange } from '@elastic/apm-synthtrace'; +import url from 'url'; +import { synthtrace } from '../../../../synthtrace'; + +const timeRange = { + rangeFrom: '2021-10-10T00:00:00.000Z', + rangeTo: '2021-10-10T00:15:00.000Z', +}; + +const agentConfigHref = url.format({ + pathname: '/app/apm/settings/agent-configuration', +}); + +function generateData({ + from, + to, + serviceName, +}: { + from: number; + to: number; + serviceName: string; +}) { + const range = timerange(from, to); + + const service1 = apm + .service(serviceName, 'production', 'java') + .instance('service-1-prod-1') + .podId('service-1-prod-1-pod'); + + const service2 = apm + .service(serviceName, 'development', 'nodejs') + .instance('opbeans-node-prod-1'); + + return range + .interval('1m') + .rate(1) + .spans((timestamp, index) => [ + ...service1 + .transaction('GET /apple 🍎 ') + .timestamp(timestamp) + .duration(1000) + .success() + .serialize(), + ...service2 + .transaction('GET /banana 🍌') + .timestamp(timestamp) + .duration(500) + .success() + .serialize(), + ]); +} + +describe('Agent configuration', () => { + before(async () => { + const { rangeFrom, rangeTo } = timeRange; + + await synthtrace.index( + generateData({ + from: new Date(rangeFrom).getTime(), + to: new Date(rangeTo).getTime(), + serviceName: 'opbeans-node', + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + + beforeEach(() => { + cy.loginAsPowerUser(); + cy.visit(agentConfigHref); + }); + + it('persists service enviroment when clicking on edit button', () => { + cy.intercept( + 'GET', + '/api/apm/settings/agent-configuration/environments?*' + ).as('serviceEnvironmentApi'); + cy.contains('Create configuration').click(); + cy.get('[data-test-subj="serviceNameComboBox"]') + .click() + .type('opbeans-node') + .type('{enter}'); + + cy.contains('opbeans-node').realClick(); + cy.wait('@serviceEnvironmentApi'); + + cy.get('[data-test-subj="serviceEnviromentComboBox"]') + .click({ force: true }) + .type('prod') + .type('{enter}'); + cy.contains('production').realClick(); + cy.contains('Next step').click(); + cy.contains('Create configuration'); + cy.contains('Edit').click(); + cy.wait('@serviceEnvironmentApi'); + cy.contains('production'); + }); +}); diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_select.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_select.tsx index be716042a63ce..bfde04af12b94 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_select.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_select.tsx @@ -5,14 +5,14 @@ * 2.0. */ -import React, { useState, useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; import { - EuiDescribedFormGroup, + EuiComboBox, EuiComboBoxOptionOption, + EuiDescribedFormGroup, EuiFormRow, - EuiComboBox, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { useMemo } from 'react'; interface Props { title: string; description: string; @@ -22,6 +22,7 @@ interface Props { isDisabled: boolean; value?: string; onChange: (value?: string) => void; + dataTestSubj?: string; } export function FormRowSelect({ @@ -32,23 +33,21 @@ export function FormRowSelect({ options, isDisabled, onChange, + value, + dataTestSubj, }: Props) { - const [selectedOptions, setSelected] = useState< - Array> | undefined - >([]); + const selectedOptions = useMemo(() => { + const optionFound = options?.find((option) => option.value === value); + return optionFound ? [optionFound] : undefined; + }, [options, value]); const handleOnChange = ( nextSelectedOptions: Array> ) => { const [selectedOption] = nextSelectedOptions; - setSelected(nextSelectedOptions); onChange(selectedOption.value); }; - useEffect(() => { - setSelected(undefined); - }, [isLoading]); - return ( diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx index f3f680ff4a9ff..5fa3a46b00901 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/form_row_suggestions_select.tsx @@ -19,6 +19,7 @@ interface Props { value?: string; allowAll?: boolean; onChange: (value?: string) => void; + dataTestSubj?: string; } export function FormRowSuggestionsSelect({ @@ -29,6 +30,7 @@ export function FormRowSuggestionsSelect({ value, allowAll = true, onChange, + dataTestSubj, }: Props) { return ( diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx index 9f8d3ca1318b5..1ede5cd5405c7 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/service_page/service_page.tsx @@ -105,6 +105,7 @@ export function ServicePage({ newConfig, setNewConfig, onClickNext }: Props) { service: { name, environment: '' }, })); }} + dataTestSubj="serviceNameComboBox" /> {/* Environment options */} From 33b0578a1748e0b6520c95a05387e0183baff3b1 Mon Sep 17 00:00:00 2001 From: Madison Caldwell Date: Tue, 12 Apr 2022 11:57:44 -0400 Subject: [PATCH 13/15] [Security Solution] Add fixtures for 7.17, 8.0, and 8.1 (#129768) * Add fixtures for 7.17, 8.0, and 8.1 * Compress fixtures --- .../security_solution/alerts/7.16.0/data.json | 3590 ---------- .../alerts/7.16.0/data.json.gz | Bin 0 -> 4755 bytes .../alerts/7.16.0/mappings.json | 5819 ----------------- .../alerts/7.16.0/mappings.json.gz | Bin 0 -> 9745 bytes .../alerts/7.17.0/data.json.gz | Bin 0 -> 4744 bytes .../alerts/7.17.0/mappings.json.gz | Bin 0 -> 9846 bytes .../alerts/8.0.0/data.json.gz | Bin 0 -> 9231 bytes .../alerts/8.0.0/mappings.json.gz | Bin 0 -> 9711 bytes .../alerts/8.1.0/data.json.gz | Bin 0 -> 9500 bytes .../alerts/8.1.0/mappings.json.gz | Bin 0 -> 9739 bytes 10 files changed, 9409 deletions(-) delete mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json.gz delete mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/mappings.json create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/mappings.json.gz create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.17.0/data.json.gz create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.17.0/mappings.json.gz create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/8.0.0/data.json.gz create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/8.0.0/mappings.json.gz create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/8.1.0/data.json.gz create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/8.1.0/mappings.json.gz diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json b/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json deleted file mode 100644 index 9f15ea353570e..0000000000000 --- a/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json +++ /dev/null @@ -1,3590 +0,0 @@ -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "0bb0c0d5488d757907f6be6e4c27ff698666948e2cf01d53e8fa43958b36c6a8", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:32.045Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.493Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-1", - "field": "host.name", - "id": "M2yvt38BIyEvspK01XQt", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "P2yvt38BIyEvspK05HSe", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "P2yvt38BIyEvspK05HSe", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-1 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "P2yvt38BIyEvspK05HSe", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:32.045Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:32.045Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "0dd11069ba6c63ec60ac902d6fb0a8a52c4f5ab20f03babe7b861c6d34431bad", - "source": { - "agent": { - "name": "security-linux-3.example.dev", - "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-3", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.196", - "name": "security-linux-3", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.654Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.495Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-3", - "field": "host.name", - "id": "NWyvt38BIyEvspK013R3", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "Pmyvt38BIyEvspK043Ri", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "Pmyvt38BIyEvspK043Ri", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-3 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "Pmyvt38BIyEvspK043Ri", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.654Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.654Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "999fef09ceb58f30dcbbe2a5fd410f8a22dda6179fa5f1041c7a759a31932ef9", - "source": { - "agent": { - "name": "security-linux-2.example.dev", - "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-2", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.195", - "name": "security-linux-2", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.330Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.496Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-2", - "field": "host.name", - "id": "NGyvt38BIyEvspK01nQn", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "PWyvt38BIyEvspK04XTd", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "PWyvt38BIyEvspK04XTd", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-2 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "PWyvt38BIyEvspK04XTd", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.330Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.330Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "f75bc411e6b0c30c26aa310c1e65ff8430cc0a98ddf74c335941dd7456858e85", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.001Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.497Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-1", - "field": "host.name", - "id": "M2yvt38BIyEvspK01XQt", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "PGyvt38BIyEvspK04HSX", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "PGyvt38BIyEvspK04HSX", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-1 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "PGyvt38BIyEvspK04HSX", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.001Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.001Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "b46b35ce011486304a3a1e1b1dc2b772e2b80684a3a8663e9cd101691cff7429", - "source": { - "agent": { - "name": "security-linux-3.example.dev", - "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-3", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.196", - "name": "security-linux-3", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.665Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.498Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-3", - "field": "host.name", - "id": "NWyvt38BIyEvspK013R3", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "O2yvt38BIyEvspK033RN", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "O2yvt38BIyEvspK033RN", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-3 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "O2yvt38BIyEvspK033RN", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:30.665Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.665Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "570caf7637457b9721fd46ec22166adb57916298bf68ef31df07bd0bbac95d7c", - "source": { - "agent": { - "name": "security-linux-2.example.dev", - "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-2", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.195", - "name": "security-linux-2", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.353Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.499Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-2", - "field": "host.name", - "id": "NGyvt38BIyEvspK01nQn", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "Omyvt38BIyEvspK03nQB", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "Omyvt38BIyEvspK03nQB", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-2 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "Omyvt38BIyEvspK03nQB", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:30.353Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.353Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "0c7bfb7198c9db281b639b1044c74db2b881e3152ee863e6c9304a6fb5d0e5bb", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.031Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.501Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-1", - "field": "host.name", - "id": "M2yvt38BIyEvspK01XQt", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "OWyvt38BIyEvspK03HTF", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "OWyvt38BIyEvspK03HTF", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-1 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "OWyvt38BIyEvspK03HTF", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:30.031Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.031Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "ae1c6e5c7680cdc986ff52b1913e93ba2a010ea207364d4782550adf180e49ee", - "source": { - "agent": { - "name": "security-linux-3.example.dev", - "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-3", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.196", - "name": "security-linux-3", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.715Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.502Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-3", - "field": "host.name", - "id": "NWyvt38BIyEvspK013R3", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "OGyvt38BIyEvspK023SI", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "OGyvt38BIyEvspK023SI", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-3 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "OGyvt38BIyEvspK023SI", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:29.715Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.715Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "a73fda6bdb25425c8597f63e2b87b662798ad46f195c47ac4243d9d0b9705dd8", - "source": { - "agent": { - "name": "security-linux-2.example.dev", - "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-2", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.195", - "name": "security-linux-2", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.387Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.503Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-2", - "field": "host.name", - "id": "NGyvt38BIyEvspK01nQn", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "N2yvt38BIyEvspK02nRK", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "N2yvt38BIyEvspK02nRK", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-2 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "N2yvt38BIyEvspK02nRK", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:29.387Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.387Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "77038fe81327ce7b578e69896fdd1869fab16d13633b5fb0cb7743bae9120ca5", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:28.994Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:51.504Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "threat": { - "enrichments": [ - { - "indicator": {}, - "matched": { - "atomic": "security-linux-1", - "field": "host.name", - "id": "M2yvt38BIyEvspK01XQt", - "index": "threat-index-000001", - "type": "indicator_match_rule" - } - } - ] - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "Nmyvt38BIyEvspK02HTJ", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "Nmyvt38BIyEvspK02HTJ", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", - "actions": [], - "interval": "1m", - "name": "threat-match-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:47.264Z", - "updated_at": "2022-03-23T16:50:48.396Z", - "description": "a simple threat match rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threat_match", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threat_query": "*", - "threat_mapping": [ - { - "entries": [ - { - "field": "host.name", - "type": "mapping", - "value": "host.name" - } - ] - } - ], - "threat_language": "kuery", - "threat_index": [ - "threat-index-*" - ], - "threat_indicator_path": "threat.indicator" - }, - "reason": "event on security-linux-1 created low alert threat-match-rule.", - "depth": 1, - "parent": { - "id": "Nmyvt38BIyEvspK02HTJ", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:28.994Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:28.994Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "21d26a1ad7b01b28667638d5f8db96f6e94957394efe7a16057948095a445ac4", - "source": { - "@timestamp": "2022-03-23T16:50:48.441Z", - "host.name": "security-linux-1", - "event": { - "kind": "signal" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "8e75aa13-6b35-5d96-b52b-1d62909a9d75", - "type": "event", - "index": "events-index-*", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "8e75aa13-6b35-5d96-b52b-1d62909a9d75", - "type": "event", - "index": "events-index-*", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "60b8b970-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "threshold-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:44.260Z", - "updated_at": "2022-03-23T16:50:45.341Z", - "description": "a simple threshold rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "b97ae2a4-f188-43b2-b082-69667b563152", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threshold", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threshold": { - "field": [ - "host.name" - ], - "value": 1 - } - }, - "reason": "event created low alert threshold-rule.", - "depth": 1, - "parent": { - "id": "8e75aa13-6b35-5d96-b52b-1d62909a9d75", - "type": "event", - "index": "events-index-*", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:32.045Z", - "threshold_result": { - "terms": [ - { - "field": "host.name", - "value": "security-linux-1" - } - ], - "count": 4, - "from": "2022-03-23T06:50:48.395Z" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "4c2a3865ca7df72e4cc17b5114feb2535b2459fd52f6fbd0669d4884f5956dc2", - "source": { - "@timestamp": "2022-03-23T16:50:48.442Z", - "host.name": "security-linux-2", - "event": { - "kind": "signal" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "9c957c24-8ce5-516b-ba8e-44b582da6579", - "type": "event", - "index": "events-index-*", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "9c957c24-8ce5-516b-ba8e-44b582da6579", - "type": "event", - "index": "events-index-*", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "60b8b970-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "threshold-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:44.260Z", - "updated_at": "2022-03-23T16:50:45.341Z", - "description": "a simple threshold rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "b97ae2a4-f188-43b2-b082-69667b563152", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threshold", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threshold": { - "field": [ - "host.name" - ], - "value": 1 - } - }, - "reason": "event created low alert threshold-rule.", - "depth": 1, - "parent": { - "id": "9c957c24-8ce5-516b-ba8e-44b582da6579", - "type": "event", - "index": "events-index-*", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.330Z", - "threshold_result": { - "terms": [ - { - "field": "host.name", - "value": "security-linux-2" - } - ], - "count": 3, - "from": "2022-03-23T06:50:48.395Z" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "3754896311b1d9f9dee45ecf06aa5160f8cd3d4504ef5c856ba285edd61d059d", - "source": { - "@timestamp": "2022-03-23T16:50:48.442Z", - "host.name": "security-linux-3", - "event": { - "kind": "signal" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "326cc81c-b55f-5b69-8222-e930bcb24692", - "type": "event", - "index": "events-index-*", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "326cc81c-b55f-5b69-8222-e930bcb24692", - "type": "event", - "index": "events-index-*", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "60b8b970-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "threshold-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:44.260Z", - "updated_at": "2022-03-23T16:50:45.341Z", - "description": "a simple threshold rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "b97ae2a4-f188-43b2-b082-69667b563152", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "threshold", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [], - "threshold": { - "field": [ - "host.name" - ], - "value": 1 - } - }, - "reason": "event created low alert threshold-rule.", - "depth": 1, - "parent": { - "id": "326cc81c-b55f-5b69-8222-e930bcb24692", - "type": "event", - "index": "events-index-*", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.654Z", - "threshold_result": { - "terms": [ - { - "field": "host.name", - "value": "security-linux-3" - } - ], - "count": 3, - "from": "2022-03-23T06:50:48.395Z" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "5cddda6852c5f8b6c32d4bfa5e876aa51884e0c7a2d4faaababf91ec9cb68de7", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:28.994Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.440Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "Nmyvt38BIyEvspK02HTJ", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "Nmyvt38BIyEvspK02HTJ", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-1 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "Nmyvt38BIyEvspK02HTJ", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:28.994Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:28.994Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "5050902fa762858249c32b1d228dd71ca9217ace612b65f9669fb3a5f371ab63", - "source": { - "agent": { - "name": "security-linux-2.example.dev", - "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-2", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.195", - "name": "security-linux-2", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.387Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.477Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "N2yvt38BIyEvspK02nRK", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "N2yvt38BIyEvspK02nRK", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-2 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "N2yvt38BIyEvspK02nRK", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:29.387Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.387Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "525833fe5aa3cabce849adf9291b4d4009c25edbe528d5d2add1dc749c00513b", - "source": { - "agent": { - "name": "security-linux-3.example.dev", - "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-3", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.196", - "name": "security-linux-3", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.715Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.499Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "OGyvt38BIyEvspK023SI", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "OGyvt38BIyEvspK023SI", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-3 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "OGyvt38BIyEvspK023SI", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:29.715Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:29.715Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "4f9c5a7581544f9dc1fa4c9f541c7e7573d7460ddeeda1875bee081e6615035b", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.031Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.510Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "OWyvt38BIyEvspK03HTF", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "OWyvt38BIyEvspK03HTF", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-1 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "OWyvt38BIyEvspK03HTF", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:30.031Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.031Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "d791d45b87a37e3b8a8388d7d6237728aa14ab6ec81bfa84f96457bd42b39e4a", - "source": { - "agent": { - "name": "security-linux-2.example.dev", - "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-2", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.195", - "name": "security-linux-2", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.353Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.533Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "Omyvt38BIyEvspK03nQB", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "Omyvt38BIyEvspK03nQB", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-2 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "Omyvt38BIyEvspK03nQB", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:30.353Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.353Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "747a4cfd4dbc1dd3924b341b0d3d94098252579354bf140e1621cb4b8681e911", - "source": { - "agent": { - "name": "security-linux-3.example.dev", - "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-3", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.196", - "name": "security-linux-3", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.665Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.547Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "O2yvt38BIyEvspK033RN", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "O2yvt38BIyEvspK033RN", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-3 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "O2yvt38BIyEvspK033RN", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:30.665Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:30.665Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "5a217bc36610a820dbbb20f7b189065d631038a9dbb33bde1511f0f6a63183d2", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.001Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.561Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "PGyvt38BIyEvspK04HSX", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "PGyvt38BIyEvspK04HSX", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-1 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "PGyvt38BIyEvspK04HSX", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.001Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.001Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "fde1f09c4420ce5747f04ca051bcdc90762394ea019a7cc2cfee8de3bd575a59", - "source": { - "agent": { - "name": "security-linux-2.example.dev", - "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-2", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.195", - "name": "security-linux-2", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.330Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.593Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "PWyvt38BIyEvspK04XTd", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "PWyvt38BIyEvspK04XTd", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-2 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "PWyvt38BIyEvspK04XTd", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.330Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.330Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "337f39b1fb862a4c6910605b16e6b5b59623219e99dcb7d442cd334229ad3a7e", - "source": { - "agent": { - "name": "security-linux-3.example.dev", - "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-3", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.196", - "name": "security-linux-3", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.654Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.606Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "Pmyvt38BIyEvspK043Ri", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "Pmyvt38BIyEvspK043Ri", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-3 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "Pmyvt38BIyEvspK043Ri", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:31.654Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:31.654Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".siem-signals-default-000001-7.16.0", - "id": "44f8d6e34631ced611f6588e7f0cdf52ac5647eff09cfbd36a38ad2a7d4bf32f", - "source": { - "agent": { - "name": "security-linux-1.example.dev", - "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", - "type": "filebeat", - "version": "7.16.0" - }, - "log": { - "file": { - "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" - }, - "offset": 148938 - }, - "cloud": { - "availability_zone": "us-central1-c", - "instance": { - "name": "security-linux-1", - "id": "8995531128842994872" - }, - "provider": "gcp", - "service": { - "name": "GCE" - }, - "machine": { - "type": "g1-small" - }, - "project": { - "id": "elastic-siem" - }, - "account": { - "id": "elastic-siem" - } - }, - "ecs": { - "version": "7.16.0" - }, - "host": { - "hostname": "security-linux-1", - "os": { - "kernel": "4.19.0-18-cloud-amd64", - "codename": "buster", - "name": "Debian GNU/Linux", - "type": "linux", - "family": "debian", - "version": "10 (buster)", - "platform": "debian" - }, - "containerized": false, - "ip": "11.200.0.194", - "name": "security-linux-1", - "architecture": "x86_64" - }, - "event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:32.045Z", - "dataset": "elastic_agent.filebeat", - "kind": "signal" - }, - "service.name": "filebeat", - "message": "Status message.", - "@timestamp": "2022-03-23T16:50:40.624Z", - "data_stream": { - "namespace": "default", - "type": "logs", - "dataset": "elastic_agent.filebeat" - }, - "signal": { - "_meta": { - "version": 57 - }, - "parents": [ - { - "id": "P2yvt38BIyEvspK05HSe", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "ancestors": [ - { - "id": "P2yvt38BIyEvspK05HSe", - "type": "event", - "index": "events-index-000001", - "depth": 0 - } - ], - "status": "open", - "rule": { - "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", - "actions": [], - "interval": "1m", - "name": "query-rule", - "tags": [], - "enabled": true, - "created_by": "elastic", - "updated_by": "elastic", - "throttle": null, - "created_at": "2022-03-23T16:50:34.234Z", - "updated_at": "2022-03-23T16:50:36.214Z", - "description": "a simple query rule", - "risk_score": 21, - "severity": "low", - "license": "", - "output_index": ".siem-signals-default-000001", - "author": [], - "false_positives": [], - "from": "now-36000s", - "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", - "max_signals": 100, - "risk_score_mapping": [], - "severity_mapping": [], - "threat": [], - "to": "now", - "references": [], - "version": 1, - "exceptions_list": [], - "immutable": false, - "type": "query", - "language": "kuery", - "index": [ - "events-index-*" - ], - "query": "*", - "filters": [] - }, - "reason": "event on security-linux-1 created low alert query-rule.", - "depth": 1, - "parent": { - "id": "P2yvt38BIyEvspK05HSe", - "type": "event", - "index": "events-index-000001", - "depth": 0 - }, - "original_time": "2022-03-23T16:50:32.045Z", - "original_event": { - "agent_id_status": "verified", - "ingested": "2022-03-23T16:50:32.045Z", - "dataset": "elastic_agent.filebeat" - } - } - } - } -} - diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json.gz b/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..11557b383024833f7989c1b59a378409110131de GIT binary patch literal 4755 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 literal 0 HcmV?d00001 diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/7.17.0/data.json.gz b/x-pack/test/functional/es_archives/security_solution/alerts/7.17.0/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..e63a4ccc0ab4f8efa6fc6c61d8980086287bdf50 GIT binary patch literal 4744 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 literal 0 HcmV?d00001 diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/7.17.0/mappings.json.gz b/x-pack/test/functional/es_archives/security_solution/alerts/7.17.0/mappings.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..fb737e83c010dacdb1347235cd72f8acf1459236 GIT binary patch literal 9846 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 literal 0 HcmV?d00001 diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/8.0.0/data.json.gz b/x-pack/test/functional/es_archives/security_solution/alerts/8.0.0/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..26952621f10e4bce828d8cb5e86504a8715be539 GIT binary patch literal 9231 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 DK?YAz literal 0 HcmV?d00001 diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/8.0.0/mappings.json.gz b/x-pack/test/functional/es_archives/security_solution/alerts/8.0.0/mappings.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..3a26e140e7eaa87becd588b84b6cfae9955a2905 GIT binary patch literal 9711 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 XQ{nMN`SpJE1#Y-!$WCVl0rr0YQDEFA literal 0 HcmV?d00001 From 062be578697509822923854b4a4accb466041cac Mon Sep 17 00:00:00 2001 From: Thomas Decaux Date: Tue, 12 Apr 2022 18:03:15 +0200 Subject: [PATCH 14/15] Add type murmur3 into the lens fields list (#129029) * Add murmur3 type to fields list To fix #129007 , naive approach. * Add murmur3 type to fields list * Add murmur3 type to fields list * removed translations * disable field preview * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * change icon * add specific murmur3 message * fix test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Joe Reuter --- .../__snapshots__/field_icon.test.tsx.snap | 2 +- .../kbn-react-field/src/field_icon/field_icon.tsx | 2 +- .../public/indexpattern_datasource/datapanel.tsx | 2 ++ .../public/indexpattern_datasource/field_item.tsx | 12 ++++++++++++ .../operations/definitions/cardinality.tsx | 1 + x-pack/plugins/lens/public/types.ts | 8 +++++++- .../lens/public/xy_visualization/xy_suggestions.ts | 1 + 7 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/kbn-react-field/src/field_icon/__snapshots__/field_icon.test.tsx.snap b/packages/kbn-react-field/src/field_icon/__snapshots__/field_icon.test.tsx.snap index cd81705dd3c19..7328e2c61b961 100644 --- a/packages/kbn-react-field/src/field_icon/__snapshots__/field_icon.test.tsx.snap +++ b/packages/kbn-react-field/src/field_icon/__snapshots__/field_icon.test.tsx.snap @@ -139,7 +139,7 @@ exports[`FieldIcon renders known field types murmur3 is rendered 1`] = ` diff --git a/packages/kbn-react-field/src/field_icon/field_icon.tsx b/packages/kbn-react-field/src/field_icon/field_icon.tsx index be62a8df60274..621b8d0199d04 100644 --- a/packages/kbn-react-field/src/field_icon/field_icon.tsx +++ b/packages/kbn-react-field/src/field_icon/field_icon.tsx @@ -46,7 +46,7 @@ export const typeToEuiIconMap: Partial> = { ip: { iconType: 'tokenIP' }, ip_range: { iconType: 'tokenIP' }, // is a plugin's data type https://www.elastic.co/guide/en/elasticsearch/plugins/current/mapper-murmur3-usage.html - murmur3: { iconType: 'tokenFile' }, + murmur3: { iconType: 'tokenSearchType' }, number: { iconType: 'tokenNumber' }, number_range: { iconType: 'tokenNumber' }, histogram: { iconType: 'tokenHistogram' }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index 4f8c492de3c17..70aacb2978955 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -82,6 +82,7 @@ const supportedFieldTypes = new Set([ 'document', 'geo_point', 'geo_shape', + 'murmur3', ]); const fieldTypeNames: Record = { @@ -94,6 +95,7 @@ const fieldTypeNames: Record = { histogram: i18n.translate('xpack.lens.datatypes.histogram', { defaultMessage: 'histogram' }), geo_point: i18n.translate('xpack.lens.datatypes.geoPoint', { defaultMessage: 'geo_point' }), geo_shape: i18n.translate('xpack.lens.datatypes.geoShape', { defaultMessage: 'geo_shape' }), + murmur3: i18n.translate('xpack.lens.datatypes.murmur3', { defaultMessage: 'murmur3' }), }; // Wrapper around buildEsQuery, handling errors (e.g. because a query can't be parsed) by diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index 82b4a0aa33409..d657a22ca8d26 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -472,6 +472,18 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { ); + } else if (field.type === 'murmur3') { + return ( + <> + {panelHeader} + + + {i18n.translate('xpack.lens.indexPattern.fieldStatsMurmur3Limited', { + defaultMessage: `Summary information is not available for murmur3 fields.`, + })} + + + ); } else if (field.type === 'geo_point' || field.type === 'geo_shape') { return ( <> diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx index e65d89547d567..eabff6f3e7f4b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx @@ -35,6 +35,7 @@ const supportedTypes = new Set([ 'ip_range', 'date', 'date_range', + 'murmur3', ]); const SCALE = 'ratio'; diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 8d2a5b881392e..2143cb1704bf5 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -476,7 +476,13 @@ export type DatasourceDimensionDropHandlerProps = DatasourceDimensionDropProp dropType: DropType; }; -export type FieldOnlyDataType = 'document' | 'ip' | 'histogram' | 'geo_point' | 'geo_shape'; +export type FieldOnlyDataType = + | 'document' + | 'ip' + | 'histogram' + | 'geo_point' + | 'geo_shape' + | 'murmur3'; export type DataType = 'string' | 'number' | 'date' | 'boolean' | FieldOnlyDataType; // An operation represents a column in a table, not any information diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts index 05bdb4fd65c88..671e225ef894b 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts @@ -32,6 +32,7 @@ const columnSortOrder = { histogram: 6, geo_point: 7, geo_shape: 8, + murmur3: 9, }; /** From b7dc8f0e9c27dcebc2e1dc28770cf95c2c75e544 Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Tue, 12 Apr 2022 12:21:23 -0400 Subject: [PATCH 15/15] Use a link to enable shift/right click of rule names in the popover (#128850) --- .../body/renderers/formatted_field.tsx | 2 + .../renderers/formatted_field_helpers.tsx | 77 ++++++++++++++----- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx index f87c7ae9e58d6..ebd0fb974f3aa 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx @@ -185,6 +185,8 @@ const FormattedFieldValueComponent: React.FC<{ eventId={eventId} fieldName={fieldName} isDraggable={isDraggable} + isButton={isButton} + onClick={onClick} linkValue={linkValue} title={title} truncate={truncate} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx index 02088b2e7d0cc..04b69cd5fd3ff 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field_helpers.tsx @@ -32,17 +32,21 @@ import { useFormatUrl } from '../../../../../common/components/link_to'; import { useKibana } from '../../../../../common/lib/kibana'; import { APP_UI_ID } from '../../../../../../common/constants'; import { LinkAnchor } from '../../../../../common/components/links'; +import { GenericLinkButton } from '../../../../../common/components/links/helpers'; const EventModuleFlexItem = styled(EuiFlexItem)` width: 100%; `; interface RenderRuleNameProps { + children?: React.ReactNode; Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon; contextId: string; eventId: string; fieldName: string; isDraggable: boolean; + isButton?: boolean; + onClick?: () => void; linkValue: string | null | undefined; truncate?: boolean; title?: string; @@ -50,11 +54,14 @@ interface RenderRuleNameProps { } export const RenderRuleName: React.FC = ({ + children, Component, contextId, eventId, fieldName, isDraggable, + isButton, + onClick, linkValue, truncate, title, @@ -64,11 +71,6 @@ export const RenderRuleName: React.FC = ({ const ruleId = linkValue; const { search } = useFormatUrl(SecurityPageName.rules); const { navigateToApp, getUrlForApp } = useKibana().services.application; - const content = truncate ? ( - {value} - ) : ( - value - ); const goToRuleDetails = useCallback( (ev) => { @@ -90,24 +92,59 @@ export const RenderRuleName: React.FC = ({ [getUrlForApp, ruleId, search] ); const id = `event-details-value-default-draggable-${contextId}-${eventId}-${fieldName}-${value}-${ruleId}`; - - if (isString(value) && ruleName.length > 0 && ruleId != null) { - const link = Component ? ( - - {title ?? value} - + const link = useMemo(() => { + const content = truncate ? ( + {value} ) : ( - - {content} - + value ); + if (isButton) { + return ( + + {children} + + ); + } else if (Component) { + return ( + + {title ?? value} + + ); + } else { + return ( + + {content} + + ); + } + }, [ + Component, + children, + fieldName, + goToRuleDetails, + href, + isButton, + onClick, + ruleName, + title, + truncate, + value, + ]); + if (isString(value) && ruleName.length > 0 && ruleId != null) { return isDraggable ? (