Skip to content

Commit dc9be8e

Browse files
committed
[Security Solution] Move prebuilt rule install/upgrade/revert into DetectionRulesClient
Moves the prebuilt rule install, upgrade, and revert logic from standalone `rule_objects/` helpers into new DetectionRulesClient methods, completing the consolidation started in #270446. Deletes create_prebuilt_rules.ts, upgrade_prebuilt_rules.ts, and revert_prebuilt_rules.ts from rule_objects/ and simplifies the corresponding API handlers to delegate to the DRC.
1 parent 702ed6e commit dc9be8e

31 files changed

Lines changed: 1272 additions & 1269 deletions

x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/legacy_create_prepackaged_rules.ts

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,9 @@ import type { RulesClient } from '@kbn/alerting-plugin/server';
1010
import type { ExceptionListClient } from '@kbn/lists-plugin/server';
1111
import type { InstallPrebuiltRulesAndTimelinesResponse } from '../../../../../../common/api/detection_engine/prebuilt_rules';
1212
import type { SecuritySolutionApiRequestHandlerContext } from '../../../../../types';
13-
import { getExistingPrepackagedRules } from '../../../rule_management/logic/search/get_existing_prepackaged_rules';
1413
import { ensureLatestRulesPackageInstalled } from '../../logic/integrations/ensure_latest_rules_package_installed';
15-
import { getRulesToInstall } from '../../logic/get_rules_to_install';
16-
import { getRulesToUpdate } from '../../logic/get_rules_to_update';
1714
import { performTimelinesInstallation } from '../../logic/perform_timelines_installation';
1815
import { createPrebuiltRuleAssetsClient } from '../../logic/rule_assets/prebuilt_rule_assets_client';
19-
import { createPrebuiltRules } from '../../logic/rule_objects/create_prebuilt_rules';
20-
import { upgradePrebuiltRules } from '../../logic/rule_objects/upgrade_prebuilt_rules';
21-
import { rulesToMap } from '../../logic/utils';
2216

2317
export class PrepackagedRulesError extends Error {
2418
public readonly statusCode: number;
@@ -31,7 +25,7 @@ export class PrepackagedRulesError extends Error {
3125
/**
3226
* @deprecated This method is incompatible with prebuilt rules customization as
3327
* it upgrades prebuilt rules to their 'target' version erasing any
34-
* customizations. Use createPrebuiltRules instead.
28+
* customizations. Use DetectionRulesClient.installPrebuiltRules instead.
3529
*/
3630
export const legacyCreatePrepackagedRules = async (
3731
context: SecuritySolutionApiRequestHandlerContext,
@@ -44,7 +38,6 @@ export const legacyCreatePrepackagedRules = async (
4438
const exceptionsListClient = context.getExceptionListClient() ?? exceptionsClient;
4539
const detectionRulesClient = context.getDetectionRulesClient();
4640
const ruleAssetsClient = createPrebuiltRuleAssetsClient(savedObjectsClient);
47-
const mlAuthz = context.getMlAuthz();
4841

4942
if (!siemClient || !rulesClient) {
5043
throw new PrepackagedRulesError('', 404);
@@ -57,49 +50,27 @@ export const legacyCreatePrepackagedRules = async (
5750

5851
await ensureLatestRulesPackageInstalled(ruleAssetsClient, context, logger);
5952

60-
const latestPrebuiltRules = await ruleAssetsClient.fetchLatestAssets();
61-
const installedPrebuiltRules = rulesToMap(
62-
await getExistingPrepackagedRules({ rulesClient, logger })
63-
);
64-
const rulesToInstall = await getRulesToInstall(
65-
latestPrebuiltRules,
66-
installedPrebuiltRules,
67-
mlAuthz
68-
);
69-
const rulesToUpdate = await getRulesToUpdate(
70-
latestPrebuiltRules,
71-
installedPrebuiltRules,
72-
mlAuthz
73-
);
53+
const { installedRules, errors: installErrors } =
54+
await detectionRulesClient.installAllPrebuiltRules();
7455

75-
const installChangeTracking = {
76-
metadata: {
77-
bulkCount: rulesToInstall.length,
78-
},
79-
};
80-
const ruleCreationResult = await createPrebuiltRules(
81-
detectionRulesClient,
82-
rulesToInstall,
83-
installChangeTracking,
84-
logger
85-
);
86-
87-
if (ruleCreationResult.errors.length > 0) {
88-
throw new AggregateError(ruleCreationResult.errors, 'Error installing new prebuilt rules');
56+
if (installErrors.length > 0) {
57+
throw new AggregateError(
58+
installErrors.map((e) => e.error),
59+
'Error installing new prebuilt rules'
60+
);
8961
}
9062

9163
const { result: timelinesResult } = await performTimelinesInstallation(context);
9264

93-
const upgradeChangeTracking = {
94-
metadata: {
95-
bulkCount: rulesToUpdate.length,
96-
},
97-
};
98-
await upgradePrebuiltRules(detectionRulesClient, rulesToUpdate, upgradeChangeTracking, logger);
65+
const { updatedRules } = await detectionRulesClient.upgradeAllPrebuiltRules({
66+
onConflict: 'UPGRADE_SOLVABLE',
67+
defaultPickVersion: 'TARGET',
68+
isDryRun: false,
69+
});
9970

10071
return {
101-
rules_installed: rulesToInstall.length,
102-
rules_updated: rulesToUpdate.length,
72+
rules_installed: installedRules.length,
73+
rules_updated: updatedRules.length,
10374
timelines_installed: timelinesResult?.timelines_installed ?? 0,
10475
timelines_updated: timelinesResult?.timelines_updated ?? 0,
10576
};

x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_handler.ts

Lines changed: 7 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,18 @@
55
* 2.0.
66
*/
77

8-
import { pick } from 'lodash';
98
import { transformError } from '@kbn/securitysolution-es-utils';
109
import type { Logger, KibanaRequest, KibanaResponseFactory } from '@kbn/core/server';
11-
import { SkipRuleInstallReason } from '../../../../../../common/api/detection_engine/prebuilt_rules';
1210
import type {
1311
PerformRuleInstallationResponseBody,
14-
SkippedRuleInstall,
1512
PerformRuleInstallationRequestBody,
16-
InstalledRuleBasicInfo,
1713
} from '../../../../../../common/api/detection_engine/prebuilt_rules';
1814
import type { SecuritySolutionRequestHandlerContext } from '../../../../../types';
1915
import { buildSiemResponse } from '../../../routes/utils';
2016
import { aggregatePrebuiltRuleErrors } from '../../logic/aggregate_prebuilt_rule_errors';
2117
import { ensureLatestRulesPackageInstalled } from '../../logic/integrations/ensure_latest_rules_package_installed';
2218
import { createPrebuiltRuleAssetsClient } from '../../logic/rule_assets/prebuilt_rule_assets_client';
23-
import { PREBUILT_RULE_BATCH_SIZE } from '../../constants';
24-
import { createPrebuiltRules } from '../../logic/rule_objects/create_prebuilt_rules';
25-
import { createPrebuiltRuleObjectsClient } from '../../logic/rule_objects/prebuilt_rule_objects_client';
2619
import { performTimelinesInstallation } from '../../logic/perform_timelines_installation';
27-
import type { RuleSignatureId, RuleVersion } from '../../../../../../common/api/detection_engine';
28-
import { excludeLicenseRestrictedRules } from '../../logic/utils';
2920

3021
export const performRuleInstallationHandler = async (
3122
context: SecuritySolutionRequestHandlerContext,
@@ -38,12 +29,9 @@ export const performRuleInstallationHandler = async (
3829
try {
3930
const ctx = await context.resolve(['core', 'alerting', 'securitySolution']);
4031
const soClient = ctx.core.savedObjects.client;
41-
const rulesClient = await ctx.alerting.getRulesClient();
4232
const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient();
4333
const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient);
44-
const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient);
4534
const exceptionsListClient = ctx.securitySolution.getExceptionListClient();
46-
const mlAuthz = ctx.securitySolution.getMlAuthz();
4735

4836
const { mode } = request.body;
4937

@@ -54,93 +42,16 @@ export const performRuleInstallationHandler = async (
5442
// pages first, the rules package might be missing.
5543
await ensureLatestRulesPackageInstalled(ruleAssetsClient, ctx.securitySolution, logger);
5644

57-
const ruleInstallQueue: Array<{
58-
rule_id: RuleSignatureId;
59-
version: RuleVersion;
60-
}> = [];
61-
const ruleErrors = [];
62-
const installedRules: InstalledRuleBasicInfo[] = [];
63-
const skippedRules: SkippedRuleInstall[] = [];
64-
65-
// Perform all the checks we can before we start the upgrade process
66-
if (mode === 'SPECIFIC_RULES') {
67-
const requestedRuleIds = request.body.rules.map((rule) => rule.rule_id);
68-
const [latestVersions, installedVersions] = await Promise.all([
69-
ruleAssetsClient.fetchLatestVersions({ ruleIds: requestedRuleIds }),
70-
ruleObjectsClient.fetchInstalledRuleVersionsByIds({ ruleIds: requestedRuleIds }),
71-
]);
72-
const installedRuleIds = new Set(installedVersions.map((version) => version.rule_id));
73-
const installableRuleIds = new Set(
74-
latestVersions
75-
.filter((version) => !installedRuleIds.has(version.rule_id))
76-
.map((version) => version.rule_id)
77-
);
78-
79-
request.body.rules.forEach((rule) => {
80-
// Check that the requested rule is not installed yet
81-
if (installedRuleIds.has(rule.rule_id)) {
82-
skippedRules.push({
83-
rule_id: rule.rule_id,
84-
reason: SkipRuleInstallReason.ALREADY_INSTALLED,
85-
});
86-
return;
87-
}
88-
89-
// Check that the requested rule is installable
90-
if (!installableRuleIds.has(rule.rule_id)) {
91-
ruleErrors.push({
92-
error: new Error(
93-
`Rule with ID "${rule.rule_id}" and version "${rule.version}" not found`
94-
),
95-
item: rule,
96-
});
97-
return;
98-
}
99-
100-
ruleInstallQueue.push(rule);
101-
});
102-
} else if (mode === 'ALL_RULES') {
103-
const allLatestVersions = await ruleAssetsClient.fetchLatestVersions();
104-
const currentRuleVersions = await ruleObjectsClient.fetchInstalledRuleVersions();
105-
const currentRuleVersionsMap = new Map(
106-
currentRuleVersions.map((version) => [version.rule_id, version])
107-
);
108-
const allInstallableRules = allLatestVersions.filter(
109-
(latestVersion) => !currentRuleVersionsMap.has(latestVersion.rule_id)
110-
);
111-
ruleInstallQueue.push(...(await excludeLicenseRestrictedRules(allInstallableRules, mlAuthz)));
112-
}
113-
114-
const changeTracking = {
115-
metadata: {
116-
bulkCount: ruleInstallQueue.length,
117-
},
118-
};
119-
120-
while (ruleInstallQueue.length > 0) {
121-
const rulesToInstall = ruleInstallQueue.splice(0, PREBUILT_RULE_BATCH_SIZE);
122-
const { assets: ruleAssets } = await ruleAssetsClient.fetchAssetsByVersion(rulesToInstall);
123-
124-
const { results, errors } = await createPrebuiltRules(
125-
detectionRulesClient,
126-
ruleAssets,
127-
changeTracking,
128-
logger
129-
);
130-
131-
const batchInstalledRules = results.map(({ result: rule }) =>
132-
pick(rule, ['id', 'rule_id', 'version'])
133-
);
134-
135-
installedRules.push(...batchInstalledRules);
136-
ruleErrors.push(...errors);
137-
}
45+
const { installedRules, skippedRules, errors } =
46+
mode === 'SPECIFIC_RULES'
47+
? await detectionRulesClient.installPrebuiltRules({ ruleSpecifiers: request.body.rules })
48+
: await detectionRulesClient.installAllPrebuiltRules();
13849

13950
const { error: timelineInstallationError } = await performTimelinesInstallation(
14051
ctx.securitySolution
14152
);
14253

143-
const allErrors = aggregatePrebuiltRuleErrors(ruleErrors);
54+
const allErrors = aggregatePrebuiltRuleErrors(errors);
14455
if (timelineInstallationError) {
14556
allErrors.push({
14657
message: timelineInstallationError,
@@ -150,10 +61,10 @@ export const performRuleInstallationHandler = async (
15061

15162
const body: PerformRuleInstallationResponseBody = {
15263
summary: {
153-
total: installedRules.length + skippedRules.length + ruleErrors.length,
64+
total: installedRules.length + skippedRules.length + errors.length,
15465
succeeded: installedRules.length,
15566
skipped: skippedRules.length,
156-
failed: ruleErrors.length,
67+
failed: errors.length,
15768
},
15869
results: {
15970
created: installedRules,

0 commit comments

Comments
 (0)