diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts index 0561c826e0c78..984b93b66aad2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts @@ -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, }, }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts index 1138a48cc39d4..3d41b7927307d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/prebuilt_rule_objects_client.ts @@ -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; fetchInstalledRulesByIds(ruleIds: string[]): Promise; + fetchInstalledRuleVersions(): Promise>; } 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, + })); + }); + }, }; };