[Security Solution] Rule status memory usage optimizations backport (#214160)

## Summary

Backport the prebuilt rule status endpoint optimizations that were
implemented in https://github.com/elastic/kibana/pull/211045
This commit is contained in:
Dmitrii Shevchenko 2025-03-13 09:34:45 +01:00 committed by GitHub
parent afc2087ec9
commit e6c8b2141a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 11 deletions

View file

@ -12,8 +12,6 @@ import type { SecuritySolutionPluginRouter } from '../../../../../types';
import { buildSiemResponse } from '../../../routes/utils';
import { createPrebuiltRuleAssetsClient } from '../../logic/rule_assets/prebuilt_rule_assets_client';
import { createPrebuiltRuleObjectsClient } from '../../logic/rule_objects/prebuilt_rule_objects_client';
import { fetchRuleVersionsTriad } from '../../logic/rule_versions/fetch_rule_versions_triad';
import { getRuleGroups } from '../../model/rule_groups/get_rule_groups';
export const getPrebuiltRulesStatusRoute = (router: SecuritySolutionPluginRouter) => {
router.versioned
@ -37,23 +35,32 @@ export const getPrebuiltRulesStatusRoute = (router: SecuritySolutionPluginRouter
try {
const ctx = await context.resolve(['core', 'alerting']);
const soClient = ctx.core.savedObjects.client;
const rulesClient = ctx.alerting.getRulesClient();
const rulesClient = await ctx.alerting.getRulesClient();
const ruleAssetsClient = createPrebuiltRuleAssetsClient(soClient);
const ruleObjectsClient = createPrebuiltRuleObjectsClient(rulesClient);
const ruleVersionsMap = await fetchRuleVersionsTriad({
ruleAssetsClient,
ruleObjectsClient,
const currentRuleVersions = await ruleObjectsClient.fetchInstalledRuleVersions();
const latestRuleVersions = await ruleAssetsClient.fetchLatestVersions();
const currentRuleVersionsMap = new Map(
currentRuleVersions.map((rule) => [rule.rule_id, rule])
);
const latestRuleVersionsMap = new Map(
latestRuleVersions.map((rule) => [rule.rule_id, rule])
);
const installableRules = latestRuleVersions.filter(
(rule) => !currentRuleVersionsMap.has(rule.rule_id)
);
const upgradeableRules = currentRuleVersions.filter((rule) => {
const latestVersion = latestRuleVersionsMap.get(rule.rule_id);
return latestVersion != null && rule.version < latestVersion.version;
});
const { currentRules, installableRules, upgradeableRules, totalAvailableRules } =
getRuleGroups(ruleVersionsMap);
const body: GetPrebuiltRulesStatusResponseBody = {
stats: {
num_prebuilt_rules_installed: currentRules.length,
num_prebuilt_rules_installed: currentRuleVersions.length,
num_prebuilt_rules_to_install: installableRules.length,
num_prebuilt_rules_to_upgrade: upgradeableRules.length,
num_prebuilt_rules_total_in_package: totalAvailableRules.length,
num_prebuilt_rules_total_in_package: latestRuleVersions.length,
},
};

View file

@ -9,15 +9,22 @@ import type { RulesClient } from '@kbn/alerting-plugin/server';
import type {
RuleResponse,
RuleSignatureId,
RuleTagArray,
} from '../../../../../../common/api/detection_engine/model/rule_schema';
import { withSecuritySpan } from '../../../../../utils/with_security_span';
import { findRules } from '../../../rule_management/logic/search/find_rules';
import { getExistingPrepackagedRules } from '../../../rule_management/logic/search/get_existing_prepackaged_rules';
import {
MAX_PREBUILT_RULES_COUNT,
getExistingPrepackagedRules,
} from '../../../rule_management/logic/search/get_existing_prepackaged_rules';
import { internalRuleToAPIResponse } from '../../../rule_management/logic/detection_rules_client/converters/internal_rule_to_api_response';
import { convertRulesFilterToKQL } from '../../../../../../common/detection_engine/rule_management/rule_filtering';
import type { RuleVersionSpecifier } from '../rule_versions/rule_version_specifier';
export interface IPrebuiltRuleObjectsClient {
fetchAllInstalledRules(): Promise<RuleResponse[]>;
fetchInstalledRulesByIds(ruleIds: string[]): Promise<RuleResponse[]>;
fetchInstalledRuleVersions(): Promise<Array<RuleVersionSpecifier & { tags: RuleTagArray }>>;
}
export const createPrebuiltRuleObjectsClient = (
@ -47,5 +54,27 @@ export const createPrebuiltRuleObjectsClient = (
return rules;
});
},
fetchInstalledRuleVersions: () => {
return withSecuritySpan('IPrebuiltRuleObjectsClient.fetchInstalledRuleVersions', async () => {
const filterKQL = convertRulesFilterToKQL({
showElasticRules: true,
});
const rulesData = await findRules({
rulesClient,
filter: filterKQL,
perPage: MAX_PREBUILT_RULES_COUNT,
page: 1,
sortField: undefined,
sortOrder: undefined,
fields: ['params.ruleId', 'params.version', 'tags'],
});
return rulesData.data.map((rule) => ({
rule_id: rule.params.ruleId,
version: rule.params.version,
tags: rule.tags,
}));
});
},
};
};