From 1a28c2087d30c0adf15a7f0fea37c793aafe22d1 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Thu, 23 Dec 2021 10:48:41 +0000 Subject: [PATCH] CR: add immutability guard --- .../rules/perform_bulk_action_route.test.ts | 42 ++++++++++++++++++- .../routes/rules/perform_bulk_action_route.ts | 6 +++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts index 43995d369ce02..c99760b72b56b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts @@ -19,13 +19,16 @@ import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { performBulkActionRoute } from './perform_bulk_action_route'; import { getPerformBulkActionSchemaMock } from '../../../../../common/detection_engine/schemas/request/perform_bulk_action_schema.mock'; import { loggingSystemMock } from 'src/core/server/mocks'; +import { isElasticRule } from '../../../../usage/detections'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); +jest.mock('../../../../usage/detections', () => ({ isElasticRule: jest.fn() })); describe.each([ ['Legacy', false], ['RAC', true], ])('perform_bulk_action - %s', (_, isRuleRegistryEnabled) => { + const isElasticRuleMock = isElasticRule as jest.Mock; let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -37,7 +40,7 @@ describe.each([ logger = loggingSystemMock.createLogger(); ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); - + isElasticRuleMock.mockReturnValue(false); clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); performBulkActionRoute(server.router, ml, logger, isRuleRegistryEnabled); @@ -78,6 +81,43 @@ describe.each([ }); describe('rules execution failures', () => { + it('returns error if rule is immutable/elastic', async () => { + isElasticRuleMock.mockReturnValue(true); + clients.rulesClient.find.mockResolvedValue( + getFindResultWithMultiHits({ + data: [mockRule], + total: 1, + }) + ); + + const response = await server.inject(getBulkActionEditRequest(), context); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: 'Bulk edit failed', + status_code: 500, + attributes: { + errors: [ + { + message: 'Elastic rule can`t be edited', + status_code: 403, + rules: [ + { + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + name: 'Detect Root/Admin Users', + }, + ], + }, + ], + rules: { + failed: 1, + succeeded: 0, + total: 1, + }, + }, + }); + }); + it('returns error if disable rule throws error', async () => { clients.rulesClient.disable.mockImplementation(async () => { throw new Error('Test error'); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts index 269a7529e79a8..0470634d5acca 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts @@ -20,6 +20,7 @@ import { SetupPlugins } from '../../../../plugin'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { initPromisePool } from '../../../../utils/promise_pool'; +import { isElasticRule } from '../../../../usage/detections'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { throwHttpError } from '../../../machine_learning/validation'; import { deleteRules } from '../../rules/delete_rules'; @@ -221,6 +222,11 @@ export const performBulkActionRoute = ( }); case BulkAction.edit: processingResponse = await executeBulkAction(rules.data, async (rule) => { + throwHttpError({ + valid: !isElasticRule(rule.tags), + message: 'Elastic rule can`t be edited', + }); + throwHttpError(await mlAuthz.validateRuleType(rule.params.type)); const editedRule = body[BulkAction.edit].reduce(