diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.import_rule.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.import_rule.test.ts index 474fecc186519..0e57de91a71ad 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.import_rule.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.import_rule.test.ts @@ -150,6 +150,74 @@ describe('DetectionRulesClient.importRule', () => { ); }); + it('enables the rule if the imported rule has enabled: true', async () => { + const disabledExistingRule = { + ...existingRule, + enabled: false, + }; + (readRules as jest.Mock).mockResolvedValueOnce(disabledExistingRule); + + const rule = await detectionRulesClient.importRule({ + ruleToImport: { + ...ruleToImport, + enabled: true, + }, + overwriteRules: true, + allowMissingConnectorSecrets, + }); + + expect(rulesClient.create).not.toHaveBeenCalled(); + expect(rulesClient.update).toHaveBeenCalledWith( + expect.objectContaining({ + id: existingRule.id, + data: expect.not.objectContaining({ + enabled: expect.anything(), + }), + }) + ); + + expect(rule.enabled).toBe(true); + expect(rulesClient.enable).toHaveBeenCalledWith( + expect.objectContaining({ + id: existingRule.id, + }) + ); + }); + + it('disables the rule if the imported rule has enabled: false', async () => { + const enabledExistingRule = { + ...existingRule, + enabled: true, + }; + (readRules as jest.Mock).mockResolvedValueOnce(enabledExistingRule); + + const rule = await detectionRulesClient.importRule({ + ruleToImport: { + ...ruleToImport, + enabled: false, + }, + overwriteRules: true, + allowMissingConnectorSecrets, + }); + + expect(rulesClient.create).not.toHaveBeenCalled(); + expect(rulesClient.update).toHaveBeenCalledWith( + expect.objectContaining({ + id: existingRule.id, + data: expect.not.objectContaining({ + enabled: expect.anything(), + }), + }) + ); + + expect(rule.enabled).toBe(false); + expect(rulesClient.disable).toHaveBeenCalledWith( + expect.objectContaining({ + id: existingRule.id, + }) + ); + }); + it('rejects when overwriteRules is false', async () => { (readRules as jest.Mock).mockResolvedValue(existingRule); await expect( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/import_rule.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/import_rule.ts index 55a0399f1a528..afa916c95d934 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/import_rule.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/import_rule.ts @@ -17,8 +17,7 @@ import { internalRuleToAPIResponse, } from '../../../normalization/rule_converters'; import { RuleResponse } from '../../../../../../../common/api/detection_engine/model/rule_schema'; - -import { validateMlAuth, RuleResponseValidationError } from '../utils'; +import { validateMlAuth, RuleResponseValidationError, toggleRuleEnabledOnUpdate } from '../utils'; import { readRules } from '../read_rules'; @@ -46,6 +45,7 @@ export const importRule = async ( } let importedInternalRule: RuleAlertType; + let enabled: boolean; if (existingRule && overwriteRules) { const ruleUpdateParams = convertUpdateAPIToInternalSchema({ @@ -57,6 +57,14 @@ export const importRule = async ( id: existingRule.id, data: ruleUpdateParams, }); + + // We strip `enabled` from the rule object to use in the rules client and need to enable it separately if user has enabled the updated rule + const { enabled: isNowEnabled } = await toggleRuleEnabledOnUpdate( + rulesClient, + existingRule, + ruleToImport.enabled + ); + enabled = isNowEnabled; } else { /* Rule does not exist, so we'll create it */ const ruleCreateParams = convertCreateAPIToInternalSchema(ruleToImport, { @@ -67,10 +75,13 @@ export const importRule = async ( data: ruleCreateParams, allowMissingConnectorSecrets, }); + enabled = importedInternalRule.enabled; } /* Trying to convert an internal rule to a RuleResponse object */ - const parseResult = RuleResponse.safeParse(internalRuleToAPIResponse(importedInternalRule)); + const parseResult = RuleResponse.safeParse( + internalRuleToAPIResponse({ ...importedInternalRule, enabled }) + ); if (!parseResult.success) { throw new RuleResponseValidationError({